/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* Represents a currency. Currencies are identified by their ISO 4217 currency
* codes. Visit the <a href="http://www.iso.org/iso/en/prods-services/popstds/currencycodes.html">
* ISO web site</a> for more information, including a table of
* currency codes.
* <p>
* The class is designed so that there's never more than one
* <code>Currency</code> instance for any given currency. Therefore, there's
* no public constructor. You obtain a <code>Currency</code> instance using
* the <code>getInstance</code> methods.
* <p>
* Users can supersede the Java runtime currency data by creating a properties
* file named <code><JAVA_HOME>/lib/currency.properties</code>. The contents
* and the ISO 4217 currency data respectively. The value part consists of
* three ISO 4217 values of a currency, i.e., an alphabetic code, a numeric
* code, and a minor unit. Those three ISO 4217 values are separated by commas.
* The lines which start with '#'s are considered comment lines. For example,
* <p>
* <code>
* #Sample currency properties<br>
* JP=JPZ,999,0
* </code>
* <p>
* will supersede the currency data for Japan.
*
* @since 1.4
*/
/**
* ISO 4217 currency code for this currency.
*
* @serial
*/
/**
* Default fraction digits for this currency.
* Set from currency data tables.
*/
transient private final int defaultFractionDigits;
/**
* ISO 4217 numeric code for this currency.
* Set from currency data tables.
*/
transient private final int numericCode;
// class data: instance map
// Class data: currency data obtained from currency.data file.
// Purpose:
// - determine valid country codes
// - determine valid currency codes
// - map country codes to currency codes
// - obtain default fraction digits for currency codes
//
// sc = special case; dfd = default fraction digits
// Simple countries are those where the country code is a prefix of the
// currency code, and there are no known plans to change the currency.
//
// table formats:
// - mainTable:
// - maps country code to 32-bit int
// - 26*26 entries, corresponding to [A-Z]*[A-Z]
// - \u007F -> not valid country
// - bits 18-31: unused
// - bits 8-17: numeric code (0 to 1023)
// - bit 7: 1 - special case, bits 0-4 indicate which one
// 0 - simple country, bits 0-4 indicate final char of currency code
// - bits 5-6: fraction digits for simple countries, 0 for special cases
// - bits 0-4: final char for currency code for simple country, or ID of special case
// - special case IDs:
// - 0: country has no currency
// - other: index into sc* arrays + 1
// - scCutOverTimes: cut-over time in millis as returned by
// System.currentTimeMillis for special case countries that are changing
// currencies; Long.MAX_VALUE for countries that are not changing currencies
// - scOldCurrencies: old currencies for special case countries
// - scNewCurrencies: new currencies for special case countries that are
// changing currencies; null for others
// - scOldCurrenciesDFD: default fraction digits for old currencies
// - scNewCurrenciesDFD: default fraction digits for new currencies, 0 for
// countries that are not changing currencies
// - otherCurrencies: concatenation of all currency codes that are not the
// main currency of a simple country, separated by "-"
// - otherCurrenciesDFD: decimal format digits for currencies in otherCurrencies, same order
static int formatVersion;
static int dataVersion;
static int[] mainTable;
static long[] scCutOverTimes;
static int[] scOldCurrenciesDFD;
static int[] scNewCurrenciesDFD;
static int[] scOldCurrenciesNumericCode;
static int[] scNewCurrenciesNumericCode;
static int[] otherCurrenciesDFD;
static int[] otherCurrenciesNumericCode;
// handy constants - must match definitions in GenerateCurrencyData
// magic number
// number of characters from A to Z
// entry for invalid country codes
// entry for countries without currency
// mask for simple case country entries
// mask for simple case country entry final character
// mask for simple case country entry default currency digits
// shift count for simple case country entry default currency digits
// mask for special case country entries
// mask for special case country index
// delta from entry index component in main table to index into special case tables
// mask for distinguishing simple and special case countries
// mask for the numeric code of the currency
// shift count for the numeric code of the currency
// Currency data format version
static {
try {
new BufferedInputStream(
new FileInputStream(dataFile)));
throw new InternalError("Currency data is possibly corrupted");
}
if (formatVersion != VALID_FORMAT_VERSION) {
throw new InternalError("Currency data format is incorrect");
}
} catch (IOException e) {
throw ie;
}
// look for the properties file for overrides
try {
}
}
}
} catch (IOException e) {
info("currency.properties is ignored because of an IOException", e);
}
return null;
}
});
}
/**
* Constants for retrieving localized names from the name providers.
*/
/**
* Constructs a <code>Currency</code> instance. The constructor is private
* so that we can insure that there's never more than one instance for a
* given currency.
*/
this.currencyCode = currencyCode;
this.numericCode = numericCode;
}
/**
* Returns the <code>Currency</code> instance for the given currency code.
*
* @param currencyCode the ISO 4217 code of the currency
* @return the <code>Currency</code> instance for the given currency code
* @exception NullPointerException if <code>currencyCode</code> is null
* @exception IllegalArgumentException if <code>currencyCode</code> is not
* a supported ISO 4217 code.
*/
}
int numericCode) {
synchronized (instances) {
// Try to look up the currency code in the instances table.
// This does the null pointer check as a side effect.
// Also, if there already is an entry, the currencyCode must be valid.
return instance;
}
// Currency code not internally generated, need to verify first
// A currency code must have 3 characters and exist in the main table
// or in the list of other currencies.
throw new IllegalArgumentException();
}
defaultFractionDigits = (tableEntry & SIMPLE_CASE_COUNTRY_DEFAULT_DIGITS_MASK) >> SIMPLE_CASE_COUNTRY_DEFAULT_DIGITS_SHIFT;
} else {
// Check for '-' separately so we don't get false hits in the table.
throw new IllegalArgumentException();
}
if (index == -1) {
throw new IllegalArgumentException();
}
}
}
return instance;
}
}
/**
* Returns the <code>Currency</code> instance for the country of the
* given locale. The language and variant components of the locale
* are ignored. The result may vary over time, as countries change their
* currencies. For example, for the original member countries of the
* European Monetary Union, the method returns the old national currencies
* until December 31, 2001, and the Euro from January 1, 2002, local time
* of the respective countries.
* <p>
* The method returns <code>null</code> for territories that don't
* have a currency, such as Antarctica.
*
* @param locale the locale for whose country a <code>Currency</code>
* instance is needed
* @return the <code>Currency</code> instance for the country of the given
* locale, or null
* @exception NullPointerException if <code>locale</code> or its country
* code is null
* @exception IllegalArgumentException if the country of the given locale
* is not a supported ISO 3166 country code.
*/
throw new NullPointerException();
}
throw new IllegalArgumentException();
}
&& tableEntry != INVALID_COUNTRY_ENTRY) {
int defaultFractionDigits = (tableEntry & SIMPLE_CASE_COUNTRY_DEFAULT_DIGITS_MASK) >> SIMPLE_CASE_COUNTRY_DEFAULT_DIGITS_SHIFT;
} else {
// special cases
if (tableEntry == INVALID_COUNTRY_ENTRY) {
throw new IllegalArgumentException();
}
if (tableEntry == COUNTRY_WITHOUT_CURRENCY_ENTRY) {
return null;
} else {
if (scCutOverTimes[index] == Long.MAX_VALUE || System.currentTimeMillis() < scCutOverTimes[index]) {
} else {
}
}
}
}
/**
* Gets the set of available currencies. The returned set of currencies
* contains all of the available currencies, which may include currencies
* that represent obsolete ISO 4217 codes. The set can be modified
* without affecting the available currencies in the runtime.
*
* @return the set of available currencies. If there is no currency
* available in the runtime, the returned set is empty.
* @since 1.7
*/
synchronized(Currency.class) {
// Add simple currencies first
&& tableEntry != INVALID_COUNTRY_ENTRY) {
int defaultFractionDigits = (tableEntry & SIMPLE_CASE_COUNTRY_DEFAULT_DIGITS_MASK) >> SIMPLE_CASE_COUNTRY_DEFAULT_DIGITS_SHIFT;
}
}
}
// Now add other currencies
while (st.hasMoreElements()) {
}
}
}
@SuppressWarnings("unchecked")
return result;
}
/**
* Gets the ISO 4217 currency code of this currency.
*
* @return the ISO 4217 currency code of this currency.
*/
return currencyCode;
}
/**
* Gets the symbol of this currency for the default locale.
* For example, for the US Dollar, the symbol is "$" if the default
* locale is the US, while for other locales it may be "US$". If no
* symbol can be determined, the ISO 4217 currency code is returned.
*
* @return the symbol of this currency for the default locale
*/
}
/**
* Gets the symbol of this currency for the specified locale.
* For example, for the US Dollar, the symbol is "$" if the specified
* locale is the US, while for other locales it may be "US$". If no
* symbol can be determined, the ISO 4217 currency code is returned.
*
* @param locale the locale for which a display name for this currency is
* needed
* @return the symbol of this currency for the specified locale
* @exception NullPointerException if <code>locale</code> is null
*/
try {
// Check whether a provider can provide an implementation that's closer
// to the requested locale than what the Java runtime itself can provide.
if (pool.hasProviders()) {
// Assuming that all the country locales include necessary currency
// symbols in the Java runtime's resources, so there is no need to
// examine whether Java runtime's currency resource bundle is missing
// names. Therefore, no resource bundle is provided for calling this
// method.
return symbol;
}
}
} catch (MissingResourceException e) {
// use currency code as symbol of last resort
return currencyCode;
}
}
/**
* Gets the default number of fraction digits used with this currency.
* For example, the default number of fraction digits for the Euro is 2,
* while for the Japanese Yen it's 0.
* In the case of pseudo-currencies, such as IMF Special Drawing Rights,
* -1 is returned.
*
* @return the default number of fraction digits used with this currency
*/
public int getDefaultFractionDigits() {
return defaultFractionDigits;
}
/**
* Returns the ISO 4217 numeric code of this currency.
*
* @return the ISO 4217 numeric code of this currency
* @since 1.7
*/
public int getNumericCode() {
return numericCode;
}
/**
* Gets the name that is suitable for displaying this currency for
* the default locale. If there is no suitable display name found
* for the default locale, the ISO 4217 currency code is returned.
*
* @return the display name of this currency for the default locale
* @since 1.7
*/
}
/**
* Gets the name that is suitable for displaying this currency for
* the specified locale. If there is no suitable display name found
* for the specified locale, the ISO 4217 currency code is returned.
*
* @param locale the locale for which a display name for this currency is
* needed
* @return the display name of this currency for the specified locale
* @exception NullPointerException if <code>locale</code> is null
* @since 1.7
*/
try {
// Check whether a provider can provide an implementation that's closer
// to the requested locale than what the Java runtime itself can provide.
if (pool.hasProviders()) {
}
}
return result;
}
} catch (MissingResourceException e) {
// fall through
}
// use currency code as symbol of last resort
return currencyCode;
}
/**
* Returns the ISO 4217 currency code of this currency.
*
* @return the ISO 4217 currency code of this currency
*/
return currencyCode;
}
/**
* Resolves instances being deserialized to a single instance per currency.
*/
return getInstance(currencyCode);
}
/**
* Gets the main table entry for the country whose country code consists
* of char1 and char2.
*/
throw new IllegalArgumentException();
}
}
/**
* Sets the main table entry for the country whose country code consists
* of char1 and char2.
*/
throw new IllegalArgumentException();
}
}
/**
* Obtains a localized currency names from a CurrencyNameProvider
* implementation.
*/
private static class CurrencyNameGetter
String> {
switch(type) {
case SYMBOL:
case DISPLAYNAME:
default:
assert false; // shouldn't happen
}
return null;
}
}
for (int i = 0; i < count; i++) {
}
return ret;
}
for (int i = 0; i < count; i++) {
}
return ret;
}
for (int i = 0; i < count; i++) {
}
return ret;
}
/**
* Replaces currency data found in the currencydata.properties file
*
* @param pattern regex pattern for the properties
* @param ctry country code
* @param data currency data. This is a comma separated string that
* consists of "three-letter alphabet code", "three-digit numeric code",
* and "one-digit (0,1,2, or 3) default fraction digit".
* For example, "JPZ,392,0".
* @throws
*/
// ignore invalid country code
.append("The entry in currency.properties for ")
.toString();
return;
}
if (!m.find()) {
// format is not recognized. ignore the data
.append("The entry in currency.properties for ")
.append(" is ignored because the value format is not recognized.")
.toString();
return;
}
int index;
break;
}
}
// simple case
} else {
// special case
}
}
if (t != null) {
} else {
}
}
}
}