/*
 * Copyright (c) 2012, 2016, 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
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package sun.util.locale.provider;

import java.lang.ref.SoftReference;
import java.text.DateFormat;
import java.text.DateFormatSymbols;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.text.spi.DateFormatProvider;
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.HashMap;
import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle.Control;
import java.util.Set;
import java.util.TimeZone;
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.
 *
 * @author Naoto Sato
 */
public class HostLocaleProviderAdapterImpl {

    // locale categories
    private static final int CAT_DISPLAY = 0;
    private static final int CAT_FORMAT  = 1;

    // NumberFormat styles
    private static final int NF_NUMBER   = 0;
    private static final int NF_CURRENCY = 1;
    private static final int NF_PERCENT  = 2;
    private static final int NF_INTEGER  = 3;
    private static final int NF_MAX = NF_INTEGER;

    // 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;

    // Windows Calendar IDs
    private static final int CAL_JAPAN  = 3;

    // Native Calendar ID to LDML calendar type map
    private static final String[] calIDToLDML = {
        "",
        "gregory",
        "gregory_en-US",
        "japanese",
        "roc",
        "",          // No appropriate type for CAL_KOREA
        "islamic",
        "buddhist",
        "hebrew",
        "gregory_fr",
        "gregory_ar",
        "gregory_en",
        "gregory_fr", "", "", "", "", "", "", "", "", "", "",
        "islamic-umalqura",
    };

    // Caches
    private static final ConcurrentMap<Locale, SoftReference<AtomicReferenceArray<String>>> dateFormatCache = new ConcurrentHashMap<>();
    private static final ConcurrentMap<Locale, SoftReference<DateFormatSymbols>> dateFormatSymbolsCache = new ConcurrentHashMap<>();
    private static final ConcurrentMap<Locale, SoftReference<AtomicReferenceArray<String>>> numberFormatCache = new ConcurrentHashMap<>();
    private static final 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.
            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 static final Locale[] supportedLocale = supportedLocaleSet.toArray(new Locale[0]);

    public static DateFormatProvider getDateFormatProvider() {
        return new DateFormatProvider() {
            @Override
            public Locale[] getAvailableLocales() {
                return getSupportedCalendarLocales();
            }

            @Override
            public boolean isSupportedLocale(Locale locale) {
                return isSupportedCalendarLocale(locale);
            }

            @Override
            public DateFormat getDateInstance(int style, Locale locale) {
                AtomicReferenceArray<String> patterns = getDateTimePatterns(locale);
                return new SimpleDateFormat(patterns.get(style/2),
                                            getCalendarLocale(locale));
            }

            @Override
            public DateFormat getTimeInstance(int style, Locale locale) {
                AtomicReferenceArray<String> patterns = getDateTimePatterns(locale);
                return new SimpleDateFormat(patterns.get(style/2+2),
                                            getCalendarLocale(locale));
            }

            @Override
            public DateFormat getDateTimeInstance(int dateStyle,
                    int timeStyle, Locale locale) {
                AtomicReferenceArray<String> patterns = getDateTimePatterns(locale);
                String pattern = new StringBuilder(patterns.get(dateStyle/2))
                                       .append(" ")
                                       .append(patterns.get(timeStyle/2+2))
                                       .toString();
                return new SimpleDateFormat(pattern, getCalendarLocale(locale));
            }

            private AtomicReferenceArray<String> getDateTimePatterns(Locale locale) {
                AtomicReferenceArray<String> patterns;
                SoftReference<AtomicReferenceArray<String>> ref = dateFormatCache.get(locale);

                if (ref == null || (patterns = ref.get()) == null) {
                    String langtag = removeExtensions(locale).toLanguageTag();
                    patterns = new AtomicReferenceArray<>(4);
                    patterns.compareAndSet(0, null, convertDateTimePattern(
                        getDateTimePattern(DateFormat.LONG, -1, langtag)));
                    patterns.compareAndSet(1, null, convertDateTimePattern(
                        getDateTimePattern(DateFormat.SHORT, -1, langtag)));
                    patterns.compareAndSet(2, null, convertDateTimePattern(
                        getDateTimePattern(-1, DateFormat.LONG, langtag)));
                    patterns.compareAndSet(3, null, convertDateTimePattern(
                        getDateTimePattern(-1, DateFormat.SHORT, langtag)));
                    ref = new SoftReference<>(patterns);
                    dateFormatCache.put(locale, ref);
                }

                return patterns;
            }
        };
    }

