getInstance()
methods rather than by using
* a constructor.
*
* @see java.util.Locale
* @author Guilhem Lavaux Currency
instances to
* ensure the singleton nature of this class. The key
* is the locale of the currency.
*
* @see #getInstance(java.util.Locale)
* @see #readResolve()
* @serial ignored.
*/
private static transient Map cache;
/**
* Instantiates the cache.
*/
static
{
cache = new HashMap();
}
/**
* Default constructor for deserialization
*/
private Currency ()
{
}
/**
* Constructor to create a Currency
object
* for a particular Locale
.
* All components of the given locale, other than the
* country code, are ignored. The results of calling this
* method may vary over time, as the currency associated with
* a particular country changes. For countries without
* a given currency (e.g. Antarctica), the result is null.
*
* @param loc the locale for the new currency.
*/
private Currency (Locale loc)
{
this.locale = loc;
this.res = ResourceBundle.getBundle ("gnu.java.locale.LocaleInformation",
locale, ClassLoader.getSystemClassLoader());
/* Retrieve the ISO4217 currency code */
try
{
currencyCode = res.getString ("intlCurrencySymbol");
}
catch (Exception _)
{
currencyCode = null;
}
}
/**
* Returns the ISO4217 currency code of this currency.
*
* @return a String
containing currency code.
*/
public String getCurrencyCode ()
{
return currencyCode;
}
/**
* Returns the number of digits which occur after the decimal point
* for this particular currency. For example, currencies such
* as the U.S. dollar, the Euro and the Great British pound have two
* digits following the decimal point to indicate the value which exists
* in the associated lower-valued coinage (cents in the case of the first
* two, pennies in the latter). Some currencies such as the Japanese
* Yen have no digits after the decimal point. In the case of pseudo
* currencies, such as IMF Special Drawing Rights, -1 is returned.
*
* @return the number of digits after the decimal separator for this currency.
*/
public int getDefaultFractionDigits ()
{
NumberFormat currency = NumberFormat.getCurrencyInstance (locale);
return currency.getMaximumFractionDigits();
}
/**
* Builds a new currency instance for this locale.
* All components of the given locale, other than the
* country code, are ignored. The results of calling this
* method may vary over time, as the currency associated with
* a particular country changes. For countries without
* a given currency (e.g. Antarctica), the result is null.
*
* @param locale a Locale
instance.
* @return a new Currency
instance.
* @throws NullPointerException if the locale or its
* country code is null.
* @throws IllegalArgumentException if the country of
* the given locale is not a supported ISO3166 code.
*/
public static Currency getInstance (Locale locale)
{
/**
* The new instance must be the only available instance
* for the currency it supports. We ensure this happens,
* while maintaining a suitable performance level, by
* creating the appropriate object on the first call to
* this method, and returning the cached instance on
* later calls.
*/
Currency newCurrency;
/* Attempt to get the currency from the cache */
newCurrency = (Currency) cache.get(locale);
if (newCurrency == null)
{
/* Create the currency for this locale */
newCurrency = new Currency (locale);
/* Cache it */
cache.put(locale, newCurrency);
}
/* Return the instance */
return newCurrency;
}
/**
* Builds the currency corresponding to the specified currency code.
*
* @param currencyCode a string representing a currency code.
* @return a new Currency
instance.
* @throws NullPointerException if currencyCode is null.
* @throws IllegalArgumentException if the supplied currency code
* is not a supported ISO 4217 code.
*/
public static Currency getInstance (String currencyCode)
{
Locale[] allLocales = Locale.getAvailableLocales ();
for (int i = 0;i < allLocales.length; i++)
{
Currency testCurrency = getInstance (allLocales[i]);
if (testCurrency.getCurrencyCode() != null &&
testCurrency.getCurrencyCode().equals(currencyCode))
return testCurrency;
}
/*
* If we get this far, the code is not supported by any of
* our locales.
*/
throw new IllegalArgumentException("The currency code, " + currencyCode +
", is not supported.");
}
/**
* This method returns the symbol which precedes or follows a
* value in this particular currency. In cases where there is no
* such symbol for the currency, the ISO 4217 currency
* code is returned.
*
* @return the currency symbol, or the ISO 4217 currency code if
* one doesn't exist.
*/
public String getSymbol()
{
try
{
/* What does this return if there is no mapping? */
return res.getString ("currencySymbol");
}
catch (Exception _)
{
return null;
}
}
/**
* * This method returns the symbol which precedes or follows a * value in this particular currency. The returned value is * the symbol used to denote the currency in the specified locale. *
*
* For example, a supplied locale may specify a different symbol
* for the currency, due to conflicts with its own currency.
* This would be the case with the American currency, the dollar.
* Locales that also use a dollar-based currency (e.g. Canada, Australia)
* need to differentiate the American dollar using 'US$' rather than '$'.
* So, supplying one of these locales to getSymbol()
would
* return this value, rather than the standard '$'.
*
* In cases where there is no such symbol for a particular currency, * the ISO 4217 currency code is returned. *
* * @param locale the locale to express the symbol in. * @return the currency symbol, or the ISO 4217 currency code if * one doesn't exist. * @throws NullPointerException if the locale is null. */ public String getSymbol(Locale locale) { // TODO. The behaviour is unclear if locale != this.locale. // First we need to implement fully LocaleInformation*.java /* * FIXME: My reading of how this method works has this implementation * as wrong. It should return a value relating to how the specified * locale handles the symbol for this currency. This implementation * seems to just do a variation of getInstance(locale). */ 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; } } } /** * Returns the international ISO4217 currency code of this currency. * * @return aString
containing the ISO4217 currency code.
*/
public String toString()
{
return getCurrencyCode();
}
/**
* Resolves the deserialized object to the singleton instance for its
* particular currency. The currency code of the deserialized instance
* is used to return the correct instance.
*
* @return the singleton instance for the currency specified by the
* currency code of the deserialized object. This replaces
* the deserialized object as the returned object from
* deserialization.
* @throws ObjectStreamException if a problem occurs with deserializing
* the object.
*/
private Object readResolve()
throws ObjectStreamException
{
return getInstance(currencyCode);
}
}