/* | |
******************************************************************************* | |
* Copyright (C) 2009, International Business Machines Corporation and * | |
* others. All Rights Reserved. * | |
******************************************************************************* | |
*/ | |
package com.ibm.icu.text; | |
import java.util.ArrayList; | |
import java.util.Locale; | |
import java.util.MissingResourceException; | |
import com.ibm.icu.impl.ICUResourceBundle; | |
import com.ibm.icu.lang.UCharacter; | |
import com.ibm.icu.util.ULocale; | |
import com.ibm.icu.util.UResourceBundle; | |
import com.ibm.icu.util.UResourceBundleIterator; | |
import com.ibm.icu.text.UCharacterIterator; | |
/** | |
* <code>NumberingSystem</code> is the base class for all number | |
* systems. This class provides the interface for setting different numbering | |
* system types, whether it be a simple alternate digit system such as | |
* Thai digits or Devanagari digits, or an algorithmic numbering system such | |
* as Hebrew numbering or Chinese numbering. | |
* | |
* @author John Emmons | |
* @draft ICU 4.2 | |
*/ | |
class NumberingSystem { | |
/** | |
* Default constructor. Returns a numbering system that uses the Western decimal | |
* digits 0 through 9. | |
* @draft ICU 4.2 | |
*/ | |
public NumberingSystem() { | |
radix = 10; | |
algorithmic = false; | |
desc = "0123456789"; | |
} | |
/** | |
* Factory method for creating a numbering system. | |
* @param radix_in The radix for this numbering system. ICU currently | |
* supports only numbering systems whose radix is 10. | |
* @param isAlgorithmic_in Specifies whether the numbering system is algorithmic | |
* (true) or numeric (false). | |
* @param desc_in String used to describe the characteristics of the numbering | |
* system. For numeric systems, this string contains the digits used by the | |
* numbering system, in order, starting from zero. For algorithmic numbering | |
* systems, the string contains the name of the RBNF ruleset in the locale's | |
* NumberingSystemRules section that will be used to format numbers using | |
* this numbering system. | |
* @draft ICU 4.2 | |
*/ | |
public static NumberingSystem getInstance(int radix_in, boolean isAlgorithmic_in, String desc_in ) { | |
if ( radix_in < 2 ) { | |
throw new IllegalArgumentException("Invalid radix for numbering system"); | |
} | |
if ( !isAlgorithmic_in ) { | |
if ( desc_in.length() != radix_in || !isValidDigitString(desc_in)) { | |
throw new IllegalArgumentException("Invalid digit string for numbering system"); | |
} | |
} | |
NumberingSystem ns = new NumberingSystem(); | |
ns.radix = radix_in; | |
ns.algorithmic = isAlgorithmic_in; | |
ns.desc = desc_in; | |
return ns; | |
} | |
/** | |
* Returns the default numbering system for the specified locale. | |
* @draft ICU 4.2 | |
*/ | |
public static NumberingSystem getInstance(Locale inLocale) { | |
return getInstance(ULocale.forLocale(inLocale)); | |
} | |
/** | |
* Returns the default numbering system for the specified ULocale. | |
* @draft ICU 4.2 | |
*/ | |
public static NumberingSystem getInstance(ULocale locale) { | |
String numbersKeyword = locale.getKeywordValue("numbers"); | |
if (numbersKeyword != null) { | |
NumberingSystem ns = getInstanceByName(numbersKeyword); | |
if ( ns != null ) { | |
return ns; | |
} | |
} | |
String defaultNumberingSystem; | |
try { | |
ICUResourceBundle rb = (ICUResourceBundle)UResourceBundle.getBundleInstance(ICUResourceBundle.ICU_BASE_NAME,locale); | |
defaultNumberingSystem = rb.getString("defaultNumberingSystem"); | |
} catch (MissingResourceException ex) { | |
return new NumberingSystem(); | |
} | |
NumberingSystem ns = getInstanceByName(defaultNumberingSystem); | |
if ( ns != null ) { | |
return ns; | |
} | |
return new NumberingSystem(); | |
} | |
/** | |
* Returns the default numbering system for the default locale. | |
* @draft ICU 4.2 | |
*/ | |
public static NumberingSystem getInstance() { | |
return getInstance(ULocale.getDefault()); | |
} | |
/** | |
* Returns a numbering system from one of the predefined numbering systems | |
* known to ICU. Numbering system names are based on the numbering systems | |
* defined in CLDR. To get a list of available numbering systems, use the | |
* getAvailableNames method. | |
* @param name The name of the desired numbering system. Numbering system | |
* names often correspond with the name of the script they are associated | |
* with. For example, "thai" for Thai digits, "hebr" for Hebrew numerals. | |
* @draft ICU 4.2 | |
*/ | |
public static NumberingSystem getInstanceByName(String name) { | |
int radix; | |
boolean isAlgorithmic; | |
String description; | |
try { | |
UResourceBundle numberingSystemsInfo = UResourceBundle.getBundleInstance(ICUResourceBundle.ICU_BASE_NAME, "numberingSystems"); | |
UResourceBundle nsCurrent = numberingSystemsInfo.get("numberingSystems"); | |
UResourceBundle nsTop = nsCurrent.get(name); | |
description = nsTop.getString("desc"); | |
UResourceBundle nsRadixBundle = nsTop.get("radix"); | |
UResourceBundle nsAlgBundle = nsTop.get("algorithmic"); | |
radix = nsRadixBundle.getInt(); | |
int algorithmic = nsAlgBundle.getInt(); | |
isAlgorithmic = ( algorithmic == 1 ); | |
} catch (MissingResourceException ex) { | |
return null; | |
} | |
return getInstance(radix,isAlgorithmic,description); | |
} | |
/** | |
* Returns a string array containing a list of the names of numbering systems | |
* currently known to ICU. | |
* @draft ICU 4.2 | |
*/ | |
public static String [] getAvailableNames() { | |
UResourceBundle numberingSystemsInfo = UResourceBundle.getBundleInstance(ICUResourceBundle.ICU_BASE_NAME, "numberingSystems"); | |
UResourceBundle nsCurrent = numberingSystemsInfo.get("numberingSystems"); | |
UResourceBundle temp; | |
String nsName; | |
ArrayList output = new ArrayList(); | |
UResourceBundleIterator it = nsCurrent.getIterator(); | |
while (it.hasNext()) { | |
temp = it.next(); | |
nsName = temp.getKey(); | |
output.add(nsName); | |
} | |
return (String[]) output.toArray(new String[output.size()]); | |
} | |
/** | |
* Convenience method to determine if a given digit string is valid for use as a | |
* descriptor of a numeric ( non-algorithmic ) numbering system. In order for | |
* a digit string to be valid, it must meet the following criteria: | |
* 1. It must only contain characters that are decimal digits as defined by Unicode. | |
* 2. It must contain characters that are contiguous code points. | |
* 3. Digits must be in Unicode's basic multilingual plane. | |
* @draft ICU 4.2 | |
*/ | |
public static boolean isValidDigitString(String str) { | |
int c; | |
int prev = 0; | |
int i = 0; | |
UCharacterIterator it = UCharacterIterator.getInstance(str); | |
it.setToStart(); | |
while ( (c = it.nextCodePoint()) != UCharacterIterator.DONE) { | |
if ( UCharacter.digit(c) != i ) { // Digits outside the Unicode decimal digit class are not currently supported | |
return false; | |
} | |
if ( prev != 0 && c != prev + 1 ) { // Non-contiguous digits are not currently supported | |
return false; | |
} | |
if ( UCharacter.isSupplementary(c)) { // Digits outside the BMP are not currently supported | |
return false; | |
} | |
i++; | |
prev = c; | |
} | |
return true; | |
} | |
/** | |
* Returns the radix of the current numbering system. | |
* @draft ICU 4.2 | |
*/ | |
public int getRadix() { | |
return radix; | |
} | |
/** | |
* Returns the description string of the current numbering system. | |
* The description string describes the characteristics of the numbering | |
* system. For numeric systems, this string contains the digits used by the | |
* numbering system, in order, starting from zero. For algorithmic numbering | |
* systems, the string contains the name of the RBNF ruleset in the locale's | |
* NumberingSystemRules section that will be used to format numbers using | |
* this numbering system. | |
* @draft ICU 4.2 | |
*/ | |
public String getDescription() { | |
return desc; | |
} | |
/** | |
* Returns the numbering system's algorithmic status. If true, | |
* the numbering system is algorithmic and uses an RBNF formatter to | |
* format numerals. If false, the numbering system is numeric and | |
* uses a fixed set of digits. | |
* @draft ICU 4.2 | |
*/ | |
public boolean isAlgorithmic() { | |
return algorithmic; | |
} | |
private String desc; | |
private int radix; | |
private boolean algorithmic; | |
} |