    public static DateFormatSymbolsProvider getDateFormatSymbolsProvider() {
        return new DateFormatSymbolsProvider() {

            @Override
            public Locale[] getAvailableLocales() {
                return getSupportedCalendarLocales();
            }

            @Override
            public boolean isSupportedLocale(Locale locale) {
                return isSupportedCalendarLocale(locale);
            }

            @Override
            public DateFormatSymbols getInstance(Locale locale) {
                DateFormatSymbols dfs;
                SoftReference<DateFormatSymbols> ref =
                    dateFormatSymbolsCache.get(locale);

                if (ref == null || (dfs = ref.get()) == null) {
                    dfs = new DateFormatSymbols(locale);
                    String langTag = removeExtensions(locale).toLanguageTag();

                    dfs.setAmPmStrings(getAmPmStrings(langTag, dfs.getAmPmStrings()));
                    dfs.setEras(getEras(langTag, dfs.getEras()));
                    dfs.setMonths(getMonths(langTag, dfs.getMonths()));
                    dfs.setShortMonths(getShortMonths(langTag, dfs.getShortMonths()));
                    dfs.setWeekdays(getWeekdays(langTag, dfs.getWeekdays()));
                    dfs.setShortWeekdays(getShortWeekdays(langTag, dfs.getShortWeekdays()));
                    ref = new SoftReference<>(dfs);
                    dateFormatSymbolsCache.put(locale, ref);
                }
                return (DateFormatSymbols)dfs.clone();
            }
        };
    }

    public static NumberFormatProvider getNumberFormatProvider() {
        return new NumberFormatProvider() {

            @Override
            public Locale[] getAvailableLocales() {
                return getSupportedNativeDigitLocales();
            }

            @Override
            public boolean isSupportedLocale(Locale locale) {
                return isSupportedNativeDigitLocale(locale);
            }

            @Override
            public NumberFormat getCurrencyInstance(Locale locale) {
                AtomicReferenceArray<String> patterns = getNumberPatterns(locale);
                return new DecimalFormat(patterns.get(NF_CURRENCY),
                    DecimalFormatSymbols.getInstance(locale));
            }

            @Override
            public NumberFormat getIntegerInstance(Locale locale) {
                AtomicReferenceArray<String> patterns = getNumberPatterns(locale);
                return new DecimalFormat(patterns.get(NF_INTEGER),
                    DecimalFormatSymbols.getInstance(locale));
            }

            @Override
            public NumberFormat getNumberInstance(Locale locale) {
                AtomicReferenceArray<String> patterns = getNumberPatterns(locale);
                return new DecimalFormat(patterns.get(NF_NUMBER),
                    DecimalFormatSymbols.getInstance(locale));
            }

            @Override
            public NumberFormat getPercentInstance(Locale locale) {
                AtomicReferenceArray<String> patterns = getNumberPatterns(locale);
                return new DecimalFormat(patterns.get(NF_PERCENT),
                    DecimalFormatSymbols.getInstance(locale));
            }

            private AtomicReferenceArray<String> getNumberPatterns(Locale locale) {
                AtomicReferenceArray<String> patterns;
                SoftReference<AtomicReferenceArray<String>> ref = numberFormatCache.get(locale);

                if (ref == null || (patterns = ref.get()) == null) {
                    String langtag = locale.toLanguageTag();
                    patterns = new AtomicReferenceArray<>(NF_MAX+1);
                    for (int i = 0; i <= NF_MAX; i++) {
                        patterns.compareAndSet(i, null, getNumberPattern(i, langtag));
                    }
                    ref = new SoftReference<>(patterns);
                    numberFormatCache.put(locale, ref);
                }
                return patterns;
            }
        };
    }

    public static DecimalFormatSymbolsProvider getDecimalFormatSymbolsProvider() {
        return new DecimalFormatSymbolsProvider() {

            @Override
            public Locale[] getAvailableLocales() {
                return getSupportedNativeDigitLocales();
            }

            @Override
            public boolean isSupportedLocale(Locale locale) {
                return isSupportedNativeDigitLocale(locale);
            }

            @Override
            public DecimalFormatSymbols getInstance(Locale locale) {
                DecimalFormatSymbols dfs;
                SoftReference<DecimalFormatSymbols> ref =
                    decimalFormatSymbolsCache.get(locale);

                if (ref == null || (dfs = ref.get()) == null) {
                    dfs = new DecimalFormatSymbols(getNumberLocale(locale));
                    String langTag = removeExtensions(locale).toLanguageTag();

                    // DecimalFormatSymbols.setInternationalCurrencySymbol() has
                    // a side effect of setting the currency symbol as well. So
                    // the calling order is relevant here.
                    dfs.setInternationalCurrencySymbol(getInternationalCurrencySymbol(langTag, dfs.getInternationalCurrencySymbol()));
                    dfs.setCurrencySymbol(getCurrencySymbol(langTag, dfs.getCurrencySymbol()));
                    dfs.setDecimalSeparator(getDecimalSeparator(langTag, dfs.getDecimalSeparator()));
                    dfs.setGroupingSeparator(getGroupingSeparator(langTag, dfs.getGroupingSeparator()));
                    dfs.setInfinity(getInfinity(langTag, dfs.getInfinity()));
                    dfs.setMinusSign(getMinusSign(langTag, dfs.getMinusSign()));
                    dfs.setMonetaryDecimalSeparator(getMonetaryDecimalSeparator(langTag, dfs.getMonetaryDecimalSeparator()));
                    dfs.setNaN(getNaN(langTag, dfs.getNaN()));
                    dfs.setPercent(getPercent(langTag, dfs.getPercent()));
                    dfs.setPerMill(getPerMill(langTag, dfs.getPerMill()));
                    dfs.setZeroDigit(getZeroDigit(langTag, dfs.getZeroDigit()));
                    ref = new SoftReference<>(dfs);
                    decimalFormatSymbolsCache.put(locale, ref);
                }
                return (DecimalFormatSymbols)dfs.clone();
            }
        };
    }

