12ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller/* GENERATED SOURCE. DO NOT MODIFY. */
2f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert// © 2016 and later: Unicode, Inc. and others.
3f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert// License & terms of use: http://www.unicode.org/copyright.html#License
42ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller/*
52ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller *******************************************************************************
6f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert * Copyright (C) 2009-2016, International Business Machines Corporation and
7f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert * others. All Rights Reserved.
82ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller *******************************************************************************
92ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */
102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerpackage android.icu.text;
122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.util.ArrayList;
142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.util.Locale;
152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.util.MissingResourceException;
162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
17f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubertimport android.icu.impl.CacheBase;
18f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubertimport android.icu.impl.ICUData;
192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport android.icu.impl.ICUResourceBundle;
20f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubertimport android.icu.impl.SoftCache;
212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport android.icu.util.ULocale;
222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport android.icu.util.ULocale.Category;
232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport android.icu.util.UResourceBundle;
242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport android.icu.util.UResourceBundleIterator;
252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller/**
282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <code>NumberingSystem</code> is the base class for all number
292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * systems. This class provides the interface for setting different numbering
30f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert * system types, whether it be a simple alternate digit system such as
312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Thai digits or Devanagari digits, or an algorithmic numbering system such
322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * as Hebrew numbering or Chinese numbering.
332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller *
342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @author       John Emmons
352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */
362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerpublic class NumberingSystem {
37f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    private static final String[] OTHER_NS_KEYWORDS = { "native", "traditional", "finance" };
382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Default constructor.  Returns a numbering system that uses the Western decimal
412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * digits 0 through 9.
422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public NumberingSystem() {
442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        radix = 10;
452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        algorithmic = false;
462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        desc = "0123456789";
472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        name = "latn";
482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Factory method for creating a numbering system.
52f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert     * @param radix_in The radix for this numbering system.  ICU currently
532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * supports only numbering systems whose radix is 10.
542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @param isAlgorithmic_in Specifies whether the numbering system is algorithmic
552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * (true) or numeric (false).
562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @param desc_in String used to describe the characteristics of the numbering
572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * system.  For numeric systems, this string contains the digits used by the
582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * numbering system, in order, starting from zero.  For algorithmic numbering
592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * systems, the string contains the name of the RBNF ruleset in the locale's
602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * NumberingSystemRules section that will be used to format numbers using
612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * this numbering system.
622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static NumberingSystem getInstance(int radix_in, boolean isAlgorithmic_in, String desc_in ) {
642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return getInstance(null,radix_in,isAlgorithmic_in,desc_in);
652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
66f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Factory method for creating a numbering system.
692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @param name_in The string representing the name of the numbering system.
70f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert     * @param radix_in The radix for this numbering system.  ICU currently
712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * supports only numbering systems whose radix is 10.
722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @param isAlgorithmic_in Specifies whether the numbering system is algorithmic
732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * (true) or numeric (false).
742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @param desc_in String used to describe the characteristics of the numbering
752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * system.  For numeric systems, this string contains the digits used by the
762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * numbering system, in order, starting from zero.  For algorithmic numbering
772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * systems, the string contains the name of the RBNF ruleset in the locale's
782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * NumberingSystemRules section that will be used to format numbers using
792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * this numbering system.
802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
81f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static NumberingSystem getInstance(String name_in, int radix_in, boolean isAlgorithmic_in, String desc_in ) {
832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if ( radix_in < 2 ) {
842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            throw new IllegalArgumentException("Invalid radix for numbering system");
852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if ( !isAlgorithmic_in ) {
882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if ( desc_in.length() != radix_in || !isValidDigitString(desc_in)) {
892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                throw new IllegalArgumentException("Invalid digit string for numbering system");
902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        NumberingSystem ns = new NumberingSystem();
932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        ns.radix = radix_in;
942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        ns.algorithmic = isAlgorithmic_in;
952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        ns.desc = desc_in;
962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        ns.name = name_in;
972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return ns;
982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
1012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Returns the default numbering system for the specified locale.
1022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
1032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static NumberingSystem getInstance(Locale inLocale) {
1042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return getInstance(ULocale.forLocale(inLocale));
1052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
1082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Returns the default numbering system for the specified ULocale.
1092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
1102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static NumberingSystem getInstance(ULocale locale) {
1112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        // Check for @numbers
112f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        boolean nsResolved = true;
1132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        String numbersKeyword = locale.getKeywordValue("numbers");
1142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if (numbersKeyword != null ) {
1152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            for ( String keyword : OTHER_NS_KEYWORDS ) {
1162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                if ( numbersKeyword.equals(keyword)) {
1172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    nsResolved = false;
1182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    break;
1192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
1202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
1212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        } else {
1222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            numbersKeyword = "default";
1232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            nsResolved = false;
1242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
1252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if (nsResolved) {
127f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            NumberingSystem ns = getInstanceByName(numbersKeyword);
128f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            if (ns != null) {
1292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                return ns;
1302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
131f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            // If the @numbers keyword points to a bogus numbering system name,
132f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            // we return the default for the locale.
133f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            numbersKeyword = "default";
1342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
135f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
1362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        // Attempt to get the numbering system from the cache
1372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        String baseName = locale.getBaseName();
138f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        // TODO: Caching by locale+numbersKeyword could yield a large cache.
139f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        // Try to load for each locale the mappings from OTHER_NS_KEYWORDS and default
140f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        // to real numbering system names; can we get those from supplemental data?
141f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        // Then look up those mappings for the locale and resolve the keyword.
142f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        String key = baseName+"@numbers="+numbersKeyword;
143f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        LocaleLookupData localeLookupData = new LocaleLookupData(locale, numbersKeyword);
144f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        return cachedLocaleData.getInstance(key, localeLookupData);
145f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    }
146f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
147f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    private static class LocaleLookupData {
148f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        public final ULocale locale;
149f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        public final String numbersKeyword;
150f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
151f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        LocaleLookupData(ULocale locale, String numbersKeyword) {
152f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            this.locale = locale;
153f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            this.numbersKeyword = numbersKeyword;
1542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
155f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    }
1562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
157f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    static NumberingSystem lookupInstanceByLocale(LocaleLookupData localeLookupData) {
158f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        ULocale locale = localeLookupData.locale;
159f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        ICUResourceBundle rb;
160f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        try {
161f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            rb = (ICUResourceBundle)UResourceBundle.getBundleInstance(ICUData.ICU_BASE_NAME, locale);
162f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            rb = rb.getWithFallback("NumberElements");
163f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        } catch (MissingResourceException ex) {
164f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            return new NumberingSystem();
165f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        }
166f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
167f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        String numbersKeyword = localeLookupData.numbersKeyword;
1682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        String resolvedNumberingSystem = null;
169f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        for (;;) {
1702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            try {
1712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                resolvedNumberingSystem = rb.getStringWithFallback(numbersKeyword);
172f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                break;
1732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            } catch (MissingResourceException ex) { // Fall back behavior as defined in TR35
174f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                if (numbersKeyword.equals("native") || numbersKeyword.equals("finance")) {
175f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                    numbersKeyword = "default";
176f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                } else if (numbersKeyword.equals("traditional")) {
177f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                    numbersKeyword = "native";
178f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                } else {
179f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                    break;
180f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                }
181f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            }
1822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
1832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
184f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        NumberingSystem ns = null;
1852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if (resolvedNumberingSystem != null) {
1862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            ns = getInstanceByName(resolvedNumberingSystem);
1872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
188f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
189f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        if (ns == null) {
1902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            ns = new NumberingSystem();
1912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
1922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return ns;
1932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
1962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Returns the default numbering system for the default <code>FORMAT</code> locale.
1972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @see Category#FORMAT
1982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
1992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static NumberingSystem getInstance() {
2002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return getInstance(ULocale.getDefault(Category.FORMAT));
2012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
2022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
2042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Returns a numbering system from one of the predefined numbering systems
2052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * known to ICU.  Numbering system names are based on the numbering systems
2062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * defined in CLDR.  To get a list of available numbering systems, use the
2072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * getAvailableNames method.
2082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @param name The name of the desired numbering system.  Numbering system
2092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * names often correspond with the name of the script they are associated
2102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * with.  For example, "thai" for Thai digits, "hebr" for Hebrew numerals.
2112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
2122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static NumberingSystem getInstanceByName(String name) {
213f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        // Get the numbering system from the cache.
214f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        return cachedStringData.getInstance(name, null /* unused */);
215f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    }
216f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
217f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    private static NumberingSystem lookupInstanceByName(String name) {
2182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        int radix;
2192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        boolean isAlgorithmic;
2202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        String description;
2212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        try {
222f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            UResourceBundle numberingSystemsInfo = UResourceBundle.getBundleInstance(ICUData.ICU_BASE_NAME, "numberingSystems");
2232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            UResourceBundle nsCurrent = numberingSystemsInfo.get("numberingSystems");
2242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            UResourceBundle nsTop = nsCurrent.get(name);
2252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            description = nsTop.getString("desc");
2272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            UResourceBundle nsRadixBundle = nsTop.get("radix");
2282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            UResourceBundle nsAlgBundle = nsTop.get("algorithmic");
2292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            radix = nsRadixBundle.getInt();
2302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            int algorithmic = nsAlgBundle.getInt();
2312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            isAlgorithmic = ( algorithmic == 1 );
2332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        } catch (MissingResourceException ex) {
2352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return null;
2362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
2372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
238f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        return getInstance(name, radix, isAlgorithmic, description);
2392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
2402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
2422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Returns a string array containing a list of the names of numbering systems
2432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * currently known to ICU.
2442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
2452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static String [] getAvailableNames() {
246f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
247f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            UResourceBundle numberingSystemsInfo = UResourceBundle.getBundleInstance(ICUData.ICU_BASE_NAME, "numberingSystems");
2482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            UResourceBundle nsCurrent = numberingSystemsInfo.get("numberingSystems");
2492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            UResourceBundle temp;
2502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            String nsName;
2522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            ArrayList<String> output = new ArrayList<String>();
2532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            UResourceBundleIterator it = nsCurrent.getIterator();
2542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            while (it.hasNext()) {
2552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                temp = it.next();
2562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                nsName = temp.getKey();
2572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                output.add(nsName);
2582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
2592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return output.toArray(new String[output.size()]);
2602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
2612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
263f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert     * Convenience method to determine if a given digit string is valid for use as a
2642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * descriptor of a numeric ( non-algorithmic ) numbering system.  In order for
265f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert     * a digit string to be valid, it must contain exactly ten Unicode code points.
2662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
2672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static boolean isValidDigitString(String str) {
268f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        int numCodepoints = str.codePointCount(0, str.length());
269f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        return (numCodepoints == 10);
2702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
2712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
2732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Returns the radix of the current numbering system.
2742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
2752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public int getRadix() {
2762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return radix;
2772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
2782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
2802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Returns the description string of the current numbering system.
2812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * The description string describes the characteristics of the numbering
2822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * system.  For numeric systems, this string contains the digits used by the
2832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * numbering system, in order, starting from zero.  For algorithmic numbering
2842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * systems, the string contains the name of the RBNF ruleset in the locale's
2852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * NumberingSystemRules section that will be used to format numbers using
2862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * this numbering system.
2872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
2882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public String getDescription() {
2892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return desc;
2902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
2912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
2932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Returns the string representing the name of the numbering system.
2942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
2952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public String getName() {
2962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return name;
2972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
2982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
2992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Returns the numbering system's algorithmic status.  If true,
3002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * the numbering system is algorithmic and uses an RBNF formatter to
3012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * format numerals.  If false, the numbering system is numeric and
302f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert     * uses a fixed set of digits.
3032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
3042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public boolean isAlgorithmic() {
3052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return algorithmic;
3062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
3072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
3082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private String desc;
3092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private int radix;
3102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private boolean algorithmic;
3112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private String name;
3122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
3132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
3142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Cache to hold the NumberingSystems by Locale.
3152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
316f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    private static CacheBase<String, NumberingSystem, LocaleLookupData> cachedLocaleData =
317f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            new SoftCache<String, NumberingSystem, LocaleLookupData>() {
318f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        @Override
319f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        protected NumberingSystem createInstance(String key, LocaleLookupData localeLookupData) {
320f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            return lookupInstanceByLocale(localeLookupData);
321f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        }
322f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    };
323f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
3242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
3252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Cache to hold the NumberingSystems by name.
3262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
327f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    private static CacheBase<String, NumberingSystem, Void>  cachedStringData =
328f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            new SoftCache<String, NumberingSystem, Void>() {
329f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        @Override
330f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        protected NumberingSystem createInstance(String key, Void unused) {
331f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            return lookupInstanceByName(key);
332f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        }
333f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    };
3342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller}
335