/*
 * 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
 * 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.*;
import java.text.spi.DateFormatProvider;
import java.text.spi.DateFormatSymbolsProvider;
import java.text.spi.DecimalFormatSymbolsProvider;
import java.text.spi.NumberFormatProvider;
import java.util.Collections;
import java.util.Calendar;
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 java.util.spi.TimeZoneNameProvider;
import sun.util.spi.CalendarProvider;

/**
 * LocaleProviderAdapter implementation for the Mac OS X locale data
 *
 * @author Naoto Sato
 */
public class HostLocaleProviderAdapterImpl {

    // per supported locale instances
    private static ConcurrentMap<Locale, SoftReference<AtomicReferenceArray<String>>> dateFormatPatternsMap =
        new ConcurrentHashMap<>(2);
    private static ConcurrentMap<Locale, SoftReference<AtomicReferenceArray<String>>> numberFormatPatternsMap =
        new ConcurrentHashMap<>(2);
    private static ConcurrentMap<Locale, SoftReference<DateFormatSymbols>> dateFormatSymbolsMap =
        new ConcurrentHashMap<>(2);
    private static ConcurrentMap<Locale, SoftReference<DecimalFormatSymbols>> decimalFormatSymbolsMap =
        new ConcurrentHashMap<>(2);

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

    // Locale/Currency display name types
    private static final int DN_LOCALE_LANGUAGE = 0;
    private static final int DN_LOCALE_SCRIPT   = 1;
    private static final int DN_LOCALE_REGION   = 2;
    private static final int DN_LOCALE_VARIANT  = 3;
    private static final int DN_CURRENCY_CODE   = 4;
    private static final int DN_CURRENCY_SYMBOL = 5;

    // TimeZone display name types
    private static final int DN_TZ_SHORT_STANDARD = 0;
    private static final int DN_TZ_SHORT_DST      = 1;
    private static final int DN_TZ_LONG_STANDARD  = 2;
    private static final int DN_TZ_LONG_DST       = 3;

    private static final Set<Locale> supportedLocaleSet;
    static {
        Set<Locale> tmpSet = new HashSet<>();
        // Assuming the default locales do not include any extensions, so
        // no stripping is needed here.
        Locale l = convertMacOSXLocaleToJavaLocale(getDefaultLocale(CAT_FORMAT));
        tmpSet.addAll(Control.getNoFallbackControl(Control.FORMAT_DEFAULT).getCandidateLocales("", l));
        l = convertMacOSXLocaleToJavaLocale(getDefaultLocale(CAT_DISPLAY));
        tmpSet.addAll(Control.getNoFallbackControl(Control.FORMAT_DEFAULT).getCandidateLocales("", l));
        supportedLocaleSet = Collections.unmodifiableSet(tmpSet);
    }
    private final static Locale[] supportedLocale = supportedLocaleSet.toArray(new Locale[0]);