    public static CalendarDataProvider getCalendarDataProvider() {
        return new CalendarDataProvider() {
            @Override
            public Locale[] getAvailableLocales() {
                return getSupportedCalendarLocales();
            }

            @Override
            public boolean isSupportedLocale(Locale locale) {
                return isSupportedCalendarLocale(locale);
            }

            @Override
            public int getFirstDayOfWeek(Locale locale) {
                int first = getCalendarDataValue(
                                 removeExtensions(locale).toLanguageTag(),
                                 CD_FIRSTDAYOFWEEK);
                if (first != -1) {
                    return (first + 1) % 7 + 1;
                } else {
                    return 0;
                }
            }

            @Override
            public int getMinimalDaysInFirstWeek(Locale locale) {
                return 0;
            }
        };
    }

    public static CalendarNameProvider getCalendarNameProvider() {
        return new CalendarNameProvider() {
            @Override
            public Locale[] getAvailableLocales() {
                return getSupportedCalendarLocales();
            }

            @Override
            public boolean isSupportedLocale(Locale locale) {
                return isSupportedCalendarLocale(locale);
            }

            @Override
            public String getDisplayName(String calendarType, int field,
                int value, int style, Locale locale) {
                String[] names = getCalendarDisplayStrings(removeExtensions(locale).toLanguageTag(),
                            getCalendarIDFromLDMLType(calendarType), field, style);
                if (names != null && value >= 0 && value < names.length) {
                    return names[value];
                } else {
                    return null;
                }
            }

            @Override
            public Map<String, Integer> getDisplayNames(String calendarType,
                int field, int style, Locale locale) {
                Map<String, Integer> map = null;
                String[] names = getCalendarDisplayStrings(removeExtensions(locale).toLanguageTag(),
                            getCalendarIDFromLDMLType(calendarType), field, style);
                if (names != null) {
                    map = new HashMap<>();
                    for (int value = 0; value < names.length; value++) {
                        if (names[value] != null) {
                            map.put(names[value], value);
                        }
                    }
                    map = map.isEmpty() ? null : map;
                }
                return map;
            }
        };
    }

