< prev index next >

src/java.base/share/classes/java/util/Currency.java

Print this page

        

*** 151,187 **** // 0 - simple country, bits 0-4 indicate final char of currency code // - bits 5-8: 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 String[] scOldCurrencies; ! static String[] scNewCurrencies; ! static int[] scOldCurrenciesDFD; ! static int[] scNewCurrenciesDFD; ! static int[] scOldCurrenciesNumericCode; ! static int[] scNewCurrenciesNumericCode; ! static String otherCurrencies; ! static int[] otherCurrenciesDFD; ! static int[] otherCurrenciesNumericCode; // handy constants - must match definitions in GenerateCurrencyData // magic number private static final int MAGIC_NUMBER = 0x43757244; // number of characters from A to Z --- 151,167 ---- // 0 - simple country, bits 0-4 indicate final char of currency code // - bits 5-8: 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 specialCasesList static int formatVersion; static int dataVersion; static int[] mainTable; ! static List<SpecialCaseEntry> specialCasesList; ! static List<OtherCurrencyEntry> otherCurrenciesList; // handy constants - must match definitions in GenerateCurrencyData // magic number private static final int MAGIC_NUMBER = 0x43757244; // number of characters from A to Z
*** 212,222 **** private static final int NUMERIC_CODE_MASK = 0x000FFC00; // shift count for the numeric code of the currency private static final int NUMERIC_CODE_SHIFT = 10; // Currency data format version ! private static final int VALID_FORMAT_VERSION = 2; static { AccessController.doPrivileged(new PrivilegedAction<>() { @Override public Void run() { --- 192,202 ---- private static final int NUMERIC_CODE_MASK = 0x000FFC00; // shift count for the numeric code of the currency private static final int NUMERIC_CODE_SHIFT = 10; // Currency data format version ! private static final int VALID_FORMAT_VERSION = 3; static { AccessController.doPrivileged(new PrivilegedAction<>() { @Override public Void run() {
*** 234,254 **** throw new InternalError("Currency data format is incorrect"); } dataVersion = dis.readInt(); mainTable = readIntArray(dis, A_TO_Z * A_TO_Z); int scCount = dis.readInt(); ! scCutOverTimes = readLongArray(dis, scCount); ! scOldCurrencies = readStringArray(dis, scCount); ! scNewCurrencies = readStringArray(dis, scCount); ! scOldCurrenciesDFD = readIntArray(dis, scCount); ! scNewCurrenciesDFD = readIntArray(dis, scCount); ! scOldCurrenciesNumericCode = readIntArray(dis, scCount); ! scNewCurrenciesNumericCode = readIntArray(dis, scCount); int ocCount = dis.readInt(); ! otherCurrencies = dis.readUTF(); ! otherCurrenciesDFD = readIntArray(dis, ocCount); ! otherCurrenciesNumericCode = readIntArray(dis, ocCount); } } catch (IOException e) { throw new InternalError(e); } --- 214,226 ---- throw new InternalError("Currency data format is incorrect"); } dataVersion = dis.readInt(); mainTable = readIntArray(dis, A_TO_Z * A_TO_Z); int scCount = dis.readInt(); ! specialCasesList = readSpecialCases(dis, scCount); int ocCount = dis.readInt(); ! otherCurrenciesList = readOtherCurrencies(dis, ocCount); } } catch (IOException e) { throw new InternalError(e); }
*** 327,336 **** --- 299,309 ---- if (defaultFractionDigits == Integer.MIN_VALUE) { // 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. + boolean found = false; if (currencyCode.length() != 3) { throw new IllegalArgumentException(); } char char1 = currencyCode.charAt(0); char char2 = currencyCode.charAt(1);
*** 338,358 **** if ((tableEntry & COUNTRY_TYPE_MASK) == SIMPLE_CASE_COUNTRY_MASK && tableEntry != INVALID_COUNTRY_ENTRY && currencyCode.charAt(2) - 'A' == (tableEntry & SIMPLE_CASE_COUNTRY_FINAL_CHAR_MASK)) { defaultFractionDigits = (tableEntry & SIMPLE_CASE_COUNTRY_DEFAULT_DIGITS_MASK) >> SIMPLE_CASE_COUNTRY_DEFAULT_DIGITS_SHIFT; numericCode = (tableEntry & NUMERIC_CODE_MASK) >> NUMERIC_CODE_SHIFT; ! } else { ! // Check for '-' separately so we don't get false hits in the table. ! if (currencyCode.charAt(2) == '-') { ! throw new IllegalArgumentException(); } ! int index = otherCurrencies.indexOf(currencyCode); ! if (index == -1) { throw new IllegalArgumentException(); } ! defaultFractionDigits = otherCurrenciesDFD[index / 4]; ! numericCode = otherCurrenciesNumericCode[index / 4]; } } Currency currencyVal = new Currency(currencyCode, defaultFractionDigits, numericCode); --- 311,337 ---- if ((tableEntry & COUNTRY_TYPE_MASK) == SIMPLE_CASE_COUNTRY_MASK && tableEntry != INVALID_COUNTRY_ENTRY && currencyCode.charAt(2) - 'A' == (tableEntry & SIMPLE_CASE_COUNTRY_FINAL_CHAR_MASK)) { defaultFractionDigits = (tableEntry & SIMPLE_CASE_COUNTRY_DEFAULT_DIGITS_MASK) >> SIMPLE_CASE_COUNTRY_DEFAULT_DIGITS_SHIFT; numericCode = (tableEntry & NUMERIC_CODE_MASK) >> NUMERIC_CODE_SHIFT; ! found = true; ! } else { //special case ! int[] fractionAndNumericCode = SpecialCaseEntry.findEntry(currencyCode); ! if (fractionAndNumericCode != null) { ! defaultFractionDigits = fractionAndNumericCode[0]; ! numericCode = fractionAndNumericCode[1]; ! found = true; } ! } ! ! if (!found) { ! OtherCurrencyEntry ocEntry = OtherCurrencyEntry.findEntry(currencyCode); ! if (ocEntry == null) { throw new IllegalArgumentException(); } ! defaultFractionDigits = ocEntry.fraction; ! numericCode = ocEntry.numericCode; } } Currency currencyVal = new Currency(currencyCode, defaultFractionDigits, numericCode);
*** 408,424 **** throw new IllegalArgumentException(); } if (tableEntry == COUNTRY_WITHOUT_CURRENCY_ENTRY) { return null; } else { ! int index = (tableEntry & SPECIAL_CASE_COUNTRY_INDEX_MASK) - SPECIAL_CASE_COUNTRY_INDEX_DELTA; ! if (scCutOverTimes[index] == Long.MAX_VALUE || System.currentTimeMillis() < scCutOverTimes[index]) { ! return getInstance(scOldCurrencies[index], scOldCurrenciesDFD[index], ! scOldCurrenciesNumericCode[index]); } else { ! return getInstance(scNewCurrencies[index], scNewCurrenciesDFD[index], ! scNewCurrenciesNumericCode[index]); } } } } --- 387,407 ---- throw new IllegalArgumentException(); } if (tableEntry == COUNTRY_WITHOUT_CURRENCY_ENTRY) { return null; } else { ! int index = SpecialCaseEntry.toIndex(tableEntry); ! SpecialCaseEntry scEntry = specialCasesList.get(index); ! if (scEntry.cutOverTime == Long.MAX_VALUE ! || System.currentTimeMillis() < scEntry.cutOverTime) { ! return getInstance(scEntry.oldCurrency, ! scEntry.oldCurrencyFraction, ! scEntry.oldCurrencyNumericCode); } else { ! return getInstance(scEntry.newCurrency, ! scEntry.newCurrencyFraction, ! scEntry.newCurrencyNumericCode); } } } }
*** 449,466 **** StringBuilder sb = new StringBuilder(); sb.append(c1); sb.append(c2); sb.append(finalChar); available.add(getInstance(sb.toString(), defaultFractionDigits, numericCode)); } } } // Now add other currencies ! StringTokenizer st = new StringTokenizer(otherCurrencies, "-"); ! while (st.hasMoreElements()) { ! available.add(getInstance((String)st.nextElement())); } } } @SuppressWarnings("unchecked") --- 432,464 ---- StringBuilder sb = new StringBuilder(); sb.append(c1); sb.append(c2); sb.append(finalChar); available.add(getInstance(sb.toString(), defaultFractionDigits, numericCode)); + } else if ((tableEntry & COUNTRY_TYPE_MASK) == SPECIAL_CASE_COUNTRY_MASK + && tableEntry != INVALID_COUNTRY_ENTRY + && tableEntry != COUNTRY_WITHOUT_CURRENCY_ENTRY) { + int index = SpecialCaseEntry.toIndex(tableEntry); + SpecialCaseEntry scEntry = specialCasesList.get(index); + + if (scEntry.cutOverTime == Long.MAX_VALUE + || System.currentTimeMillis() < scEntry.cutOverTime) { + available.add(getInstance(scEntry.oldCurrency, + scEntry.oldCurrencyFraction, + scEntry.oldCurrencyNumericCode)); + } else { + available.add(getInstance(scEntry.newCurrency, + scEntry.newCurrencyFraction, + scEntry.newCurrencyNumericCode)); + } } } } // Now add other currencies ! for (OtherCurrencyEntry entry : otherCurrenciesList) { ! available.add(getInstance(entry.currencyCode)); } } } @SuppressWarnings("unchecked")
*** 691,716 **** } return ret; } ! private static long[] readLongArray(DataInputStream dis, int count) throws IOException { ! long[] ret = new long[count]; ! for (int i = 0; i < count; i++) { ! ret[i] = dis.readLong(); ! } ! return ret; ! } - private static String[] readStringArray(DataInputStream dis, int count) throws IOException { - String[] ret = new String[count]; for (int i = 0; i < count; i++) { ! ret[i] = dis.readUTF(); } ! ! return ret; } /** * Replaces currency data found in the currencydata.properties file * --- 689,747 ---- } return ret; } ! private static List<SpecialCaseEntry> readSpecialCases(DataInputStream dis, ! int count) ! throws IOException { ! ! List<SpecialCaseEntry> list = new ArrayList<>(count); ! long cutOverTime; ! String oldCurrency; ! String newCurrency; ! int oldCurrencyFraction; ! int newCurrencyFraction; ! int oldCurrencyNumericCode; ! int newCurrencyNumericCode; ! for (int i = 0; i < count; i++) { ! cutOverTime = dis.readLong(); ! oldCurrency = dis.readUTF(); ! newCurrency = dis.readUTF(); ! oldCurrencyFraction = dis.readInt(); ! newCurrencyFraction = dis.readInt(); ! oldCurrencyNumericCode = dis.readInt(); ! newCurrencyNumericCode = dis.readInt(); ! SpecialCaseEntry sc = new SpecialCaseEntry(cutOverTime, ! oldCurrency, newCurrency, ! oldCurrencyFraction, newCurrencyFraction, ! oldCurrencyNumericCode, newCurrencyNumericCode); ! list.add(sc); ! } ! return list; ! } ! ! private static List<OtherCurrencyEntry> readOtherCurrencies(DataInputStream dis, ! int count) ! throws IOException { ! ! List<OtherCurrencyEntry> list = new ArrayList<>(count); ! String currencyCode; ! int fraction; ! int numericCode; for (int i = 0; i < count; i++) { ! currencyCode = dis.readUTF(); ! fraction = dis.readInt(); ! numericCode = dis.readInt(); ! OtherCurrencyEntry oc = new OtherCurrencyEntry(currencyCode, ! fraction, ! numericCode); ! list.add(oc); } ! return list; } /** * Replaces currency data found in the currencydata.properties file *
*** 764,788 **** " ignored since the fraction is more than " + SIMPLE_CASE_COUNTRY_MAX_DEFAULT_DIGITS + ":" + curdata, null); return; } ! int index; ! for (index = 0; index < scOldCurrencies.length; index++) { ! if (scOldCurrencies[index].equals(code)) { ! break; ! } } ! if (index == scOldCurrencies.length) { // simple case ! entry |= (fraction << SIMPLE_CASE_COUNTRY_DEFAULT_DIGITS_SHIFT) | ! (code.charAt(2) - 'A'); } else { // special case ! entry |= SPECIAL_CASE_COUNTRY_MASK | ! (index + SPECIAL_CASE_COUNTRY_INDEX_DELTA); } setMainTableEntry(ctry.charAt(0), ctry.charAt(1), entry); } private static boolean isPastCutoverDate(String s) throws ParseException { --- 795,825 ---- " ignored since the fraction is more than " + SIMPLE_CASE_COUNTRY_MAX_DEFAULT_DIGITS + ":" + curdata, null); return; } ! int index = SpecialCaseEntry.indexOf(code, fraction, numeric); ! ! /* if a country switches from simple case to special case or ! * one special case to other special case which is not present ! * in the sc arrays then insert the new entry in special case arrays ! */ ! if (index == -1 && (ctry.charAt(0) != code.charAt(0) ! || ctry.charAt(1) != code.charAt(1))) { ! ! specialCasesList.add(new SpecialCaseEntry(code, fraction, numeric)); ! index = specialCasesList.size() - 1; } ! if (index == -1) { // simple case ! entry |= (fraction << SIMPLE_CASE_COUNTRY_DEFAULT_DIGITS_SHIFT) ! | (code.charAt(2) - 'A'); } else { // special case ! entry = SPECIAL_CASE_COUNTRY_MASK ! | (index + SPECIAL_CASE_COUNTRY_INDEX_DELTA); } setMainTableEntry(ctry.charAt(0), ctry.charAt(1), entry); } private static boolean isPastCutoverDate(String s) throws ParseException {
*** 812,818 **** --- 849,978 ---- } else { logger.info(message); } } } + + /* Used to represent a special case currency entry + * - cutOverTime: 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 + * - oldCurrency: old currencies for special case countries + * - newCurrency: new currencies for special case countries that are + * changing currencies; null for others + * - oldCurrencyFraction: default fraction digits for old currencies + * - newCurrencyFraction: default fraction digits for new currencies, 0 for + * countries that are not changing currencies + * - oldCurrencyNumericCode: numeric code for old currencies + * - newCurrencyNumericCode: numeric code for new currencies, 0 for countries + * that are not changing currencies + */ + private static class SpecialCaseEntry { + + final private long cutOverTime; + final private String oldCurrency; + final private String newCurrency; + final private int oldCurrencyFraction; + final private int newCurrencyFraction; + final private int oldCurrencyNumericCode; + final private int newCurrencyNumericCode; + + private SpecialCaseEntry(long cutOverTime, String oldCurrency, String newCurrency, + int oldCurrencyFraction, int newCurrencyFraction, + int oldCurrencyNumericCode, int newCurrencyNumericCode) { + this.cutOverTime = cutOverTime; + this.oldCurrency = oldCurrency; + this.newCurrency = newCurrency; + this.oldCurrencyFraction = oldCurrencyFraction; + this.newCurrencyFraction = newCurrencyFraction; + this.oldCurrencyNumericCode = oldCurrencyNumericCode; + this.newCurrencyNumericCode = newCurrencyNumericCode; + } + + private SpecialCaseEntry(String currencyCode, int fraction, + int numericCode) { + this(Long.MAX_VALUE, currencyCode, "", fraction, 0, numericCode, 0); + } + + //get the index of the special case entry + private static int indexOf(String code, int fraction, int numeric) { + int size = specialCasesList.size(); + for (int index = 0; index < size; index++) { + SpecialCaseEntry scEntry = specialCasesList.get(index); + if (scEntry.oldCurrency.equals(code) + && scEntry.oldCurrencyFraction == fraction + && scEntry.oldCurrencyNumericCode == numeric + && scEntry.cutOverTime == Long.MAX_VALUE) { + return index; + } + } + return -1; + } + + // get the fraction and numericCode of the sc currencycode + private static int[] findEntry(String code) { + int[] fractionAndNumericCode = null; + int size = specialCasesList.size(); + for (int index = 0; index < size; index++) { + SpecialCaseEntry scEntry = specialCasesList.get(index); + if (scEntry.oldCurrency.equals(code) && (scEntry.cutOverTime == Long.MAX_VALUE + || System.currentTimeMillis() < scEntry.cutOverTime)) { + //consider only when there is no new currency or cutover time is not passed + fractionAndNumericCode = new int[2]; + fractionAndNumericCode[0] = scEntry.oldCurrencyFraction; + fractionAndNumericCode[1] = scEntry.oldCurrencyNumericCode; + break; + } else if (scEntry.newCurrency.equals(code) + && System.currentTimeMillis() >= scEntry.cutOverTime) { + //consider only if the cutover time is passed + fractionAndNumericCode = new int[2]; + fractionAndNumericCode[0] = scEntry.newCurrencyFraction; + fractionAndNumericCode[1] = scEntry.newCurrencyNumericCode; + break; + } + } + return fractionAndNumericCode; + } + + // convert the special case entry to sc arrays index + private static int toIndex(int tableEntry) { + return (tableEntry & SPECIAL_CASE_COUNTRY_INDEX_MASK) - SPECIAL_CASE_COUNTRY_INDEX_DELTA; + } + + } + + /* Used to represent Other currencies + * - currencyCode: currency codes that are not the main currency + * of a simple country + * - otherCurrenciesDFD: decimal format digits for other currencies + * - otherCurrenciesNumericCode: numeric code for other currencies + */ + private static class OtherCurrencyEntry { + + final private String currencyCode; + final private int fraction; + final private int numericCode; + + private OtherCurrencyEntry(String currencyCode, int fraction, + int numericCode) { + this.currencyCode = currencyCode; + this.fraction = fraction; + this.numericCode = numericCode; + } + + //get the instance of the other currency code + private static OtherCurrencyEntry findEntry(String code) { + int size = otherCurrenciesList.size(); + for (int index = 0; index < size; index++) { + OtherCurrencyEntry ocEntry = otherCurrenciesList.get(index); + if (ocEntry.currencyCode.equalsIgnoreCase(code)) { + return ocEntry; + } + } + return null; + } + + } + } +
< prev index next >