| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package java.util; |
| |
| import java.io.Serializable; |
| import libcore.icu.ICU; |
| import libcore.icu.LocaleData; |
| |
| /** |
| * A currency corresponding to an <a href="http://en.wikipedia.org/wiki/ISO_4217">ISO 4217</a> |
| * currency code such as "EUR" or "USD". |
| */ |
| public final class Currency implements Serializable { |
| private static final long serialVersionUID = -158308464356906721L; |
| |
| private static final HashMap<String, Currency> codesToCurrencies = new HashMap<String, Currency>(); |
| private static final HashMap<Locale, Currency> localesToCurrencies = new HashMap<Locale, Currency>(); |
| |
| private final String currencyCode; |
| |
| private Currency(String currencyCode) { |
| this.currencyCode = currencyCode; |
| String symbol = ICU.getCurrencySymbol(Locale.US.toString(), currencyCode); |
| if (symbol == null) { |
| throw new IllegalArgumentException("Unsupported ISO 4217 currency code: " + |
| currencyCode); |
| } |
| } |
| |
| /** |
| * Returns the {@code Currency} instance for the given ISO 4217 currency code. |
| * @throws IllegalArgumentException |
| * if the currency code is not a supported ISO 4217 currency code. |
| */ |
| public static Currency getInstance(String currencyCode) { |
| synchronized (codesToCurrencies) { |
| Currency currency = codesToCurrencies.get(currencyCode); |
| if (currency == null) { |
| currency = new Currency(currencyCode); |
| codesToCurrencies.put(currencyCode, currency); |
| } |
| return currency; |
| } |
| } |
| |
| /** |
| * Returns the {@code Currency} instance for this {@code Locale}'s country. |
| * @throws IllegalArgumentException |
| * if the locale's country is not a supported ISO 3166 country. |
| */ |
| public static Currency getInstance(Locale locale) { |
| synchronized (localesToCurrencies) { |
| Currency currency = localesToCurrencies.get(locale); |
| if (currency != null) { |
| return currency; |
| } |
| String country = locale.getCountry(); |
| String variant = locale.getVariant(); |
| if (!variant.isEmpty() && (variant.equals("EURO") || variant.equals("HK") || |
| variant.equals("PREEURO"))) { |
| country = country + "_" + variant; |
| } |
| |
| String currencyCode = ICU.getCurrencyCode(country); |
| if (currencyCode == null) { |
| throw new IllegalArgumentException("Unsupported ISO 3166 country: " + locale); |
| } else if (currencyCode.equals("XXX")) { |
| return null; |
| } |
| Currency result = getInstance(currencyCode); |
| localesToCurrencies.put(locale, result); |
| return result; |
| } |
| } |
| |
| /** |
| * Returns a set of all known currencies. |
| * @since 1.7 |
| */ |
| public static Set<Currency> getAvailableCurrencies() { |
| Set<Currency> result = new LinkedHashSet<Currency>(); |
| String[] currencyCodes = ICU.getAvailableCurrencyCodes(); |
| for (String currencyCode : currencyCodes) { |
| result.add(Currency.getInstance(currencyCode)); |
| } |
| return result; |
| } |
| |
| /** |
| * Returns this currency's ISO 4217 currency code. |
| */ |
| public String getCurrencyCode() { |
| return currencyCode; |
| } |
| |
| /** |
| * Equivalent to {@code getDisplayName(Locale.getDefault())}. |
| * See "<a href="../util/Locale.html#default_locale">Be wary of the default locale</a>". |
| * @since 1.7 |
| */ |
| public String getDisplayName() { |
| return getDisplayName(Locale.getDefault()); |
| } |
| |
| /** |
| * Returns the localized name of this currency in the given {@code locale}. |
| * Returns the ISO 4217 currency code if no localized name is available. |
| * @since 1.7 |
| */ |
| public String getDisplayName(Locale locale) { |
| return ICU.getCurrencyDisplayName(locale.toString(), currencyCode); |
| } |
| |
| /** |
| * Returns the ISO 4217 numeric code for this currency. If there is no standard numeric code a |
| * zero is returned. |
| * |
| * @since 1.7 |
| * @hide Until ready for an API update |
| */ |
| public int getNumericCode() { |
| return ICU.getCurrencyNumericCode(currencyCode); |
| } |
| |
| /** |
| * Equivalent to {@code getSymbol(Locale.getDefault())}. |
| * See "<a href="../util/Locale.html#default_locale">Be wary of the default locale</a>". |
| */ |
| public String getSymbol() { |
| return getSymbol(Locale.getDefault()); |
| } |
| |
| /** |
| * Returns the localized currency symbol for this currency in {@code locale}. |
| * That is, given "USD" and Locale.US, you'd get "$", but given "USD" and a non-US locale, |
| * you'd get "US$". |
| * |
| * <p>If the locale only specifies a language rather than a language and a country (such as |
| * {@code Locale.JAPANESE} or {new Locale("en", "")} rather than {@code Locale.JAPAN} or |
| * {new Locale("en", "US")}), the ISO 4217 currency code is returned. |
| * |
| * <p>If there is no locale-specific currency symbol, the ISO 4217 currency code is returned. |
| */ |
| public String getSymbol(Locale locale) { |
| if (locale.getCountry().length() == 0) { |
| return currencyCode; |
| } |
| |
| // Check the locale first, in case the locale has the same currency. |
| LocaleData localeData = LocaleData.get(locale); |
| if (localeData.internationalCurrencySymbol.equals(currencyCode)) { |
| return localeData.currencySymbol; |
| } |
| |
| // Try ICU, and fall back to the currency code if ICU has nothing. |
| String symbol = ICU.getCurrencySymbol(locale.toString(), currencyCode); |
| return symbol != null ? symbol : currencyCode; |
| } |
| |
| /** |
| * Returns the default number of fraction digits for this currency. |
| * For instance, the default number of fraction digits for the US dollar is 2 because there are |
| * 100 US cents in a US dollar. For the Japanese Yen, the number is 0 because coins smaller |
| * than 1 Yen became invalid in 1953. In the case of pseudo-currencies, such as |
| * IMF Special Drawing Rights, -1 is returned. |
| */ |
| public int getDefaultFractionDigits() { |
| // In some places the code XXX is used as the fall back currency. |
| // The RI returns -1, but ICU defaults to 2 for unknown currencies. |
| if (currencyCode.equals("XXX")) { |
| return -1; |
| } |
| return ICU.getCurrencyFractionDigits(currencyCode); |
| } |
| |
| /** |
| * Returns this currency's ISO 4217 currency code. |
| */ |
| @Override |
| public String toString() { |
| return currencyCode; |
| } |
| |
| private Object readResolve() { |
| return getInstance(currencyCode); |
| } |
| } |