    public static CalendarProvider getCalendarProvider() {
        return new CalendarProvider() {
            @Override
            public Locale[] getAvailableLocales() {
                return getSupportedCalendarLocales();
            }

            @Override
            public boolean isSupportedLocale(Locale locale) {
                return isSupportedCalendarLocale(locale);
            }

            @Override
            public Calendar getInstance(TimeZone zone, Locale locale) {
                return new Calendar.Builder()
                             .setLocale(getCalendarLocale(locale))
                             .setTimeZone(zone)
                             .setInstant(System.currentTimeMillis())
                             .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");
        return ret;
    }

    private static Locale[] getSupportedCalendarLocales() {
        if (supportedLocale.length != 0 &&
            supportedLocaleSet.contains(Locale.JAPAN) &&
            isJapaneseCalendar()) {
            Locale[] sup = new Locale[supportedLocale.length+1];
            sup[0] = JRELocaleConstants.JA_JP_JP;
            System.arraycopy(supportedLocale, 0, sup, 1, supportedLocale.length);
            return sup;
        }
        return supportedLocale;
    }

    private static boolean isSupportedCalendarLocale(Locale locale) {
        Locale base = stripVariantAndExtensions(locale);

        if (!supportedLocaleSet.contains(base)) {
            return false;
        }

        int calid = getCalendarID(base.toLanguageTag());
        if (calid <= 0 || calid >= calIDToLDML.length) {
            return false;
        }

        String requestedCalType = locale.getUnicodeLocaleType("ca");
        String nativeCalType = calIDToLDML[calid]
                .replaceFirst("_.*", ""); // remove locale part.

        if (requestedCalType == null) {
            return Calendar.getAvailableCalendarTypes().contains(nativeCalType);
        } else {
            return requestedCalType.equals(nativeCalType);
        }
    }

    private static Locale[] getSupportedNativeDigitLocales() {
        if (supportedLocale.length != 0 &&
            supportedLocaleSet.contains(JRELocaleConstants.TH_TH) &&
            isNativeDigit("th-TH")) {
            Locale[] sup = new Locale[supportedLocale.length+1];
            sup[0] = JRELocaleConstants.TH_TH_TH;
            System.arraycopy(supportedLocale, 0, sup, 1, supportedLocale.length);
            return sup;
        }
        return supportedLocale;
    }

    private static boolean isSupportedNativeDigitLocale(Locale locale) {
        // special case for th_TH_TH
        if (JRELocaleConstants.TH_TH_TH.equals(locale)) {
            return isNativeDigit("th-TH");
        }

        String numtype = null;
        Locale base = locale;
        if (locale.hasExtensions()) {
            numtype = locale.getUnicodeLocaleType("nu");
            base = locale.stripExtensions();
        }

        if (supportedLocaleSet.contains(base)) {
            // Only supports Latin or Thai (in thai locales) digits.
            if (numtype == null || numtype.equals("latn")) {
                return true;
            } else if (locale.getLanguage().equals("th")) {
                return "thai".equals(numtype) &&
                       isNativeDigit(locale.toLanguageTag());
            }
        }

        return false;
    }

    private static Locale removeExtensions(Locale src) {
        return new Locale.Builder().setLocale(src).clearExtensions().build();
    }

    private static boolean isJapaneseCalendar() {
        return getCalendarID("ja-JP") == CAL_JAPAN;
    }

    private static Locale stripVariantAndExtensions(Locale locale) {
        if (locale.hasExtensions() || locale.getVariant() != "") {
            // strip off extensions and variant.
            locale = new Locale.Builder()
                            .setLocale(locale)
                            .clearExtensions()
                            .build();
        }

        return locale;
    }

    private static Locale getCalendarLocale(Locale locale) {
        int calid = getCalendarID(stripVariantAndExtensions(locale).toLanguageTag());
        if (calid > 0 && calid < calIDToLDML.length) {
            Locale.Builder lb = new Locale.Builder();
            String[] caltype = calIDToLDML[calid].split("_");
            if (caltype.length > 1) {
                lb.setLocale(Locale.forLanguageTag(caltype[1]));
            } else {
                lb.setLocale(locale);
            }
            lb.setUnicodeLocaleKeyword("ca", caltype[0]);
            return lb.build();
        }

        return locale;
    }

    private static int getCalendarIDFromLDMLType(String ldmlType) {
        for (int i = 0; i < calIDToLDML.length; i++) {
            if (calIDToLDML[i].startsWith(ldmlType)) {
                return i;
            }
        }
        return -1;
    }

    private static Locale getNumberLocale(Locale src) {
        if (JRELocaleConstants.TH_TH.equals(src)) {
            if (isNativeDigit("th-TH")) {
                Locale.Builder lb = new Locale.Builder().setLocale(src);
                lb.setUnicodeLocaleKeyword("nu", "thai");
                return lb.build();
            }
        }

        return src;
    }

    // native methods

    // initialize
    private static native boolean initialize();
    private static native String getDefaultLocale(int cat);

    // For DateFormatProvider
    private static native String getDateTimePattern(int dateStyle, int timeStyle, String langTag);
    private static native int getCalendarID(String langTag);

    // For DateFormatSymbolsProvider
    private static native String[] getAmPmStrings(String langTag, String[] ampm);
    private static native String[] getEras(String langTag, String[] eras);
    private static native String[] getMonths(String langTag, String[] months);
    private static native String[] getShortMonths(String langTag, String[] smonths);
    private static native String[] getWeekdays(String langTag, String[] wdays);
    private static native String[] getShortWeekdays(String langTag, String[] swdays);

    // For NumberFormatProvider
    private static native String getNumberPattern(int numberStyle, String langTag);
    private static native boolean isNativeDigit(String langTag);

    // For DecimalFormatSymbolsProvider
    private static native String getCurrencySymbol(String langTag, String currencySymbol);
    private static native char getDecimalSeparator(String langTag, char decimalSeparator);
    private static native char getGroupingSeparator(String langTag, char groupingSeparator);
    private static native String getInfinity(String langTag, String infinity);
    private static native String getInternationalCurrencySymbol(String langTag, String internationalCurrencySymbol);
    private static native char getMinusSign(String langTag, char minusSign);
    private static native char getMonetaryDecimalSeparator(String langTag, char monetaryDecimalSeparator);
    private static native String getNaN(String langTag, String nan);
    private static native char getPercent(String langTag, char percent);
    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 CalendarNameProvider
    private static native String[] getCalendarDisplayStrings(String langTag, int calid, int field, int style);

    // For Locale/CurrencyNameProvider
    private static native String getDisplayString(String langTag, int key, String value);
}
