2 *******************************************************************************
\r
3 * Copyright (C) 2009-2010, International Business Machines Corporation and *
\r
4 * others. All Rights Reserved. *
\r
5 *******************************************************************************
\r
8 package com.ibm.icu.text;
\r
10 import java.util.ArrayList;
\r
11 import java.util.Locale;
\r
12 import java.util.MissingResourceException;
\r
14 import com.ibm.icu.impl.ICUCache;
\r
15 import com.ibm.icu.impl.ICUResourceBundle;
\r
16 import com.ibm.icu.impl.SimpleCache;
\r
17 import com.ibm.icu.lang.UCharacter;
\r
18 import com.ibm.icu.util.ULocale;
\r
19 import com.ibm.icu.util.UResourceBundle;
\r
20 import com.ibm.icu.util.UResourceBundleIterator;
\r
24 * <code>NumberingSystem</code> is the base class for all number
\r
25 * systems. This class provides the interface for setting different numbering
\r
26 * system types, whether it be a simple alternate digit system such as
\r
27 * Thai digits or Devanagari digits, or an algorithmic numbering system such
\r
28 * as Hebrew numbering or Chinese numbering.
\r
30 * @author John Emmons
\r
33 class NumberingSystem {
\r
36 * Default constructor. Returns a numbering system that uses the Western decimal
\r
37 * digits 0 through 9.
\r
40 public NumberingSystem() {
\r
42 algorithmic = false;
\r
43 desc = "0123456789";
\r
47 * Factory method for creating a numbering system.
\r
48 * @param radix_in The radix for this numbering system. ICU currently
\r
49 * supports only numbering systems whose radix is 10.
\r
50 * @param isAlgorithmic_in Specifies whether the numbering system is algorithmic
\r
51 * (true) or numeric (false).
\r
52 * @param desc_in String used to describe the characteristics of the numbering
\r
53 * system. For numeric systems, this string contains the digits used by the
\r
54 * numbering system, in order, starting from zero. For algorithmic numbering
\r
55 * systems, the string contains the name of the RBNF ruleset in the locale's
\r
56 * NumberingSystemRules section that will be used to format numbers using
\r
57 * this numbering system.
\r
60 public static NumberingSystem getInstance(int radix_in, boolean isAlgorithmic_in, String desc_in ) {
\r
61 if ( radix_in < 2 ) {
\r
62 throw new IllegalArgumentException("Invalid radix for numbering system");
\r
65 if ( !isAlgorithmic_in ) {
\r
66 if ( desc_in.length() != radix_in || !isValidDigitString(desc_in)) {
\r
67 throw new IllegalArgumentException("Invalid digit string for numbering system");
\r
70 NumberingSystem ns = new NumberingSystem();
\r
71 ns.radix = radix_in;
\r
72 ns.algorithmic = isAlgorithmic_in;
\r
78 * Returns the default numbering system for the specified locale.
\r
81 public static NumberingSystem getInstance(Locale inLocale) {
\r
82 return getInstance(ULocale.forLocale(inLocale));
\r
86 * Returns the default numbering system for the specified ULocale.
\r
89 public static NumberingSystem getInstance(ULocale locale) {
\r
92 String defaultNumberingSystem;
\r
94 // Check for @numbers
\r
95 String numbersKeyword = locale.getKeywordValue("numbers");
\r
96 if (numbersKeyword != null) {
\r
97 ns = getInstanceByName(numbersKeyword);
\r
103 // Get the numbering system from the cache
\r
104 String baseName = locale.getBaseName();
\r
105 ns = cachedLocaleData.get(baseName);
\r
110 // Cache miss, create new instance
\r
112 ICUResourceBundle rb = (ICUResourceBundle)UResourceBundle.getBundleInstance(ICUResourceBundle.ICU_BASE_NAME,locale);
\r
113 defaultNumberingSystem = rb.getString("defaultNumberingSystem");
\r
114 } catch (MissingResourceException ex) {
\r
115 ns = new NumberingSystem();
\r
116 cachedLocaleData.put(baseName, ns);
\r
120 ns = getInstanceByName(defaultNumberingSystem);
\r
121 if ( ns != null ) {
\r
122 cachedLocaleData.put(baseName, ns);
\r
126 ns = new NumberingSystem();
\r
127 cachedLocaleData.put(baseName, ns);
\r
133 * Returns the default numbering system for the default locale.
\r
136 public static NumberingSystem getInstance() {
\r
137 return getInstance(ULocale.getDefault());
\r
141 * Returns a numbering system from one of the predefined numbering systems
\r
142 * known to ICU. Numbering system names are based on the numbering systems
\r
143 * defined in CLDR. To get a list of available numbering systems, use the
\r
144 * getAvailableNames method.
\r
145 * @param name The name of the desired numbering system. Numbering system
\r
146 * names often correspond with the name of the script they are associated
\r
147 * with. For example, "thai" for Thai digits, "hebr" for Hebrew numerals.
\r
150 public static NumberingSystem getInstanceByName(String name) {
\r
152 boolean isAlgorithmic;
\r
153 String description;
\r
155 // Get the numbering system from the cache
\r
156 NumberingSystem ns = cachedStringData.get(name);
\r
162 UResourceBundle numberingSystemsInfo = UResourceBundle.getBundleInstance(ICUResourceBundle.ICU_BASE_NAME, "numberingSystems");
\r
163 UResourceBundle nsCurrent = numberingSystemsInfo.get("numberingSystems");
\r
164 UResourceBundle nsTop = nsCurrent.get(name);
\r
166 description = nsTop.getString("desc");
\r
167 UResourceBundle nsRadixBundle = nsTop.get("radix");
\r
168 UResourceBundle nsAlgBundle = nsTop.get("algorithmic");
\r
169 radix = nsRadixBundle.getInt();
\r
170 int algorithmic = nsAlgBundle.getInt();
\r
172 isAlgorithmic = ( algorithmic == 1 );
\r
174 } catch (MissingResourceException ex) {
\r
178 ns = getInstance(radix,isAlgorithmic,description);
\r
179 cachedStringData.put(name, ns);
\r
184 * Returns a string array containing a list of the names of numbering systems
\r
185 * currently known to ICU.
\r
188 public static String [] getAvailableNames() {
\r
190 UResourceBundle numberingSystemsInfo = UResourceBundle.getBundleInstance(ICUResourceBundle.ICU_BASE_NAME, "numberingSystems");
\r
191 UResourceBundle nsCurrent = numberingSystemsInfo.get("numberingSystems");
\r
192 UResourceBundle temp;
\r
195 ArrayList<String> output = new ArrayList<String>();
\r
196 UResourceBundleIterator it = nsCurrent.getIterator();
\r
197 while (it.hasNext()) {
\r
199 nsName = temp.getKey();
\r
200 output.add(nsName);
\r
202 return output.toArray(new String[output.size()]);
\r
206 * Convenience method to determine if a given digit string is valid for use as a
\r
207 * descriptor of a numeric ( non-algorithmic ) numbering system. In order for
\r
208 * a digit string to be valid, it must meet the following criteria:
\r
209 * 1. It must only contain characters that are decimal digits as defined by Unicode.
\r
210 * 2. It must contain characters that are contiguous code points.
\r
211 * 3. Digits must be in Unicode's basic multilingual plane.
\r
214 public static boolean isValidDigitString(String str) {
\r
219 UCharacterIterator it = UCharacterIterator.getInstance(str);
\r
222 while ( (c = it.nextCodePoint()) != UCharacterIterator.DONE) {
\r
223 if ( UCharacter.digit(c) != i ) { // Digits outside the Unicode decimal digit class are not currently supported
\r
226 if ( prev != 0 && c != prev + 1 ) { // Non-contiguous digits are not currently supported
\r
229 if ( UCharacter.isSupplementary(c)) { // Digits outside the BMP are not currently supported
\r
239 * Returns the radix of the current numbering system.
\r
242 public int getRadix() {
\r
247 * Returns the description string of the current numbering system.
\r
248 * The description string describes the characteristics of the numbering
\r
249 * system. For numeric systems, this string contains the digits used by the
\r
250 * numbering system, in order, starting from zero. For algorithmic numbering
\r
251 * systems, the string contains the name of the RBNF ruleset in the locale's
\r
252 * NumberingSystemRules section that will be used to format numbers using
\r
253 * this numbering system.
\r
256 public String getDescription() {
\r
261 * Returns the numbering system's algorithmic status. If true,
\r
262 * the numbering system is algorithmic and uses an RBNF formatter to
\r
263 * format numerals. If false, the numbering system is numeric and
\r
264 * uses a fixed set of digits.
\r
267 public boolean isAlgorithmic() {
\r
268 return algorithmic;
\r
271 private String desc;
\r
273 private boolean algorithmic;
\r
276 * Cache to hold the NumberingSystems by Locale.
\r
278 private static ICUCache<String, NumberingSystem> cachedLocaleData = new SimpleCache<String, NumberingSystem>();
\r
281 * Cache to hold the NumberingSystems by name.
\r
283 private static ICUCache<String, NumberingSystem> cachedStringData = new SimpleCache<String, NumberingSystem>();
\r