/* GENERATED SOURCE. DO NOT MODIFY. */ // © 2016 and later: Unicode, Inc. and others. // License & terms of use: http://www.unicode.org/copyright.html /** ******************************************************************************* * Copyright (C) 2001-2016, International Business Machines Corporation and * others. All Rights Reserved. ******************************************************************************* */ package android.icu.util; import java.io.ObjectStreamException; import java.lang.ref.SoftReference; import java.text.ParsePosition; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.MissingResourceException; import java.util.Set; import android.icu.impl.CacheBase; import android.icu.impl.ICUCache; import android.icu.impl.ICUData; import android.icu.impl.ICUDebug; import android.icu.impl.ICUResourceBundle; import android.icu.impl.SimpleCache; import android.icu.impl.SoftCache; import android.icu.impl.StaticUnicodeSets; import android.icu.impl.TextTrieMap; import android.icu.text.CurrencyDisplayNames; import android.icu.text.CurrencyMetaInfo; import android.icu.text.CurrencyMetaInfo.CurrencyDigits; import android.icu.text.CurrencyMetaInfo.CurrencyFilter; import android.icu.text.UnicodeSet; import android.icu.util.ULocale.Category; /** * A class encapsulating a currency, as defined by ISO 4217. A * Currency object can be created given a Locale or * given an ISO 4217 code. Once created, the Currency object * can return various data necessary to its proper display: * *
Note: This class deliberately resembles
* java.util.Currency but it has a completely independent
* implementation, and adds features not present in the JDK.
* @author Alan Liu
*/
public class Currency extends MeasureUnit {
private static final long serialVersionUID = -5839973855554750484L;
private static final boolean DEBUG = ICUDebug.enabled("currency");
// Cache to save currency name trie
private static ICUCache
* The narrow currency symbol is similar to the regular currency symbol,
* but it always takes the shortest form;
* for example, "$" instead of "US$" for USD in en-CA.
*/
public static final int NARROW_SYMBOL_NAME = 3;
/**
* Selector for getName() indicating the formal currency symbol.
*
* The formal currency symbol is similar to the regular currency symbol,
* but it always takes the form used in formal settings such as banking;
* for example, "NT$" instead of "$" for TWD in zh-TW.
*/
public static final int FORMAL_SYMBOL_NAME = 4;
/**
* Selector for getName() indicating the variant currency symbol.
*
* The variant symbol for a currency is an alternative symbol that is not
* necessarily as widely used as the regular symbol.
*/
public static final int VARIANT_SYMBOL_NAME = 5;
/**
* Currency Usage used for Decimal Format
*/
public enum CurrencyUsage{
/**
* a setting to specify currency usage which determines currency digit and rounding
* for standard usage, for example: "50.00 NT$"
*/
STANDARD,
/**
* a setting to specify currency usage which determines currency digit and rounding
* for cash usage, for example: "50 NT$"
*/
CASH
}
// begin registry stuff
// shim for service code
/* package */ static abstract class ServiceShim {
abstract ULocale[] getAvailableULocales();
abstract Locale[] getAvailableLocales();
abstract Currency createInstance(ULocale l);
abstract Object registerInstance(Currency c, ULocale l);
abstract boolean unregister(Object f);
}
private static ServiceShim shim;
private static ServiceShim getShim() {
// Note: this instantiation is safe on loose-memory-model configurations
// despite lack of synchronization, since the shim instance has no state--
// it's all in the class init. The worst problem is we might instantiate
// two shim instances, but they'll share the same state so that's ok.
if (shim == null) {
try {
Class> cls = Class.forName("android.icu.util.CurrencyServiceShim");
shim = (ServiceShim)cls.newInstance();
}
catch (Exception e) {
if(DEBUG){
e.printStackTrace();
}
throw new RuntimeException(e.getMessage());
}
}
return shim;
}
/**
* Returns a currency object for the default currency in the given
* locale.
* @param locale the locale
* @return the currency object for this locale
*/
public static Currency getInstance(Locale locale) {
return getInstance(ULocale.forLocale(locale));
}
/**
* Returns a currency object for the default currency in the given
* locale.
*/
public static Currency getInstance(ULocale locale) {
String currency = locale.getKeywordValue("currency");
if (currency != null) {
return getInstance(currency);
}
if (shim == null) {
return createCurrency(locale);
}
return shim.createInstance(locale);
}
/**
* Returns an array of Strings which contain the currency
* identifiers that are valid for the given locale on the
* given date. If there are no such identifiers, returns null.
* Returned identifiers are in preference order.
* @param loc the locale for which to retrieve currency codes.
* @param d the date for which to retrieve currency codes for the given locale.
* @return The array of ISO currency codes.
*/
public static String[] getAvailableCurrencyCodes(ULocale loc, Date d) {
String region = ULocale.getRegionForSupplementalData(loc, false);
CurrencyFilter filter = CurrencyFilter.onDate(d).withRegion(region);
List Because ICU may choose to cache Currency objects internally, this must
* be called at application startup, prior to any calls to
* Currency.getInstance to avoid undefined behavior.
*
* @param currency the currency to register
* @param locale the ulocale under which to register the currency
* @return a registry key that can be used to unregister this currency
* @see #unregister
* @hide unsupported on Android
*/
public static Object registerInstance(Currency currency, ULocale locale) {
return getShim().registerInstance(currency, locale);
}
/**
* Unregister the currency associated with this key (obtained from
* registerInstance).
* @param registryKey the registry key returned from registerInstance
* @see #registerInstance
* @hide unsupported on Android
*/
public static boolean unregister(Object registryKey) {
if (registryKey == null) {
throw new IllegalArgumentException("registryKey must not be null");
}
if (shim == null) {
return false;
}
return shim.unregister(registryKey);
}
/**
* Return an array of the locales for which a currency
* is defined.
* @return an array of the available locales
*/
public static Locale[] getAvailableLocales() {
if (shim == null) {
return ICUResourceBundle.getAvailableLocales();
} else {
return shim.getAvailableLocales();
}
}
/**
* Return an array of the ulocales for which a currency
* is defined.
* @return an array of the available ulocales
*/
public static ULocale[] getAvailableULocales() {
if (shim == null) {
return ICUResourceBundle.getAvailableULocales();
} else {
return shim.getAvailableULocales();
}
}
// end registry stuff
/**
* Given a key and a locale, returns an array of values for the key for which data
* exists. If commonlyUsed is true, these are the values that typically are used
* with this locale, otherwise these are all values for which data exists.
* This is a common service API.
*
* The only supported key is "currency", other values return an empty array.
*
* Currency information is based on the region of the locale. If the locale does not
* indicate a region, {@link ULocale#addLikelySubtags(ULocale)} is used to infer a region,
* except for the 'und' locale.
*
* If commonlyUsed is true, only the currencies known to be in use as of the current date
* are returned. When there are more than one, these are returned in preference order
* (typically, this occurs when a country is transitioning to a new currency, and the
* newer currency is preferred), see
* Unicode TR#35 Sec. C1.
* If commonlyUsed is false, all currencies ever used in any locale are returned, in no
* particular order.
*
* @param key key whose values to look up. the only recognized key is "currency"
* @param locale the locale
* @param commonlyUsed if true, return only values that are currently used in the locale.
* Otherwise returns all values.
* @return an array of values for the given key and the locale. If there is no data, the
* array will be empty.
*/
public static final String[] getKeywordValuesForLocale(String key, ULocale locale,
boolean commonlyUsed) {
// The only keyword we recognize is 'currency'
if (!"currency".equals(key)) {
return EMPTY_STRING_ARRAY;
}
if (!commonlyUsed) {
// Behavior change from 4.3.3, no longer sort the currencies
return getAllTenderCurrencies().toArray(new String[0]);
}
// Don't resolve region if the requested locale is 'und', it will resolve to US
// which we don't want.
if (UND.equals(locale)) {
return EMPTY_STRING_ARRAY;
}
String prefRegion = ULocale.getRegionForSupplementalData(locale, true);
CurrencyFilter filter = CurrencyFilter.now().withRegion(prefRegion);
// currencies are in region's preferred order when we're filtering on region, which
// matches our spec
List Note: If the ISO 4217 numeric code is not assigned for the currency or
* the currency is unknown, this method returns 0.
* @throws IllegalArgumentException if the nameStyle is not SYMBOL_NAME
* or LONG_NAME.
* @see #getName(ULocale, int, String, boolean[])
*/
public String getName(ULocale locale, int nameStyle, boolean[] isChoiceFormat) {
// We no longer support choice format data in names. Data should not contain
// choice patterns.
if (isChoiceFormat != null) {
isChoiceFormat[0] = false;
}
CurrencyDisplayNames names = CurrencyDisplayNames.getInstance(locale);
switch (nameStyle) {
case SYMBOL_NAME:
return names.getSymbol(subType);
case NARROW_SYMBOL_NAME:
return names.getNarrowSymbol(subType);
case FORMAL_SYMBOL_NAME:
return names.getFormalSymbol(subType);
case VARIANT_SYMBOL_NAME:
return names.getVariantSymbol(subType);
case LONG_NAME:
return names.getName(subType);
default:
throw new IllegalArgumentException("bad name style: " + nameStyle);
}
}
/**
* Returns the display name for the given currency in the given locale.
* This is a convenience overload of getName(ULocale, int, String, boolean[]);
*
* @param locale locale in which to display currency
* @param nameStyle selector for which kind of name to return
* @param pluralCount plural count string for this locale
* @param isChoiceFormat isChoiceFormat[0] is always set to false, or isChoiceFormat can be null;
* display names are static strings;
* since ICU 4.4, ChoiceFormat patterns are no longer supported
* @return display string for this currency. If the resource data
* contains no entry for this currency, then the ISO 4217 code is
* returned.
*/
public String getName(Locale locale, int nameStyle, String pluralCount,
boolean[] isChoiceFormat) {
return getName(ULocale.forLocale(locale), nameStyle, pluralCount, isChoiceFormat);
}
/**
* Returns the display name for the given currency in the
* given locale. For example, the SYMBOL_NAME for the USD
* currency object in the en_US locale is "$".
* The PLURAL_LONG_NAME for the USD currency object when the currency
* amount is plural is "US dollars", such as in "3.00 US dollars";
* while the PLURAL_LONG_NAME for the USD currency object when the currency
* amount is singular is "US dollar", such as in "1.00 US dollar".
*
* @param locale locale in which to display currency
* @param nameStyle selector for which kind of name to return
* @param pluralCount plural count string for this locale
* @param isChoiceFormat isChoiceFormat[0] is always set to false, or isChoiceFormat can be null;
* display names are static strings;
* since ICU 4.4, ChoiceFormat patterns are no longer supported
* @return display string for this currency. If the resource data
* contains no entry for this currency, then the ISO 4217 code is
* returned.
* @throws IllegalArgumentException if the nameStyle is not SYMBOL_NAME,
* LONG_NAME, or PLURAL_LONG_NAME.
*/
public String getName(ULocale locale, int nameStyle, String pluralCount,
boolean[] isChoiceFormat) {
if (nameStyle != PLURAL_LONG_NAME) {
return getName(locale, nameStyle, isChoiceFormat);
}
// We no longer support choice format
if (isChoiceFormat != null) {
isChoiceFormat[0] = false;
}
CurrencyDisplayNames names = CurrencyDisplayNames.getInstance(locale);
return names.getPluralName(subType, pluralCount);
}
/**
* Returns the display name for this currency in the default locale.
* If the resource data for the default locale contains no entry for this currency,
* then the ISO 4217 code is returned.
*
* Note: This method is a convenience equivalent for
* {@link java.util.Currency#getDisplayName()} and is equivalent to
*
* Note: This method is a convenience equivalent for
* {@link java.util.Currency#getDisplayName(java.util.Locale)} and is equivalent
* to
* Note: For checking availability of a currency on a specific date, specify the date on both theISOCode
is null.
* @throws IllegalArgumentException if theISOCode
is not a
* 3-letter alpha code.
*/
public static Currency getInstance(String theISOCode) {
if (theISOCode == null) {
throw new NullPointerException("The input currency code is null.");
}
if (!isAlpha3Code(theISOCode)) {
throw new IllegalArgumentException(
"The input currency code is not 3-letter alphabetic code.");
}
return (Currency) MeasureUnit.internalGetInstance("currency", theISOCode.toUpperCase(Locale.ENGLISH));
}
private static boolean isAlpha3Code(String code) {
if (code.length() != 3) {
return false;
} else {
for (int i = 0; i < 3; i++) {
char ch = code.charAt(i);
if (ch < 'A' || (ch > 'Z' && ch < 'a') || ch > 'z') {
return false;
}
}
}
return true;
}
/**
* Returns a Currency object based on the currency represented by the given java.util.Currency.
*
* @param currency The Java currency object to convert.
* @return An equivalent ICU currency object.
*/
public static Currency fromJavaCurrency(java.util.Currency currency) {
return getInstance(currency.getCurrencyCode());
}
/**
* Returns a java.util.Currency object based on the currency represented by this Currency.
*
* @return An equivalent Java currency object.
*/
public java.util.Currency toJavaCurrency() {
return java.util.Currency.getInstance(getCurrencyCode());
}
/**
* Registers a new currency for the provided locale. The returned object
* is a key that can be used to unregister this currency object.
*
* DISPLAY
locale.
* @see #getName
* @see Category#DISPLAY
*/
public String getSymbol() {
return getSymbol(ULocale.getDefault(Category.DISPLAY));
}
/**
* Convenience and compatibility override of getName that
* requests the symbol name.
* @param loc the Locale for the symbol
* @see #getName
*/
public String getSymbol(Locale loc) {
return getSymbol(ULocale.forLocale(loc));
}
/**
* Convenience and compatibility override of getName that
* requests the symbol name.
* @param uloc the ULocale for the symbol
* @see #getName
*/
public String getSymbol(ULocale uloc) {
return getName(uloc, SYMBOL_NAME, null);
}
/**
* Returns the display name for the given currency in the
* given locale.
* This is a convenient method for
* getName(ULocale, int, boolean[]);
*
* @param locale locale in which to display currency
* @param nameStyle selector for which kind of name to return.
* The nameStyle should be SYMBOL_NAME, NARROW_SYMBOL_NAME,
* or LONG_NAME. Otherwise, throw IllegalArgumentException.
* @param isChoiceFormat isChoiceFormat[0] is always set to false, or isChoiceFormat can be null;
* display names are static strings;
* since ICU 4.4, ChoiceFormat patterns are no longer supported
* @return display string for this currency. If the resource data
* contains no entry for this currency, then the ISO 4217 code is
* returned.
*/
public String getName(Locale locale,
int nameStyle,
boolean[] isChoiceFormat) {
return getName(ULocale.forLocale(locale), nameStyle, isChoiceFormat);
}
/**
* Returns the display name for the given currency in the
* given locale. For example, the display name for the USD
* currency object in the en_US locale is "$".
*
* @param locale locale in which to display currency
* @param nameStyle selector for which kind of name to return.
* The nameStyle should be SYMBOL_NAME, NARROW_SYMBOL_NAME,
* or LONG_NAME. Otherwise, throw IllegalArgumentException.
* @param isChoiceFormat isChoiceFormat[0] is always set to false, or isChoiceFormat can be null;
* display names are static strings;
* since ICU 4.4, ChoiceFormat patterns are no longer supported
* @return display string for this currency. If the resource data
* contains no entry for this currency, then the ISO 4217 code is
* returned.
* getName(Locale.getDefault(), LONG_NAME, null)
.
*
* @return The display name of this currency
* @see #getDisplayName(Locale)
* @see #getName(Locale, int, boolean[])
*/
public String getDisplayName() {
return getName(Locale.getDefault(), LONG_NAME, null);
}
/**
* Returns the display name for this currency in the given locale.
* If the resource data for the given locale contains no entry for this currency,
* then the ISO 4217 code is returned.
* getName(locale, LONG_NAME, null)
.
*
* @param locale locale in which to display currency
* @return The display name of this currency for the specified locale
* @see #getDisplayName(Locale)
* @see #getName(Locale, int, boolean[])
*/
public String getDisplayName(Locale locale) {
return getName(locale, LONG_NAME, null);
}
/**
* Attempt to parse the given string as a currency, either as a
* display name in the given locale, or as a 3-letter ISO 4217
* code. If multiple display names match, then the longest one is
* selected. If both a display name and a 3-letter ISO code
* match, then the display name is preferred, unless it's length
* is less than 3.
*
* @param locale the locale of the display names to match
* @param text the text to parse
* @param type parse against currency type: LONG_NAME only or not
* @param pos input-output position; on input, the position within
* text to match; must have 0 <= pos.getIndex() < text.length();
* on output, the position after the last matched character. If
* the parse fails, the position in unchanged upon output.
* @return the ISO 4217 code, as a string, of the best match, or
* null if there is no match
*
* @deprecated This API is ICU internal only.
* @hide original deprecated declaration
* @hide draft / provisional / internal are hidden on Android
*/
@Deprecated
public static String parse(ULocale locale, String text, int type, ParsePosition pos) {
List> ALL_TENDER_CODES;
private static SoftReference
from
and
* to
. When both from
and to
are null, this method checks if the specified
* currency is available all time.
*
* @param code
* The ISO 4217 3-letter code.
* @param from
* The lower bound of the date range, inclusive. When from
is null, check the availability
* of the currency any date before to
* @param to
* The upper bound of the date range, inclusive. When to
is null, check the availability of
* the currency any date after from
* @return true if the given ISO 4217 3-letter code is supported on the specified date range.
* @throws IllegalArgumentException when to
is before from
.
*/
public static boolean isAvailable(String code, Date from, Date to) {
if (!isAlpha3Code(code)) {
return false;
}
if (from != null && to != null && from.after(to)) {
throw new IllegalArgumentException("To is before from");
}
code = code.toUpperCase(Locale.ENGLISH);
boolean isKnown = getAllCurrenciesAsSet().contains(code);
if (isKnown == false) {
return false;
} else if (from == null && to == null) {
return true;
}
// If caller passed a date range, we cannot rely solely on the cache
CurrencyMetaInfo info = CurrencyMetaInfo.getInstance();
List