37 |
|
|
38 |
package java.util; |
package java.util; |
39 |
|
|
40 |
|
import java.io.IOException; |
41 |
import java.io.ObjectStreamException; |
import java.io.ObjectStreamException; |
42 |
import java.io.Serializable; |
import java.io.Serializable; |
43 |
import java.text.NumberFormat; |
import java.util.Properties; |
44 |
|
|
45 |
/** |
/** |
46 |
* Representation of a currency for a particular locale. Each currency |
* Representation of a currency for a particular locale. Each currency |
65 |
static final long serialVersionUID = -158308464356906721L; |
static final long serialVersionUID = -158308464356906721L; |
66 |
|
|
67 |
/** |
/** |
68 |
* The locale associated with this currency. |
* The set of properties which map a currency to |
69 |
* |
* the currency information such as the ISO 4217 |
70 |
* @see #Currency(java.util.Locale) |
* currency code and the number of decimal points. |
|
* @see #getInstance(java.util.Locale) |
|
|
* @see #getSymbol(java.util.Locale) |
|
|
* @serial ignored. |
|
|
*/ |
|
|
private transient Locale locale; |
|
|
|
|
|
/** |
|
|
* The resource bundle which maps the currency to |
|
|
* a ISO 4217 currency code. |
|
71 |
* |
* |
72 |
* @see #getCurrencyCode() |
* @see #getCurrencyCode() |
73 |
* @serial ignored. |
* @serial ignored. |
74 |
*/ |
*/ |
75 |
private transient ResourceBundle res; |
private static transient Properties properties; |
76 |
|
|
77 |
/** |
/** |
78 |
* The ISO 4217 currency code associated with this |
* The ISO 4217 currency code associated with this |
84 |
private String currencyCode; |
private String currencyCode; |
85 |
|
|
86 |
/** |
/** |
87 |
|
* The number of fraction digits associated with this |
88 |
|
* particular instance. |
89 |
|
* |
90 |
|
* @see #getDefaultFractionDigits() |
91 |
|
* @serial the number of fraction digits |
92 |
|
*/ |
93 |
|
private transient int fractionDigits; |
94 |
|
|
95 |
|
/** |
96 |
* A cache of <code>Currency</code> instances to |
* A cache of <code>Currency</code> instances to |
97 |
* ensure the singleton nature of this class. The key |
* ensure the singleton nature of this class. The key |
98 |
* is the locale of the currency. |
* is the locale of the currency. |
104 |
private static transient Map cache; |
private static transient Map cache; |
105 |
|
|
106 |
/** |
/** |
107 |
* Instantiates the cache. |
* Instantiates the cache and reads in the properties. |
108 |
*/ |
*/ |
109 |
static |
static |
110 |
{ |
{ |
111 |
|
/* Create a hash map for the cache */ |
112 |
cache = new HashMap(); |
cache = new HashMap(); |
113 |
|
/* Create the properties object */ |
114 |
|
properties = new Properties(); |
115 |
|
/* Try and load the properties from our iso4217.properties resource */ |
116 |
|
try |
117 |
|
{ |
118 |
|
properties.load(Currency.class.getResourceAsStream("iso4217.properties")); |
119 |
|
} |
120 |
|
catch (IOException exception) |
121 |
|
{ |
122 |
|
System.out.println("Failed to load currency resource: " + exception); |
123 |
|
} |
124 |
} |
} |
125 |
|
|
126 |
/** |
/** |
127 |
* Default constructor for deserialization |
* Default constructor for deserialization |
128 |
*/ |
*/ |
129 |
private Currency () |
private Currency() |
130 |
{ |
{ |
131 |
} |
} |
132 |
|
|
139 |
* a particular country changes. For countries without |
* a particular country changes. For countries without |
140 |
* a given currency (e.g. Antarctica), the result is null. |
* a given currency (e.g. Antarctica), the result is null. |
141 |
* |
* |
142 |
* @param loc the locale for the new currency. |
* @param loc the locale for the new currency, or null if |
143 |
|
* there is no country code specified or a currency |
144 |
|
* for this country. |
145 |
*/ |
*/ |
146 |
private Currency (Locale loc) |
private Currency(Locale loc) |
147 |
{ |
{ |
148 |
this.locale = loc; |
String countryCode; |
149 |
this.res = ResourceBundle.getBundle ("gnu.java.locale.LocaleInformation", |
String currencyKey; |
150 |
locale, ClassLoader.getSystemClassLoader()); |
String fractionDigitsKey; |
151 |
/* Retrieve the ISO4217 currency code */ |
int commaPosition; |
152 |
try |
|
153 |
|
/* Retrieve the country code from the locale */ |
154 |
|
countryCode = loc.getCountry(); |
155 |
|
/* If there is no country code, return */ |
156 |
|
if (countryCode.equals("")) |
157 |
|
{ |
158 |
|
return; |
159 |
|
} |
160 |
|
/* Construct the key for the currency */ |
161 |
|
currencyKey = countryCode + ".currency"; |
162 |
|
/* Construct the key for the fraction digits */ |
163 |
|
fractionDigitsKey = countryCode + ".fractionDigits"; |
164 |
|
/* Retrieve the currency */ |
165 |
|
currencyCode = properties.getProperty(currencyKey); |
166 |
|
/* Return if the currency code is null */ |
167 |
|
if (currencyCode == null) |
168 |
{ |
{ |
169 |
currencyCode = res.getString ("intlCurrencySymbol"); |
return; |
170 |
} |
} |
171 |
catch (Exception _) |
/* Split off the first currency code (we only use the first for now) */ |
172 |
|
commaPosition = currencyCode.indexOf(","); |
173 |
|
if (commaPosition != -1) |
174 |
{ |
{ |
175 |
currencyCode = null; |
currencyCode = currencyCode.substring(0, commaPosition); |
176 |
} |
} |
177 |
|
/* Retrieve the fraction digits */ |
178 |
|
fractionDigits = Integer.parseInt(properties.getProperty(fractionDigitsKey)); |
179 |
} |
} |
180 |
|
|
181 |
/** |
/** |
183 |
* |
* |
184 |
* @return a <code>String</code> containing currency code. |
* @return a <code>String</code> containing currency code. |
185 |
*/ |
*/ |
186 |
public String getCurrencyCode () |
public String getCurrencyCode() |
187 |
{ |
{ |
188 |
return currencyCode; |
return currencyCode; |
189 |
} |
} |
200 |
* |
* |
201 |
* @return the number of digits after the decimal separator for this currency. |
* @return the number of digits after the decimal separator for this currency. |
202 |
*/ |
*/ |
203 |
public int getDefaultFractionDigits () |
public int getDefaultFractionDigits() |
204 |
{ |
{ |
205 |
NumberFormat currency = NumberFormat.getCurrencyInstance (locale); |
return fractionDigits; |
|
|
|
|
return currency.getMaximumFractionDigits(); |
|
206 |
} |
} |
207 |
|
|
208 |
/** |
/** |
220 |
* @throws IllegalArgumentException if the country of |
* @throws IllegalArgumentException if the country of |
221 |
* the given locale is not a supported ISO3166 code. |
* the given locale is not a supported ISO3166 code. |
222 |
*/ |
*/ |
223 |
public static Currency getInstance (Locale locale) |
public static Currency getInstance(Locale locale) |
224 |
{ |
{ |
225 |
/** |
/** |
226 |
* The new instance must be the only available instance |
* The new instance must be the only available instance |
238 |
{ |
{ |
239 |
/* Create the currency for this locale */ |
/* Create the currency for this locale */ |
240 |
newCurrency = new Currency (locale); |
newCurrency = new Currency (locale); |
241 |
/* Cache it */ |
/* |
242 |
cache.put(locale, newCurrency); |
* If the currency code is null, then creation failed |
243 |
|
* and we return null. |
244 |
|
*/ |
245 |
|
if (newCurrency.getCurrencyCode() == null) |
246 |
|
{ |
247 |
|
return null; |
248 |
|
} |
249 |
|
else |
250 |
|
{ |
251 |
|
/* Cache it */ |
252 |
|
cache.put(locale, newCurrency); |
253 |
|
} |
254 |
} |
} |
255 |
/* Return the instance */ |
/* Return the instance */ |
256 |
return newCurrency; |
return newCurrency; |
265 |
* @throws IllegalArgumentException if the supplied currency code |
* @throws IllegalArgumentException if the supplied currency code |
266 |
* is not a supported ISO 4217 code. |
* is not a supported ISO 4217 code. |
267 |
*/ |
*/ |
268 |
public static Currency getInstance (String currencyCode) |
public static Currency getInstance(String currencyCode) |
269 |
{ |
{ |
270 |
Locale[] allLocales = Locale.getAvailableLocales (); |
Locale[] allLocales; |
271 |
|
|
272 |
|
/* |
273 |
|
* Throw a null pointer exception explicitly if currencyCode is null. |
274 |
|
* One is not thrown otherwise. It results in an IllegalArgumentException. |
275 |
|
*/ |
276 |
|
if (currencyCode == null) |
277 |
|
{ |
278 |
|
throw new NullPointerException("The supplied currency code is null."); |
279 |
|
} |
280 |
|
/* Get all locales */ |
281 |
|
allLocales = Locale.getAvailableLocales(); |
282 |
|
/* Loop through each locale, looking for the code */ |
283 |
for (int i = 0;i < allLocales.length; i++) |
for (int i = 0;i < allLocales.length; i++) |
284 |
{ |
{ |
285 |
Currency testCurrency = getInstance (allLocales[i]); |
Currency testCurrency = getInstance (allLocales[i]); |
286 |
|
|
287 |
if (testCurrency.getCurrencyCode() != null && |
if (testCurrency != null && |
288 |
testCurrency.getCurrencyCode().equals(currencyCode)) |
testCurrency.getCurrencyCode().equals(currencyCode)) |
289 |
return testCurrency; |
return testCurrency; |
290 |
} |
} |
307 |
*/ |
*/ |
308 |
public String getSymbol() |
public String getSymbol() |
309 |
{ |
{ |
310 |
try |
/* |
311 |
{ |
We don't currently have the currency symbols, so we always |
312 |
/* What does this return if there is no mapping? */ |
return the currency code. |
313 |
return res.getString ("currencySymbol"); |
*/ |
314 |
} |
return getCurrencyCode(); |
|
catch (Exception _) |
|
|
{ |
|
|
return null; |
|
|
} |
|
315 |
} |
} |
316 |
|
|
317 |
/** |
/** |
341 |
*/ |
*/ |
342 |
public String getSymbol(Locale locale) |
public String getSymbol(Locale locale) |
343 |
{ |
{ |
|
// TODO. The behaviour is unclear if locale != this.locale. |
|
|
// First we need to implement fully LocaleInformation*.java |
|
|
|
|
344 |
/* |
/* |
345 |
* FIXME: My reading of how this method works has this implementation |
We don't currently have the currency symbols, so we always |
346 |
* as wrong. It should return a value relating to how the specified |
return the currency code. |
347 |
* locale handles the symbol for this currency. This implementation |
*/ |
348 |
* seems to just do a variation of getInstance(locale). |
return getCurrencyCode(); |
|
*/ |
|
|
try |
|
|
{ |
|
|
ResourceBundle localeResource = |
|
|
ResourceBundle.getBundle ("gnu.java.locale.LocaleInformation", |
|
|
locale, Currency.class.getClassLoader()); |
|
|
|
|
|
if (localeResource.equals(res)) |
|
|
return localeResource.getString ("currencySymbol"); |
|
|
else |
|
|
return localeResource.getString ("intlCurrencySymbol"); |
|
|
} |
|
|
catch (Exception e1) |
|
|
{ |
|
|
try |
|
|
{ |
|
|
return res.getString ("intlCurrencySymbol"); |
|
|
} |
|
|
catch (Exception e2) |
|
|
{ |
|
|
return null; |
|
|
} |
|
|
} |
|
349 |
} |
} |
350 |
|
|
351 |
/** |
/** |