/*
* Copyright ( c ) 2007 , 2022 , Oracle and / or its affiliates . All rights reserved .
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER .
*
* This code is free software ; you can redistribute it and / or modify it
* under the terms of the GNU General Public License version 2 only , as
* published by the Free Software Foundation .
*
* 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 .
*/
/*
* @ test
* @ bug 4691089 4819436 4942982 5104960 6544471 6627549 7066203 7195759
* 8039317 8074350 8074351 8145952 8187946 8193552 8202026 8204269
* 8208746 8209775 8264792 8274658 8283277 8296239
* @ summary Validate ISO 4217 data for Currency class .
* @ modules java . base / java . util : open
* jdk . localedata
*/
/*
* # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
*
* ValidateISO4217 is a tool to detect differences between the latest ISO 4217
* data and Java ' s currency data which is based on ISO 4217 .
* If there is a difference , the following file which includes currency data
* may need to be updated .
* src / share / classes / java / util / CurrencyData . properties
*
* # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
*
* 1 ) Make a golden - data file .
* From BSi ' s ISO4217 data ( TABLE A1 . doc ) , extract four ( or eight , if currency is changing )
* fields and save as . / tablea1 . txt .
* < Country code > \ t < Currency code > \ t < Numeric code > \ t < Minor unit > [ \ t < Cutover Date > \ t < new Currency code > \ t < new Numeric code > \ t < new Minor unit > ]
* The Cutover Date is given in SimpleDateFormat ' s ' yyyy - MM - dd - HH - mm - ss ' format in the GMT time zone .
*
* 2 ) Compile ValidateISO4217 . java
*
* 3 ) Execute ValidateISO4217 as follows :
* java ValidateISO4217
*/
import java.io.*;
import java.text.*;
import java.util.*;
public class ValidateISO4217 {
static final int ALPHA_NUM = 26 ;
static final byte UNDEFINED = 0 ;
static final byte DEFINED = 1 ;
static final byte SKIPPED = 2 ;
/* input files */
static final String datafile = "tablea1.txt" ;
/* alpha2-code table */
static byte [] codes = new byte [ALPHA_NUM * ALPHA_NUM];
static final String[][] additionalCodes = {
/* Defined in ISO 4217 list, but don't have code and minor unit info. */
{"AQ" , "" , "" , "0" }, // Antarctica
/*
* Defined in ISO 4217 list , but don ' t have code and minor unit info in
* it . On the other hand , both code and minor unit are defined in
* . properties file . I don ' t know why , though .
*/
{"GS" , "GBP" , "826" , "2" }, // South Georgia And The South Sandwich Islands
/* Not defined in ISO 4217 list, but defined in .properties file. */
{"AX" , "EUR" , "978" , "2" }, // \u00c5LAND ISLANDS
{"PS" , "ILS" , "376" , "2" }, // Palestinian Territory, Occupied
/* Not defined in ISO 4217 list, but added in ISO 3166 country code list */
{"JE" , "GBP" , "826" , "2" }, // Jersey
{"GG" , "GBP" , "826" , "2" }, // Guernsey
{"IM" , "GBP" , "826" , "2" }, // Isle of Man
{"BL" , "EUR" , "978" , "2" }, // Saint Barthelemy
{"MF" , "EUR" , "978" , "2" }, // Saint Martin
/* Defined neither in ISO 4217 nor ISO 3166 list */
{"XK" , "EUR" , "978" , "2" }, // Kosovo
};
/* Codes that are obsolete, do not have related country, extra currency */
static final String otherCodes =
"ADP-AFA-ATS-AYM-AZM-BEF-BGL-BOV-BYB-BYR-CHE-CHW-CLF-COU-CUC-CYP-"
+ "DEM-EEK-ESP-FIM-FRF-GHC-GRD-GWP-IEP-ITL-LTL-LUF-LVL-MGF-MRO-MTL-MXV-MZM-NLG-"
+ "PTE-ROL-RUR-SDD-SIT-SLL-SKK-SRG-STD-TMM-TPE-TRL-VEF-UYI-USN-USS-VEB-VED-"
+ "XAG-XAU-XBA-XBB-XBC-XBD-XDR-XFO-XFU-XPD-XPT-XSU-XTS-XUA-XXX-"
+ "YUM-ZMK-ZWD-ZWN-ZWR" ;
static boolean err = false ;
static Set<Currency> testCurrencies = new HashSet<Currency>();
public static void main(String[] args) throws Exception {
CheckDataVersion.check();
test1();
test2();
getAvailableCurrenciesTest();
if (err) {
throw new RuntimeException("Failed: Validation ISO 4217 data" );
}
}
static void test1() throws Exception {
try (FileReader fr = new FileReader(new File(System.getProperty("test.src" , "." ), datafile));
BufferedReader in = new BufferedReader(fr))
{
String line;
SimpleDateFormat format = null ;
while ((line = in.readLine()) != null ) {
if (line.length() == 0 || line.charAt(0 ) == '#' ) {
continue ;
}
StringTokenizer tokens = new StringTokenizer(line, "\t" );
String country = tokens.nextToken();
if (country.length() != 2 ) {
continue ;
}
String currency;
String numeric;
String minorUnit;
int tokensCount = tokens.countTokens();
if (tokensCount < 3 ) {
currency = "" ;
numeric = "0" ;
minorUnit = "0" ;
} else {
currency = tokens.nextToken();
numeric = tokens.nextToken();
minorUnit = tokens.nextToken();
testCurrencies.add(Currency.getInstance(currency));
// check for the cutover
if (tokensCount > 3 ) {
if (format == null ) {
format = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss" , Locale.US);
format.setTimeZone(TimeZone.getTimeZone("GMT" ));
format.setLenient(false );
}
if (format.parse(tokens.nextToken()).getTime() <
System.currentTimeMillis()) {
currency = tokens.nextToken();
numeric = tokens.nextToken();
minorUnit = tokens.nextToken();
testCurrencies.add(Currency.getInstance(currency));
}
}
}
int index = toIndex(country);
testCountryCurrency(country, currency, Integer.parseInt(numeric),
Integer.parseInt(minorUnit), index);
}
}
for (int i = 0 ; i < additionalCodes.length; i++) {
int index = toIndex(additionalCodes[i][0 ]);
if (additionalCodes[i][1 ].length() != 0 ) {
testCountryCurrency(additionalCodes[i][0 ], additionalCodes[i][1 ],
Integer.parseInt(additionalCodes[i][2 ]),
Integer.parseInt(additionalCodes[i][3 ]), index);
testCurrencies.add(Currency.getInstance(additionalCodes[i][1 ]));
} else {
codes[index] = SKIPPED;
}
}
}
static int toIndex(String s) {
return ((s.charAt(0 ) - 'A' ) * ALPHA_NUM + s.charAt(1 ) - 'A' );
}
static void testCountryCurrency(String country, String currencyCode,
int numericCode, int digits, int index) {
if (currencyCode.length() == 0 ) {
return ;
}
testCurrencyDefined(currencyCode, numericCode, digits);
Locale loc = Locale.of("" , country);
try {
Currency currency = Currency.getInstance(loc);
if (!currency.getCurrencyCode().equals(currencyCode)) {
System.err.println("Error: [" + country + ":" +
loc.getDisplayCountry() + "] expected: " + currencyCode +
", got: " + currency.getCurrencyCode());
err = true ;
}
if (codes[index] != UNDEFINED) {
System.out.println("Warning: [" + country + ":" +
loc.getDisplayCountry() +
"] multiple definitions. currency code=" + currencyCode);
}
codes[index] = DEFINED;
}
catch (Exception e) {
System.err.println("Error: " + e + ": Country=" + country);
err = true ;
}
}
static void testCurrencyDefined(String currencyCode, int numericCode, int digits) {
try {
Currency currency = currency = Currency.getInstance(currencyCode);
if (currency.getNumericCode() != numericCode) {
System.err.println("Error: [" + currencyCode + "] expected: " +
numericCode + "; got: " + currency.getNumericCode());
err = true ;
}
if (currency.getDefaultFractionDigits() != digits) {
System.err.println("Error: [" + currencyCode + "] expected: " +
digits + "; got: " + currency.getDefaultFractionDigits());
err = true ;
}
}
catch (Exception e) {
System.err.println("Error: " + e + ": Currency code=" +
currencyCode);
err = true ;
}
}
static void test2() {
for (int i = 0 ; i < ALPHA_NUM; i++) {
for (int j = 0 ; j < ALPHA_NUM; j++) {
char [] code = new char [2 ];
code[0 ] = (char )('A' + i);
code[1 ] = (char )('A' + j);
String country = new String(code);
boolean ex;
if (codes[toIndex(country)] == UNDEFINED) {
ex = false ;
try {
Currency.getInstance(Locale.of("" , country));
}
catch (IllegalArgumentException e) {
ex = true ;
}
if (!ex) {
System.err.println("Error: This should be an undefined code and throw IllegalArgumentException: " +
country);
err = true ;
}
} else if (codes[toIndex(country)] == SKIPPED) {
Currency cur = null ;
try {
cur = Currency.getInstance(Locale.of("" , country));
}
catch (Exception e) {
System.err.println("Error: " + e + ": Country=" +
country);
err = true ;
}
if (cur != null ) {
System.err.println("Error: Currency.getInstance() for an this locale should return null: " +
country);
err = true ;
}
}
}
}
}
/**
* This test depends on test1 ( ) , where ' testCurrencies ' set is constructed
*/
static void getAvailableCurrenciesTest() {
Set<Currency> jreCurrencies = Currency.getAvailableCurrencies();
// add otherCodes
StringTokenizer st = new StringTokenizer(otherCodes, "-" );
while (st.hasMoreTokens()) {
testCurrencies.add(Currency.getInstance(st.nextToken()));
}
if (!testCurrencies.containsAll(jreCurrencies)) {
System.err.print("Error: getAvailableCurrencies() returned extra currencies than expected: " );
jreCurrencies.removeAll(testCurrencies);
for (Currency c : jreCurrencies) {
System.err.print(" " +c);
}
System.err.println();
err = true ;
}
}
}
Messung V0.5 in Prozent C=94 H=94 G=93
¤ Dauer der Verarbeitung: 0.19 Sekunden
(vorverarbeitet am 2026-06-10)
¤
*© Formatika GbR, Deutschland