• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
2   *  Licensed to the Apache Software Foundation (ASF) under one or more
3   *  contributor license agreements.  See the NOTICE file distributed with
4   *  this work for additional information regarding copyright ownership.
5   *  The ASF licenses this file to You under the Apache License, Version 2.0
6   *  (the "License"); you may not use this file except in compliance with
7   *  the License.  You may obtain a copy of the License at
8   *
9   *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   *  Unless required by applicable law or agreed to in writing, software
12   *  distributed under the License is distributed on an "AS IS" BASIS,
13   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   *  See the License for the specific language governing permissions and
15   *  limitations under the License.
16   */
17  
18  package java.util;
19  
20  import java.io.Serializable;
21  import libcore.icu.ICU;
22  import libcore.icu.LocaleData;
23  
24  /**
25   * A currency corresponding to an <a href="http://en.wikipedia.org/wiki/ISO_4217">ISO 4217</a>
26   * currency code such as "EUR" or "USD".
27   */
28  public final class Currency implements Serializable {
29      private static final long serialVersionUID = -158308464356906721L;
30  
31      private static final HashMap<String, Currency> codesToCurrencies = new HashMap<String, Currency>();
32      private static final HashMap<Locale, Currency> localesToCurrencies = new HashMap<Locale, Currency>();
33  
34      private final String currencyCode;
35  
Currency(String currencyCode)36      private Currency(String currencyCode) {
37          this.currencyCode = currencyCode;
38          String symbol = ICU.getCurrencySymbol(Locale.US.toString(), currencyCode);
39          if (symbol == null) {
40              throw new IllegalArgumentException("Unsupported ISO 4217 currency code: " +
41                      currencyCode);
42          }
43      }
44  
45      /**
46       * Returns the {@code Currency} instance for the given ISO 4217 currency code.
47       * @throws IllegalArgumentException
48       *             if the currency code is not a supported ISO 4217 currency code.
49       */
getInstance(String currencyCode)50      public static Currency getInstance(String currencyCode) {
51          synchronized (codesToCurrencies) {
52              Currency currency = codesToCurrencies.get(currencyCode);
53              if (currency == null) {
54                  currency = new Currency(currencyCode);
55                  codesToCurrencies.put(currencyCode, currency);
56              }
57              return currency;
58          }
59      }
60  
61      /**
62       * Returns the {@code Currency} instance for this {@code Locale}'s country.
63       * @throws IllegalArgumentException
64       *             if the locale's country is not a supported ISO 3166 country.
65       */
getInstance(Locale locale)66      public static Currency getInstance(Locale locale) {
67          synchronized (localesToCurrencies) {
68              Currency currency = localesToCurrencies.get(locale);
69              if (currency != null) {
70                  return currency;
71              }
72              String country = locale.getCountry();
73              String variant = locale.getVariant();
74              if (!variant.isEmpty() && (variant.equals("EURO") || variant.equals("HK") ||
75                      variant.equals("PREEURO"))) {
76                  country = country + "_" + variant;
77              }
78  
79              String currencyCode = ICU.getCurrencyCode(country);
80              if (currencyCode == null) {
81                  throw new IllegalArgumentException("Unsupported ISO 3166 country: " + locale);
82              } else if (currencyCode.equals("None")) {
83                  return null;
84              }
85              Currency result = getInstance(currencyCode);
86              localesToCurrencies.put(locale, result);
87              return result;
88          }
89      }
90  
91      /**
92       * Returns a set of all known currencies.
93       * @since 1.7
94       * @hide 1.7
95       */
getAvailableCurrencies()96      public static Set<Currency> getAvailableCurrencies() {
97          Set<Currency> result = new LinkedHashSet<Currency>();
98          String[] currencyCodes = ICU.getAvailableCurrencyCodes();
99          for (String currencyCode : currencyCodes) {
100              result.add(Currency.getInstance(currencyCode));
101          }
102          return result;
103      }
104  
105      /**
106       * Returns this currency's ISO 4217 currency code.
107       */
getCurrencyCode()108      public String getCurrencyCode() {
109          return currencyCode;
110      }
111  
112      /**
113       * Equivalent to {@code getDisplayName(Locale.getDefault())}.
114       * See "<a href="../util/Locale.html#default_locale">Be wary of the default locale</a>".
115       * @since 1.7
116       * @hide 1.7
117       */
getDisplayName()118      public String getDisplayName() {
119          return getDisplayName(Locale.getDefault());
120      }
121  
122      /**
123       * Returns the localized name of this currency in the given {@code locale}.
124       * Returns the ISO 4217 currency code if no localized name is available.
125       * @since 1.7
126       * @hide 1.7
127       */
getDisplayName(Locale locale)128      public String getDisplayName(Locale locale) {
129          return ICU.getCurrencyDisplayName(locale.toString(), currencyCode);
130      }
131  
132      /**
133       * Equivalent to {@code getSymbol(Locale.getDefault())}.
134       * See "<a href="../util/Locale.html#default_locale">Be wary of the default locale</a>".
135       */
getSymbol()136      public String getSymbol() {
137          return getSymbol(Locale.getDefault());
138      }
139  
140      /**
141       * Returns the localized currency symbol for this currency in {@code locale}.
142       * That is, given "USD" and Locale.US, you'd get "$", but given "USD" and a non-US locale,
143       * you'd get "US$".
144       *
145       * <p>If the locale only specifies a language rather than a language and a country (such as
146       * {@code Locale.JAPANESE} or {new Locale("en", "")} rather than {@code Locale.JAPAN} or
147       * {new Locale("en", "US")}), the ISO 4217 currency code is returned.
148       *
149       * <p>If there is no locale-specific currency symbol, the ISO 4217 currency code is returned.
150       */
getSymbol(Locale locale)151      public String getSymbol(Locale locale) {
152          if (locale.getCountry().length() == 0) {
153              return currencyCode;
154          }
155  
156          // Check the locale first, in case the locale has the same currency.
157          LocaleData localeData = LocaleData.get(locale);
158          if (localeData.internationalCurrencySymbol.equals(currencyCode)) {
159              return localeData.currencySymbol;
160          }
161  
162          // Try ICU, and fall back to the currency code if ICU has nothing.
163          String symbol = ICU.getCurrencySymbol(locale.toString(), currencyCode);
164          return symbol != null ? symbol : currencyCode;
165      }
166  
167      /**
168       * Returns the default number of fraction digits for this currency.
169       * For instance, the default number of fraction digits for the US dollar is 2 because there are
170       * 100 US cents in a US dollar. For the Japanese Yen, the number is 0 because coins smaller
171       * than 1 Yen became invalid in 1953. In the case of pseudo-currencies, such as
172       * IMF Special Drawing Rights, -1 is returned.
173       */
getDefaultFractionDigits()174      public int getDefaultFractionDigits() {
175          // In some places the code XXX is used as the fall back currency.
176          // The RI returns -1, but ICU defaults to 2 for unknown currencies.
177          if (currencyCode.equals("XXX")) {
178              return -1;
179          }
180          return ICU.getCurrencyFractionDigits(currencyCode);
181      }
182  
183      /**
184       * Returns this currency's ISO 4217 currency code.
185       */
186      @Override
toString()187      public String toString() {
188          return currencyCode;
189      }
190  
readResolve()191      private Object readResolve() {
192          return getInstance(currencyCode);
193      }
194  }
195