• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This code is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License version 2 only, as
8  * published by the Free Software Foundation.  Oracle designates this
9  * particular file as subject to the "Classpath" exception as provided
10  * by Oracle in the LICENSE file that accompanied this code.
11  *
12  * This code is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15  * version 2 for more details (a copy is included in the LICENSE file that
16  * accompanied this code).
17  *
18  * You should have received a copy of the GNU General Public License version
19  * 2 along with this work; if not, write to the Free Software Foundation,
20  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21  *
22  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23  * or visit www.oracle.com if you need additional information or have any
24  * questions.
25  */
26 
27 package java.util;
28 
29 import java.io.Serializable;
30 
31 import libcore.icu.ICU;
32 
33 /**
34  * Represents a currency. Currencies are identified by their ISO 4217 currency
35  * codes. Visit the <a href="http://www.iso.org/iso/en/prods-services/popstds/currencycodes.html">
36  * ISO web site</a> for more information, including a table of
37  * currency codes.
38  * <p>
39  * The class is designed so that there's never more than one
40  * <code>Currency</code> instance for any given currency. Therefore, there's
41  * no public constructor. You obtain a <code>Currency</code> instance using
42  * the <code>getInstance</code> methods.
43  * <p>
44  * Users can supersede the Java runtime currency data by creating a properties
45  * file named <code>&lt;JAVA_HOME&gt;/lib/currency.properties</code>.  The contents
46  * of the properties file are key/value pairs of the ISO 3166 country codes
47  * and the ISO 4217 currency data respectively.  The value part consists of
48  * three ISO 4217 values of a currency, i.e., an alphabetic code, a numeric
49  * code, and a minor unit.  Those three ISO 4217 values are separated by commas.
50  * The lines which start with '#'s are considered comment lines.  For example,
51  * <p>
52  * <code>
53  * #Sample currency properties<br>
54  * JP=JPZ,999,0
55  * </code>
56  * <p>
57  * will supersede the currency data for Japan.
58  *
59  * @since 1.4
60  */
61 public final class Currency implements Serializable {
62 
63     private static final long serialVersionUID = -158308464356906721L;
64 
65     private static HashMap<String, Currency> instances = new HashMap<>();
66 
67     private static HashSet<Currency> available;
68 
69     private transient final android.icu.util.Currency icuCurrency;
70 
71     private final String currencyCode;
72 
73     /**
74      * Constructs a <code>Currency</code> instance. The constructor is private
75      * so that we can insure that there's never more than one instance for a
76      * given currency.
77      */
Currency(android.icu.util.Currency icuCurrency)78     private Currency(android.icu.util.Currency icuCurrency) {
79         this.icuCurrency = icuCurrency;
80         this.currencyCode = icuCurrency.getCurrencyCode();
81     }
82 
83     /**
84      * Returns the <code>Currency</code> instance for the given currency code.
85      *
86      * @param currencyCode the ISO 4217 code of the currency
87      * @return the <code>Currency</code> instance for the given currency code
88      * @exception NullPointerException if <code>currencyCode</code> is null
89      * @exception IllegalArgumentException if <code>currencyCode</code> is not
90      * a supported ISO 4217 code.
91      */
getInstance(String currencyCode)92     public static Currency getInstance(String currencyCode) {
93         synchronized (instances) {
94             Currency instance = instances.get(currencyCode);
95             if (instance == null) {
96                 android.icu.util.Currency icuInstance =
97                         android.icu.util.Currency.getInstance(currencyCode);
98                 if (icuInstance == null) {
99                     return null;
100                 }
101                 instance = new Currency(icuInstance);
102                 instances.put(currencyCode, instance);
103             }
104             return instance;
105         }
106     }
107 
108     /**
109      * Returns the <code>Currency</code> instance for the country of the
110      * given locale. The language and variant components of the locale
111      * are ignored. The result may vary over time, as countries change their
112      * currencies. For example, for the original member countries of the
113      * European Monetary Union, the method returns the old national currencies
114      * until December 31, 2001, and the Euro from January 1, 2002, local time
115      * of the respective countries.
116      * <p>
117      * The method returns <code>null</code> for territories that don't
118      * have a currency, such as Antarctica.
119      *
120      * @param locale the locale for whose country a <code>Currency</code>
121      * instance is needed
122      * @return the <code>Currency</code> instance for the country of the given
123      * locale, or null
124      * @exception NullPointerException if <code>locale</code> or its country
125      * code is null
126      * @exception IllegalArgumentException if the country of the given locale
127      * is not a supported ISO 3166 country code.
128      */
getInstance(Locale locale)129     public static Currency getInstance(Locale locale) {
130         android.icu.util.Currency icuInstance =
131                 android.icu.util.Currency.getInstance(locale);
132         String variant = locale.getVariant();
133         String country = locale.getCountry();
134         if (!variant.isEmpty() && (variant.equals("EURO") || variant.equals("HK") ||
135                 variant.equals("PREEURO"))) {
136             country = country + "_" + variant;
137         }
138         String currencyCode = ICU.getCurrencyCode(country);
139         if (currencyCode == null) {
140             throw new IllegalArgumentException("Unsupported ISO 3166 country: " + locale);
141         }
142         if (icuInstance == null || icuInstance.getCurrencyCode().equals("XXX")) {
143             return null;
144         }
145         return getInstance(currencyCode);
146     }
147 
148     /**
149      * Gets the set of available currencies.  The returned set of currencies
150      * contains all of the available currencies, which may include currencies
151      * that represent obsolete ISO 4217 codes.  The set can be modified
152      * without affecting the available currencies in the runtime.
153      *
154      * @return the set of available currencies.  If there is no currency
155      *    available in the runtime, the returned set is empty.
156      * @since 1.7
157      */
getAvailableCurrencies()158     public static Set<Currency> getAvailableCurrencies() {
159         synchronized (Currency.class) {
160             if (available == null) {
161                 Set<android.icu.util.Currency> icuAvailableCurrencies
162                         = android.icu.util.Currency.getAvailableCurrencies();
163                 available = new HashSet<>();
164                 for (android.icu.util.Currency icuCurrency : icuAvailableCurrencies) {
165                     Currency currency = getInstance(icuCurrency.getCurrencyCode());
166                     if (currency == null) {
167                         currency = new Currency(icuCurrency);
168                         instances.put(currency.currencyCode, currency);
169                     }
170                     available.add(currency);
171                 }
172             }
173             return (Set<Currency>) available.clone();
174         }
175     }
176 
177     /**
178      * Gets the ISO 4217 currency code of this currency.
179      *
180      * @return the ISO 4217 currency code of this currency.
181      */
getCurrencyCode()182     public String getCurrencyCode() {
183         return currencyCode;
184     }
185 
186     /**
187      * Gets the symbol of this currency for the default locale.
188      * For example, for the US Dollar, the symbol is "$" if the default
189      * locale is the US, while for other locales it may be "US$". If no
190      * symbol can be determined, the ISO 4217 currency code is returned.
191      *
192      * @return the symbol of this currency for the default locale
193      */
getSymbol()194     public String getSymbol() {
195         return icuCurrency.getSymbol();
196     }
197 
198     /**
199      * Gets the symbol of this currency for the specified locale.
200      * For example, for the US Dollar, the symbol is "$" if the specified
201      * locale is the US, while for other locales it may be "US$". If no
202      * symbol can be determined, the ISO 4217 currency code is returned.
203      *
204      * @param locale the locale for which a display name for this currency is
205      * needed
206      * @return the symbol of this currency for the specified locale
207      * @exception NullPointerException if <code>locale</code> is null
208      */
getSymbol(Locale locale)209     public String getSymbol(Locale locale) {
210         if (locale == null) {
211             throw new NullPointerException("locale == null");
212         }
213         return icuCurrency.getSymbol(locale);
214     }
215 
216     /**
217      * Gets the default number of fraction digits used with this currency.
218      * For example, the default number of fraction digits for the Euro is 2,
219      * while for the Japanese Yen it's 0.
220      * In the case of pseudo-currencies, such as IMF Special Drawing Rights,
221      * -1 is returned.
222      *
223      * @return the default number of fraction digits used with this currency
224      */
getDefaultFractionDigits()225     public int getDefaultFractionDigits() {
226         if (icuCurrency.getCurrencyCode().equals("XXX")) {
227             return -1;
228         }
229         return icuCurrency.getDefaultFractionDigits();
230     }
231 
232     /**
233      * Returns the ISO 4217 numeric code of this currency.
234      *
235      * @return the ISO 4217 numeric code of this currency
236      * @since 1.7
237      */
getNumericCode()238     public int getNumericCode() {
239         return icuCurrency.getNumericCode();
240     }
241 
242     /**
243      * Gets the name that is suitable for displaying this currency for
244      * the default locale.  If there is no suitable display name found
245      * for the default locale, the ISO 4217 currency code is returned.
246      *
247      * @return the display name of this currency for the default locale
248      * @since 1.7
249      */
getDisplayName()250     public String getDisplayName() {
251         return icuCurrency.getDisplayName();
252     }
253 
254     /**
255      * Gets the name that is suitable for displaying this currency for
256      * the specified locale.  If there is no suitable display name found
257      * for the specified locale, the ISO 4217 currency code is returned.
258      *
259      * @param locale the locale for which a display name for this currency is
260      * needed
261      * @return the display name of this currency for the specified locale
262      * @exception NullPointerException if <code>locale</code> is null
263      * @since 1.7
264      */
getDisplayName(Locale locale)265     public String getDisplayName(Locale locale) {
266         return icuCurrency.getDisplayName(locale);
267     }
268 
269     /**
270      * Returns the ISO 4217 currency code of this currency.
271      *
272      * @return the ISO 4217 currency code of this currency
273      */
toString()274     public String toString() {
275         return icuCurrency.toString();
276     }
277 
278     /**
279      * Resolves instances being deserialized to a single instance per currency.
280      */
readResolve()281     private Object readResolve() {
282         return getInstance(currencyCode);
283     }
284 }
285