    @SuppressWarnings("fallthrough")
    private static Locale convertMacOSXLocaleToJavaLocale(String macosxloc) {
        // MacOSX may return ICU notation, here is the quote from CFLocale doc:
        // "The corresponding value is a CFString containing the POSIX locale
        // identifier as used by ICU, such as "ja_JP". If you have a variant
        // locale or a different currency or calendar, it can be as complex as
        // "en_US_POSIX@calendar=japanese;currency=EUR" or
        // "az_Cyrl_AZ@calendar=buddhist;currency=JPY".
        String[] tmp = macosxloc.split("@");
        String langTag = tmp[0].replace('_', '-');
        if (tmp.length > 1) {
            String[] ext = tmp[1].split(";");
            for (String keyval : ext) {
                // We are only interested in "calendar" value for now.
                if (keyval.startsWith("calendar=")) {
                    String calid = keyval.substring(keyval.indexOf('=')+1);
                    switch (calid) {
                        case "gregorian":
                            langTag += "-u-ca-gregory";
                            break;
                        case "japanese":
                            // Tweak for ja_JP_JP
                            if (tmp[0].equals("ja_JP")) {
                                return JRELocaleConstants.JA_JP_JP;
                            }

                            // fall through

                        default:
                            langTag += "-u-ca-" + calid;
                            break;
                    }
                }
            }
        }

        return Locale.forLanguageTag(langTag);
    }

    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) {
                return new SimpleDateFormat(getDateTimePattern(style, -1, locale),
                                            getCalendarLocale(locale));
            }

            @Override
            public DateFormat getTimeInstance(int style, Locale locale) {
                return new SimpleDateFormat(getDateTimePattern(-1, style, locale),
                                            getCalendarLocale(locale));
            }

            @Override
            public DateFormat getDateTimeInstance(int dateStyle,
                    int timeStyle, Locale locale) {
                return new SimpleDateFormat(getDateTimePattern(dateStyle, timeStyle, locale),
                                            getCalendarLocale(locale));
            }

            private String getDateTimePattern(int dateStyle, int timeStyle, Locale locale) {
                AtomicReferenceArray<String> dateFormatPatterns;
                SoftReference<AtomicReferenceArray<String>> ref = dateFormatPatternsMap.get(locale);

                if (ref == null || (dateFormatPatterns = ref.get()) == null) {
                    dateFormatPatterns = new AtomicReferenceArray<>(5 * 5);
                    ref = new SoftReference<>(dateFormatPatterns);
                    dateFormatPatternsMap.put(locale, ref);
                }

                int index = (dateStyle + 1) * 5 + timeStyle + 1;
                String pattern = dateFormatPatterns.get(index);
                if (pattern == null) {
                    String langTag = locale.toLanguageTag();
                    pattern = translateDateFormatLetters(getCalendarID(langTag),
                            getDateTimePatternNative(dateStyle, timeStyle, langTag));
                    if (!dateFormatPatterns.compareAndSet(index, null, pattern)) {
                        pattern = dateFormatPatterns.get(index);
                    }
                }

                return pattern;
            }
        };
    }

    public static DateFormatSymbolsProvider getDateFormatSymbolsProvider() {
        return new DateFormatSymbolsProvider() {
            @Override
            public Locale[] getAvailableLocales() {
                if (isSupportedLocale(Locale.getDefault(Locale.Category.FORMAT))) {
                    return supportedLocale;
                }
                return new Locale[0];
            }

            @Override
            public boolean isSupportedLocale(Locale locale) {
                // Only supports the locale with Gregorian calendar
                Locale base = locale.stripExtensions();
                if (supportedLocaleSet.contains(base)) {
                    return getCalendarID(locale.toLanguageTag()).equals("gregorian");
                }
                return false;
            }

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

                if (ref == null || (dateFormatSymbols = ref.get()) == null) {
                    dateFormatSymbols = new DateFormatSymbols(locale);
                    String langTag = locale.toLanguageTag();
                    dateFormatSymbols.setAmPmStrings(getAmPmStrings(langTag, dateFormatSymbols.getAmPmStrings()));
                    dateFormatSymbols.setEras(getEras(langTag, dateFormatSymbols.getEras()));
                    dateFormatSymbols.setMonths(getMonths(langTag, dateFormatSymbols.getMonths()));
                    dateFormatSymbols.setShortMonths(getShortMonths(langTag, dateFormatSymbols.getShortMonths()));
                    dateFormatSymbols.setWeekdays(getWeekdays(langTag, dateFormatSymbols.getWeekdays()));
                    dateFormatSymbols.setShortWeekdays(getShortWeekdays(langTag, dateFormatSymbols.getShortWeekdays()));
                    ref = new SoftReference<>(dateFormatSymbols);
                    dateFormatSymbolsMap.put(locale, ref);
                }
                return (DateFormatSymbols)dateFormatSymbols.clone();
            }
        };
    }

    public static NumberFormatProvider getNumberFormatProvider() {
        return new NumberFormatProvider() {
            @Override
            public Locale[] getAvailableLocales() {
                return supportedLocale;
            }

            @Override
            public boolean isSupportedLocale(Locale locale) {
                // Ignore the extensions for now
                return supportedLocaleSet.contains(locale.stripExtensions());
            }

            @Override
            public NumberFormat getCurrencyInstance(Locale locale) {
                return new DecimalFormat(getNumberPattern(NF_CURRENCY, locale),
                    DecimalFormatSymbols.getInstance(locale));
            }

            @Override
            public NumberFormat getIntegerInstance(Locale locale) {
                return new DecimalFormat(getNumberPattern(NF_INTEGER, locale),
                    DecimalFormatSymbols.getInstance(locale));
            }

            @Override
            public NumberFormat getNumberInstance(Locale locale) {
                return new DecimalFormat(getNumberPattern(NF_NUMBER, locale),
                    DecimalFormatSymbols.getInstance(locale));
            }

            @Override
            public NumberFormat getPercentInstance(Locale locale) {
                return new DecimalFormat(getNumberPattern(NF_PERCENT, locale),
                    DecimalFormatSymbols.getInstance(locale));
            }

            private String getNumberPattern(int style, Locale locale) {
                AtomicReferenceArray<String> numberFormatPatterns;
                SoftReference<AtomicReferenceArray<String>> ref = numberFormatPatternsMap.get(locale);

                if (ref == null || (numberFormatPatterns = ref.get()) == null) {
                    numberFormatPatterns = new AtomicReferenceArray<>(4);
                    ref = new SoftReference<>(numberFormatPatterns);
                    numberFormatPatternsMap.put(locale, ref);
                }

                String pattern = numberFormatPatterns.get(style);
                if (pattern == null) {
                    pattern = getNumberPatternNative(style, locale.toLanguageTag());
                    if (!numberFormatPatterns.compareAndSet(style, null, pattern)) {
                        pattern = numberFormatPatterns.get(style);
                    }
                }

                return pattern;
            }
        };
    }

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

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

            @Override
            public boolean isSupportedLocale(Locale locale) {
                // Ignore the extensions for now
                return supportedLocaleSet.contains(locale.stripExtensions());
            }

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

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

                    // DecimalFormatSymbols.setInternationalCurrencySymbol() has
                    // a side effect of setting the currency symbol as well. So
                    // the calling order is relevant here.
                    decimalFormatSymbols.setInternationalCurrencySymbol(getInternationalCurrencySymbol(langTag, decimalFormatSymbols.getInternationalCurrencySymbol()));
                    decimalFormatSymbols.setCurrencySymbol(getCurrencySymbol(langTag, decimalFormatSymbols.getCurrencySymbol()));
                    decimalFormatSymbols.setDecimalSeparator(getDecimalSeparator(langTag, decimalFormatSymbols.getDecimalSeparator()));
                    decimalFormatSymbols.setGroupingSeparator(getGroupingSeparator(langTag, decimalFormatSymbols.getGroupingSeparator()));
                    decimalFormatSymbols.setInfinity(getInfinity(langTag, decimalFormatSymbols.getInfinity()));
                    decimalFormatSymbols.setMinusSign(getMinusSign(langTag, decimalFormatSymbols.getMinusSign()));
                    decimalFormatSymbols.setMonetaryDecimalSeparator(getMonetaryDecimalSeparator(langTag, decimalFormatSymbols.getMonetaryDecimalSeparator()));
                    decimalFormatSymbols.setNaN(getNaN(langTag, decimalFormatSymbols.getNaN()));
                    decimalFormatSymbols.setPercent(getPercent(langTag, decimalFormatSymbols.getPercent()));
                    decimalFormatSymbols.setPerMill(getPerMill(langTag, decimalFormatSymbols.getPerMill()));
                    decimalFormatSymbols.setZeroDigit(getZeroDigit(langTag, decimalFormatSymbols.getZeroDigit()));
                    decimalFormatSymbols.setExponentSeparator(getExponentSeparator(langTag, decimalFormatSymbols.getExponentSeparator()));
                    ref = new SoftReference<>(decimalFormatSymbols);
                    decimalFormatSymbolsMap.put(locale, ref);
                }
                return (DecimalFormatSymbols)decimalFormatSymbols.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) {
                return getCalendarInt(locale.toLanguageTag(), CD_FIRSTDAYOFWEEK);
            }

            @Override
            public int getMinimalDaysInFirstWeek(Locale locale) {
                return getCalendarInt(locale.toLanguageTag(), CD_MINIMALDAYSINFIRSTWEEK);
            }
        };
    }

    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 calType, int field, int value,
                                         int style, Locale locale) {
                return null;
            }

            @Override
            public Map<String, Integer> getDisplayNames(String calType,
                                         int field, int style, Locale locale) {
                return null;
            }
        };
    }

    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(locale)
                             .setCalendarType(getCalendarID(locale.toLanguageTag()))
                             .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());
            }

            @Override
            public String getDisplayName(String code, Locale locale) {
                return getDisplayString(locale.toLanguageTag(), DN_CURRENCY_CODE, code);
            }

            @Override
            public String getSymbol(String code, Locale locale) {
                return getDisplayString(locale.toLanguageTag(), DN_CURRENCY_SYMBOL, code);
            }
        };
    }

    public static LocaleNameProvider getLocaleNameProvider() {
        return new LocaleNameProvider() {
            @Override
            public Locale[] getAvailableLocales() {
                return supportedLocale;
            }

            @Override
            public boolean isSupportedLocale(Locale locale) {
                // Ignore the extensions for now
                return supportedLocaleSet.contains(locale.stripExtensions());
            }

            @Override
            public String getDisplayLanguage(String languageCode, Locale locale) {
                return getDisplayString(locale.toLanguageTag(), DN_LOCALE_LANGUAGE, languageCode);
            }

            @Override
            public String getDisplayCountry(String countryCode, Locale locale) {
                return getDisplayString(locale.toLanguageTag(), DN_LOCALE_REGION, countryCode);
            }

            @Override
            public String getDisplayScript(String scriptCode, Locale locale) {
                return getDisplayString(locale.toLanguageTag(), DN_LOCALE_SCRIPT, scriptCode);
            }

            @Override
            public String getDisplayVariant(String variantCode, Locale locale) {
                return getDisplayString(locale.toLanguageTag(), DN_LOCALE_VARIANT, variantCode);
            }
        };
    }

    public static TimeZoneNameProvider getTimeZoneNameProvider() {
        return new TimeZoneNameProvider() {
            @Override
            public Locale[] getAvailableLocales() {
                return supportedLocale;
            }

            @Override
            public boolean isSupportedLocale(Locale locale) {
                // Ignore the extensions for now
                return supportedLocaleSet.contains(locale.stripExtensions());
            }

            @Override
            public String getDisplayName(String ID, boolean daylight, int style, Locale locale) {
                return getTimeZoneDisplayString(locale.toLanguageTag(), style * 2 + (daylight ? 1 : 0), ID);
            }
        };
    }

    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 = locale;

        if (base.hasExtensions() || base.getVariant() != "") {
            base = new Locale.Builder()
                            .setLocale(locale)
                            .clearExtensions()
                            .build();
        }

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

        String requestedCalType = locale.getUnicodeLocaleType("ca");
        String nativeCalType =
            getCalendarID(base.toLanguageTag()).replaceFirst("gregorian", "gregory");

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

    private static boolean isJapaneseCalendar() {
        return getCalendarID("ja-JP").equals("japanese");
    }

    private static Locale getCalendarLocale(Locale locale) {
        String nativeCalType = getCalendarID(locale.toLanguageTag())
                     .replaceFirst("gregorian", "gregory");
        if (Calendar.getAvailableCalendarTypes().contains(nativeCalType)) {
            return new Locale.Builder()
                           .setLocale(locale)
                           .setUnicodeLocaleKeyword("ca", nativeCalType)
                           .build();
        } else {
            return locale;
        }
    }

    // The following methods are copied from CLDRConverter build tool.
    private static String translateDateFormatLetters(String calendarType, String cldrFormat) {
        String pattern = cldrFormat;
        int length = pattern.length();
        boolean inQuote = false;
        StringBuilder jrePattern = new StringBuilder(length);
        int count = 0;
        char lastLetter = 0;

        for (int i = 0; i < length; i++) {
            char c = pattern.charAt(i);

            if (c == '\'') {
                // '' is treated as a single quote regardless of being
                // in a quoted section.
                if ((i + 1) < length) {
                    char nextc = pattern.charAt(i + 1);
                    if (nextc == '\'') {
                        i++;
                        if (count != 0) {
                            convert(calendarType, lastLetter, count, jrePattern);
                            lastLetter = 0;
                            count = 0;
                        }
                        jrePattern.append("''");
                        continue;
                    }
                }
                if (!inQuote) {
                    if (count != 0) {
                        convert(calendarType, lastLetter, count, jrePattern);
                        lastLetter = 0;
                        count = 0;
                    }
                    inQuote = true;
                } else {
                    inQuote = false;
                }
                jrePattern.append(c);
                continue;
            }
            if (inQuote) {
                jrePattern.append(c);
                continue;
            }
            if (!(c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z')) {
                if (count != 0) {
                    convert(calendarType, lastLetter, count, jrePattern);
                    lastLetter = 0;
                    count = 0;
                }
                jrePattern.append(c);
                continue;
            }

            if (lastLetter == 0 || lastLetter == c) {
                lastLetter = c;
                count++;
                continue;
            }
            convert(calendarType, lastLetter, count, jrePattern);
            lastLetter = c;
            count = 1;
        }

        if (count != 0) {
            convert(calendarType, lastLetter, count, jrePattern);
        }
        if (cldrFormat.contentEquals(jrePattern)) {
            return cldrFormat;
        }
        return jrePattern.toString();
    }

    private static void convert(String calendarType, char cldrLetter, int count, StringBuilder sb) {
        switch (cldrLetter) {
        case 'G':
            if (!calendarType.equals("gregorian")) {
                // Adjust the number of 'G's for JRE SimpleDateFormat
                if (count == 5) {
                    // CLDR narrow -> JRE short
                    count = 1;
                } else if (count == 1) {
                    // CLDR abbr -> JRE long
                    count = 4;
                }
            }
            appendN(cldrLetter, count, sb);
            break;

        // TODO: support 'c' and 'e' in JRE SimpleDateFormat
        // Use 'u' and 'E' for now.
        case 'c':
        case 'e':
            switch (count) {
            case 1:
                sb.append('u');
                break;
            case 3:
            case 4:
                appendN('E', count, sb);
                break;
            case 5:
                appendN('E', 3, sb);
                break;
            }
            break;

        case 'v':
        case 'V':
            appendN('z', count, sb);
            break;

        case 'Z':
            if (count == 4 || count == 5) {
                sb.append("XXX");
            }
            break;

        case 'u':
        case 'U':
        case 'q':
        case 'Q':
        case 'l':
        case 'g':
        case 'j':
        case 'A':
            // Unsupported letter. Just append it within quotes
            sb.append('\'');
            sb.append(cldrLetter);
            sb.append('\'');
            break;

        default:
            appendN(cldrLetter, count, sb);
            break;
        }
    }

    private static void appendN(char c, int n, StringBuilder sb) {
        for (int i = 0; i < n; i++) {
            sb.append(c);
        }
    }

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

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

    // For NumberFormatProvider
    private static native String getNumberPatternNative(int style, 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 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);
    private static native String getExponentSeparator(String langTag, String exponent);

    // For CalendarDataProvider
    private static native int getCalendarInt(String langTag, int type);

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

    // For TimeZoneNameProvider
    private static native String getTimeZoneDisplayString(String langTag, int style, String value);
}
