12ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller/* GENERATED SOURCE. DO NOT MODIFY. */
22ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller/**
32ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller *******************************************************************************
42ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Copyright (C) 2001-2015, International Business Machines Corporation and    *
52ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * others. All Rights Reserved.                                                *
62ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller *******************************************************************************
72ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */
82ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerpackage android.icu.impl;
92ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.util.Collections;
112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.util.Locale;
122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.util.Map;
132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.util.Set;
142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport android.icu.util.ULocale;
162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
171537b2f39245c07b00aa78c3600f7aebcb172490Neil Fuller/**
181537b2f39245c07b00aa78c3600f7aebcb172490Neil Fuller * @hide Only a subset of ICU is exposed in Android
19836e6b40a94ec3fb7545a76cb072960442b7eee9Neil Fuller */
202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerpublic class ICULocaleService extends ICUService {
212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private ULocale fallbackLocale;
222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private String fallbackLocaleName;
232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Construct an ICULocaleService.
262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public ICULocaleService() {
282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Construct an ICULocaleService with a name (useful for debugging).
322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public ICULocaleService(String name) {
342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        super(name);
352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Convenience override for callers using locales.  This calls
392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * get(ULocale, int, ULocale[]) with KIND_ANY for kind and null for
402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * actualReturn.
412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public Object get(ULocale locale) {
432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return get(locale, LocaleKey.KIND_ANY, null);
442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Convenience override for callers using locales.  This calls
482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * get(ULocale, int, ULocale[]) with a null actualReturn.
492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public Object get(ULocale locale, int kind) {
512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return get(locale, kind, null);
522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Convenience override for callers using locales.  This calls
562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * get(ULocale, int, ULocale[]) with KIND_ANY for kind.
572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public Object get(ULocale locale, ULocale[] actualReturn) {
592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return get(locale, LocaleKey.KIND_ANY, actualReturn);
602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Convenience override for callers using locales.  This uses
642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * createKey(ULocale.toString(), kind) to create a key, calls getKey, and then
652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * if actualReturn is not null, returns the actualResult from
662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * getKey (stripping any prefix) into a ULocale.
672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public Object get(ULocale locale, int kind, ULocale[] actualReturn) {
692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        Key key = createKey(locale, kind);
702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if (actualReturn == null) {
712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return getKey(key);
722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        String[] temp = new String[1];
752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        Object result = getKey(key, temp);
762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if (result != null) {
772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            int n = temp[0].indexOf("/");
782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if (n >= 0) {
792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                temp[0] = temp[0].substring(n+1);
802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            actualReturn[0] = new ULocale(temp[0]);
822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return result;
842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Convenience override for callers using locales.  This calls
882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * registerObject(Object, ULocale, int kind, boolean visible)
892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * passing KIND_ANY for the kind, and true for the visibility.
902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public Factory registerObject(Object obj, ULocale locale) {
922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return registerObject(obj, locale, LocaleKey.KIND_ANY, true);
932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Convenience override for callers using locales.  This calls
972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * registerObject(Object, ULocale, int kind, boolean visible)
982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * passing KIND_ANY for the kind.
992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
1002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public Factory registerObject(Object obj, ULocale locale, boolean visible) {
1012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return registerObject(obj, locale, LocaleKey.KIND_ANY, visible);
1022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
1052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Convenience function for callers using locales.  This calls
1062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * registerObject(Object, ULocale, int kind, boolean visible)
1072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * passing true for the visibility.
1082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
1092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public Factory registerObject(Object obj, ULocale locale, int kind) {
1102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return registerObject(obj, locale, kind, true);
1112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
1142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Convenience function for callers using locales.  This  instantiates
1152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * a SimpleLocaleKeyFactory, and registers the factory.
1162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
1172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public Factory registerObject(Object obj, ULocale locale, int kind, boolean visible) {
1182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        Factory factory = new SimpleLocaleKeyFactory(obj, locale, kind, visible);
1192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return registerFactory(factory);
1202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
1232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Convenience method for callers using locales.  This returns the standard
1242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Locale list, built from the Set of visible ids.
1252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
1262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public Locale[] getAvailableLocales() {
1272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        // TODO make this wrap getAvailableULocales later
1282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        Set<String> visIDs = getVisibleIDs();
1292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        Locale[] locales = new Locale[visIDs.size()];
1302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int n = 0;
1312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        for (String id : visIDs) {
1322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            Locale loc = LocaleUtility.getLocaleFromName(id);
1332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            locales[n++] = loc;
1342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
1352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return locales;
1362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
1392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Convenience method for callers using locales.  This returns the standard
1402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * ULocale list, built from the Set of visible ids.
1412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
1422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public ULocale[] getAvailableULocales() {
1432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        Set<String> visIDs = getVisibleIDs();
1442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        ULocale[] locales = new ULocale[visIDs.size()];
1452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int n = 0;
1462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        for (String id : visIDs) {
1472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            locales[n++] = new ULocale(id);
1482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
1492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return locales;
1502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
1532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * A subclass of Key that implements a locale fallback mechanism.
1542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * The first locale to search for is the locale provided by the
1552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * client, and the fallback locale to search for is the current
1562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * default locale.  If a prefix is present, the currentDescriptor
1572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * includes it before the locale proper, separated by "/".  This
1582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * is the default key instantiated by ICULocaleService.</p>
1592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *
1602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * <p>Canonicalization adjusts the locale string so that the
1612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * section before the first understore is in lower case, and the rest
1622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * is in upper case, with no trailing underscores.</p>
1632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
1642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static class LocaleKey extends ICUService.Key {
1652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        private int kind;
1662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        private int varstart;
1672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        private String primaryID;
1682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        private String fallbackID;
1692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        private String currentID;
1702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        public static final int KIND_ANY = -1;
1722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /**
1742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * Create a LocaleKey with canonical primary and fallback IDs.
1752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         */
1762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        public static LocaleKey createWithCanonicalFallback(String primaryID, String canonicalFallbackID) {
1772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return createWithCanonicalFallback(primaryID, canonicalFallbackID, KIND_ANY);
1782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
1792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /**
1812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * Create a LocaleKey with canonical primary and fallback IDs.
1822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         */
1832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        public static LocaleKey createWithCanonicalFallback(String primaryID, String canonicalFallbackID, int kind) {
1842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if (primaryID == null) {
1852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                return null;
1862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
1872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            String canonicalPrimaryID = ULocale.getName(primaryID);
1882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return new LocaleKey(primaryID, canonicalPrimaryID, canonicalFallbackID, kind);
1892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
1902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /**
1922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * Create a LocaleKey with canonical primary and fallback IDs.
1932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         */
1942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        public static LocaleKey createWithCanonical(ULocale locale, String canonicalFallbackID, int kind) {
1952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if (locale == null) {
1962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                return null;
1972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
1982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            String canonicalPrimaryID = locale.getName();
1992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return new LocaleKey(canonicalPrimaryID, canonicalPrimaryID, canonicalFallbackID, kind);
2002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
2012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /**
2032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * PrimaryID is the user's requested locale string,
2042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * canonicalPrimaryID is this string in canonical form,
2052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * fallbackID is the current default locale's string in
2062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * canonical form.
2072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         */
2082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        protected LocaleKey(String primaryID, String canonicalPrimaryID, String canonicalFallbackID, int kind) {
2092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            super(primaryID);
2102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            this.kind = kind;
2112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if (canonicalPrimaryID == null || canonicalPrimaryID.equalsIgnoreCase("root")) {
2132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                this.primaryID = "";
2142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                this.fallbackID = null;
2152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            } else {
2162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                int idx = canonicalPrimaryID.indexOf('@');
2172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                if (idx == 4 && canonicalPrimaryID.regionMatches(true, 0, "root", 0, 4)) {
2182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    this.primaryID = canonicalPrimaryID.substring(4);
2192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    this.varstart = 0;
2202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    this.fallbackID = null;
2212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                } else {
2222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    this.primaryID = canonicalPrimaryID;
2232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    this.varstart = idx;
2242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    if (canonicalFallbackID == null || this.primaryID.equals(canonicalFallbackID)) {
2262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        this.fallbackID = "";
2272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    } else {
2282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        this.fallbackID = canonicalFallbackID;
2292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    }
2302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
2312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
2322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            this.currentID = varstart == -1 ? this.primaryID : this.primaryID.substring(0, varstart);
2342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
2352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /**
2372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * Return the prefix associated with the kind, or null if the kind is KIND_ANY.
2382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         */
2392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        public String prefix() {
2402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return kind == KIND_ANY ? null : Integer.toString(kind());
2412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
2422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /**
2442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * Return the kind code associated with this key.
2452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         */
2462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        public int kind() {
2472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return kind;
2482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
2492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /**
2512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * Return the (canonical) original ID.
2522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         */
2532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        public String canonicalID() {
2542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return primaryID;
2552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
2562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /**
2582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * Return the (canonical) current ID, or null if no current id.
2592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         */
2602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        public String currentID() {
2612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return currentID;
2622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
2632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /**
2652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * Return the (canonical) current descriptor, or null if no current id.
2662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * Includes the keywords, whereas the ID does not include keywords.
2672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         */
2682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        public String currentDescriptor() {
2692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            String result = currentID();
2702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if (result != null) {
2712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                StringBuilder buf = new StringBuilder(); // default capacity 16 is usually good enough
2722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                if (kind != KIND_ANY) {
2732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    buf.append(prefix());
2742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
2752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                buf.append('/');
2762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                buf.append(result);
2772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                if (varstart != -1) {
2782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    buf.append(primaryID.substring(varstart, primaryID.length()));
2792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
2802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                result = buf.toString();
2812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
2822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return result;
2832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
2842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /**
2862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * Convenience method to return the locale corresponding to the (canonical) original ID.
2872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         */
2882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        public ULocale canonicalLocale() {
2892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return new ULocale(primaryID);
2902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
2912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /**
2932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * Convenience method to return the ulocale corresponding to the (canonical) currentID.
2942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         */
2952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        public ULocale currentLocale() {
2962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if (varstart == -1) {
2972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                return new ULocale(currentID);
2982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            } else {
2992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                return new ULocale(currentID + primaryID.substring(varstart));
3002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
3012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
3022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
3032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /**
3042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * If the key has a fallback, modify the key and return true,
3052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * otherwise return false.</p>
3062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         *
3072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * <p>First falls back through the primary ID, then through
3082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * the fallbackID.  The final fallback is "" (root)
3092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * unless the primary id was "" (root), in which case
3102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * there is no fallback.
3112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         */
3122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        public boolean fallback() {
3132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            int x = currentID.lastIndexOf('_');
3142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if (x != -1) {
3152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                while (--x >= 0 && currentID.charAt(x) == '_') { // handle zh__PINYIN
3162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
3172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                currentID = currentID.substring(0, x+1);
3182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                return true;
3192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
3202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if (fallbackID != null) {
3212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                currentID = fallbackID;
3222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                if (fallbackID.length() == 0) {
3232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    fallbackID = null;
3242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                } else {
3252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    fallbackID = "";
3262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
3272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                return true;
3282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
3292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            currentID = null;
3302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return false;
3312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
3322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
3332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /**
3342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * If a key created from id would eventually fallback to match the
3352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * canonical ID of this key, return true.
3362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         */
3372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        public boolean isFallbackOf(String id) {
3382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return LocaleUtility.isFallbackOf(canonicalID(), id);
3392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
3402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
3412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
3422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
3432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * A subclass of Factory that uses LocaleKeys.  If 'visible' the
3442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * factory reports its IDs.
3452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
3462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static abstract class LocaleKeyFactory implements Factory {
3472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        protected final String name;
3482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        protected final boolean visible;
3492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
3502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        public static final boolean VISIBLE = true;
3512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        public static final boolean INVISIBLE = false;
3522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
3532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /**
3542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * Constructor used by subclasses.
3552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         */
3562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        protected LocaleKeyFactory(boolean visible) {
3572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            this.visible = visible;
3582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            this.name = null;
3592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
3602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
3612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /**
3622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * Constructor used by subclasses.
3632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         */
3642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        protected LocaleKeyFactory(boolean visible, String name) {
3652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            this.visible = visible;
3662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            this.name = name;
3672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
3682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
3692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /**
3702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * Implement superclass abstract method.  This checks the currentID of
3712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * the key against the supported IDs, and passes the canonicalLocale and
3722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * kind off to handleCreate (which subclasses must implement).
3732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         */
3742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        public Object create(Key key, ICUService service) {
3752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if (handlesKey(key)) {
3762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                LocaleKey lkey = (LocaleKey)key;
3772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                int kind = lkey.kind();
3782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
3792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                ULocale uloc = lkey.currentLocale();
3802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                return handleCreate(uloc, kind, service);
3812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            } else {
3822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                // System.out.println("factory: " + this + " did not support id: " + key.currentID());
3832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                // System.out.println("supported ids: " + getSupportedIDs());
3842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
3852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return null;
3862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
3872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
3882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        protected boolean handlesKey(Key key) {
3892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if (key != null) {
3902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                String id = key.currentID();
3912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                Set<String> supported = getSupportedIDs();
3922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                return supported.contains(id);
3932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
3942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return false;
3952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
3962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
3972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /**
3982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * Override of superclass method.
3992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         */
4002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        public void updateVisibleIDs(Map<String, Factory> result) {
4012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            Set<String> cache = getSupportedIDs();
4022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            for (String id : cache) {
4032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                if (visible) {
4042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    result.put(id, this);
4052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                } else {
4062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    result.remove(id);
4072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
4082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
4092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller       }
4102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
4112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /**
4122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * Return a localized name for the locale represented by id.
4132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         */
4142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        public String getDisplayName(String id, ULocale locale) {
4152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            // assume if the user called this on us, we must have handled some fallback of this id
4162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            //          if (isSupportedID(id)) {
4172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if (locale == null) {
4182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                return id;
4192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
4202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            ULocale loc = new ULocale(id);
4212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return loc.getDisplayName(locale);
4222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            //              }
4232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            //          return null;
4242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
4252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
4262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        ///CLOVER:OFF
4272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /**
4282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * Utility method used by create(Key, ICUService).  Subclasses can
4292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * implement this instead of create.
4302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         */
4312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        protected Object handleCreate(ULocale loc, int kind, ICUService service) {
4322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return null;
4332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
4342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        ///CLOVER:ON
4352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
4362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /**
4372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * Return true if this id is one the factory supports (visible or
4382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * otherwise).
4392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         */
4402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        protected boolean isSupportedID(String id) {
4412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return getSupportedIDs().contains(id);
4422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
4432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
4442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /**
4452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * Return the set of ids that this factory supports (visible or
4462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * otherwise).  This can be called often and might need to be
4472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * cached if it is expensive to create.
4482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         */
4492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        protected Set<String> getSupportedIDs() {
4502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return Collections.emptySet();
4512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
4522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
4532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /**
4542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * For debugging.
4552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         */
4562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        public String toString() {
4572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            StringBuilder buf = new StringBuilder(super.toString());
4582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if (name != null) {
4592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                buf.append(", name: ");
4602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                buf.append(name);
4612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
4622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            buf.append(", visible: ");
4632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            buf.append(visible);
4642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return buf.toString();
4652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
4662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
4672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
4682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
4692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * A LocaleKeyFactory that just returns a single object for a kind/locale.
4702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
4712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static class SimpleLocaleKeyFactory extends LocaleKeyFactory {
4722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        private final Object obj;
4732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        private final String id;
4742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        private final int kind;
4752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
4762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        // TODO: remove when we no longer need this
4772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        public SimpleLocaleKeyFactory(Object obj, ULocale locale, int kind, boolean visible) {
4782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            this(obj, locale, kind, visible, null);
4792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
4802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
4812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        public SimpleLocaleKeyFactory(Object obj, ULocale locale, int kind, boolean visible, String name) {
4822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            super(visible, name);
4832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
4842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            this.obj = obj;
4852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            this.id = locale.getBaseName();
4862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            this.kind = kind;
4872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
4882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
4892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /**
4902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * Returns the service object if kind/locale match.  Service is not used.
4912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         */
4922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        public Object create(Key key, ICUService service) {
4932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if (!(key instanceof LocaleKey)) {
4942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                return null;
4952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
4962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
4972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            LocaleKey lkey = (LocaleKey)key;
4982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if (kind != LocaleKey.KIND_ANY && kind != lkey.kind()) {
4992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                return null;
5002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
5012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if (!id.equals(lkey.currentID())) {
5022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                return null;
5032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
5042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
5052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return obj;
5062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
5072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
5082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        protected boolean isSupportedID(String idToCheck) {
5092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return this.id.equals(idToCheck);
5102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
5112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
5122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        public void updateVisibleIDs(Map<String, Factory> result) {
5132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if (visible) {
5142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                result.put(id, this);
5152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            } else {
5162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                result.remove(id);
5172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
5182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
5192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
5202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        public String toString() {
5212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            StringBuilder buf = new StringBuilder(super.toString());
5222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            buf.append(", id: ");
5232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            buf.append(id);
5242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            buf.append(", kind: ");
5252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            buf.append(kind);
5262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return buf.toString();
5272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
5282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
5292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
5302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
5312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * A LocaleKeyFactory that creates a service based on the ICU locale data.
5322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * This is a base class for most ICU factories.  Subclasses instantiate it
5332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * with a constructor that takes a bundle name, which determines the supported
5342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * IDs.  Subclasses then override handleCreate to create the actual service
5352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * object.  The default implementation returns a resource bundle.
5362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
5372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static class ICUResourceBundleFactory extends LocaleKeyFactory {
5382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        protected final String bundleName;
5392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
5402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /**
5412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * Convenience constructor that uses the main ICU bundle name.
5422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         */
5432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        public ICUResourceBundleFactory() {
5442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            this(ICUResourceBundle.ICU_BASE_NAME);
5452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
5462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
5472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /**
5482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * A service factory based on ICU resource data in resources
5492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * with the given name.
5502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         */
5512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        public ICUResourceBundleFactory(String bundleName) {
5522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            super(true);
5532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
5542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            this.bundleName = bundleName;
5552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
5562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
5572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /**
5582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * Return the supported IDs.  This is the set of all locale names for the bundleName.
5592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         */
5602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        protected Set<String> getSupportedIDs() {
5612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return ICUResourceBundle.getFullLocaleNameSet(bundleName, loader());
5622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
5632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
5642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /**
5652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * Override of superclass method.
5662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         */
5672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        public void updateVisibleIDs(Map<String, Factory> result) {
5682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller          Set<String> visibleIDs = ICUResourceBundle.getAvailableLocaleNameSet(bundleName, loader()); // only visible ids
5692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            for (String id : visibleIDs) {
5702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                result.put(id, this);
5712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
5722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
5732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
5742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /**
5752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * Create the service.  The default implementation returns the resource bundle
5762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * for the locale, ignoring kind, and service.
5772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         */
5782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        protected Object handleCreate(ULocale loc, int kind, ICUService service) {
5792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return ICUResourceBundle.getBundleInstance(bundleName, loc, loader());
5802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
5812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
5822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        protected ClassLoader loader() {
5832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return ClassLoaderUtil.getClassLoader(getClass());
5842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
5852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
5862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        public String toString() {
5872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return super.toString() + ", bundle: " + bundleName;
5882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
5892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
5902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
5912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
5922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Return the name of the current fallback locale.  If it has changed since this was
5932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * last accessed, the service cache is cleared.
5942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
5952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public String validateFallbackLocale() {
5962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        ULocale loc = ULocale.getDefault();
5972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if (loc != fallbackLocale) {
5982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            synchronized (this) {
5992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                if (loc != fallbackLocale) {
6002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    fallbackLocale = loc;
6012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    fallbackLocaleName = loc.getBaseName();
6022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    clearServiceCache();
6032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
6042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
6052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
6062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return fallbackLocaleName;
6072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
6082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
6092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public Key createKey(String id) {
6102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return LocaleKey.createWithCanonicalFallback(id, validateFallbackLocale());
6112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
6122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
6132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public Key createKey(String id, int kind) {
6142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return LocaleKey.createWithCanonicalFallback(id, validateFallbackLocale(), kind);
6152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
6162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
6172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public Key createKey(ULocale l, int kind) {
6182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return LocaleKey.createWithCanonical(l, validateFallbackLocale(), kind);
6192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
6202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller}
621