author | ljiang |
Sun, 14 Jan 2018 21:46:14 -0800 | |
changeset 48537 | 0140779fc556 |
parent 47216 | 71c04702a3d5 |
child 50422 | 04b3e0cc53bb |
permissions | -rw-r--r-- |
2 | 1 |
/* |
29524
2dbceeab4b8b
8074350: Support ISO 4217 "Current funds codes" table (A.2)
naoto
parents:
25174
diff
changeset
|
2 |
* Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved. |
2 | 3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 |
* |
|
5 |
* This code is free software; you can redistribute it and/or modify it |
|
6 |
* under the terms of the GNU General Public License version 2 only, as |
|
7 |
* published by the Free Software Foundation. |
|
8 |
* |
|
9 |
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
10 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
11 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
12 |
* version 2 for more details (a copy is included in the LICENSE file that |
|
13 |
* accompanied this code). |
|
14 |
* |
|
15 |
* You should have received a copy of the GNU General Public License version |
|
16 |
* 2 along with this work; if not, write to the Free Software Foundation, |
|
17 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
18 |
* |
|
5506 | 19 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
20 |
* or visit www.oracle.com if you need additional information or have any |
|
21 |
* questions. |
|
2 | 22 |
*/ |
23 |
/* |
|
24 |
* @test |
|
14857 | 25 |
* @bug 4691089 4819436 4942982 5104960 6544471 6627549 7066203 7195759 |
48537 | 26 |
* 8039317 8074350 8074351 8145952 8187946 |
2 | 27 |
* @summary Validate ISO 4217 data for Currency class. |
42338
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
40999
diff
changeset
|
28 |
* @modules java.base/java.util:open |
a60f280f803c
8169069: Module system implementation refresh (11/2016)
alanb
parents:
40999
diff
changeset
|
29 |
* jdk.localedata |
2 | 30 |
*/ |
31 |
||
32 |
/* |
|
33 |
* ############################################################################ |
|
34 |
* |
|
35 |
* ValidateISO4217 is a tool to detect differences between the latest ISO 4217 |
|
36 |
* data and and Java's currency data which is based on ISO 4217. |
|
37 |
* If there is a difference, the following file which includes currency data |
|
38 |
* may need to be updated. |
|
39 |
* src/share/classes/java/util/CurrencyData.properties |
|
40 |
* |
|
41 |
* ############################################################################ |
|
42 |
* |
|
43 |
* 1) Make a golden-data file. |
|
44 |
* From BSi's ISO4217 data (TABLE A1.doc), extract four (or eight, if currency is changing) |
|
45 |
* fields and save as ./tablea1.txt. |
|
46 |
* <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>] |
|
47 |
* The Cutover Date is given in SimpleDateFormat's 'yyyy-MM-dd-HH-mm-ss' format in the GMT time zone. |
|
48 |
* |
|
49 |
* 2) Compile ValidateISO4217.java |
|
50 |
* |
|
51 |
* 3) Execute ValidateISO4217 as follows: |
|
52 |
* java ValidateISO4217 |
|
53 |
*/ |
|
54 |
||
55 |
import java.io.*; |
|
56 |
import java.text.*; |
|
57 |
import java.util.*; |
|
58 |
||
59 |
public class ValidateISO4217 { |
|
60 |
||
61 |
static final int ALPHA_NUM = 26; |
|
62 |
||
63 |
static final byte UNDEFINED = 0; |
|
64 |
static final byte DEFINED = 1; |
|
65 |
static final byte SKIPPED = 2; |
|
66 |
||
67 |
/* input files */ |
|
68 |
static final String datafile = "tablea1.txt"; |
|
69 |
||
70 |
/* alpha2-code table */ |
|
71 |
static byte[] codes = new byte[ALPHA_NUM * ALPHA_NUM]; |
|
72 |
||
73 |
static final String[][] additionalCodes = { |
|
74 |
/* Defined in ISO 4217 list, but don't have code and minor unit info. */ |
|
75 |
{"AQ", "", "", "0"}, // Antarctica |
|
76 |
||
77 |
/* |
|
78 |
* Defined in ISO 4217 list, but don't have code and minor unit info in |
|
79 |
* it. On the othe hand, both code and minor unit are defined in |
|
80 |
* .properties file. I don't know why, though. |
|
81 |
*/ |
|
82 |
{"GS", "GBP", "826", "2"}, // South Georgia And The South Sandwich Islands |
|
83 |
||
84 |
/* Not defined in ISO 4217 list, but defined in .properties file. */ |
|
85 |
{"AX", "EUR", "978", "2"}, // \u00c5LAND ISLANDS |
|
86 |
{"PS", "ILS", "376", "2"}, // Palestinian Territory, Occupied |
|
87 |
||
88 |
/* Not defined in ISO 4217 list, but added in ISO 3166 country code list */ |
|
89 |
{"JE", "GBP", "826", "2"}, // Jersey |
|
90 |
{"GG", "GBP", "826", "2"}, // Guernsey |
|
91 |
{"IM", "GBP", "826", "2"}, // Isle of Man |
|
1848
6ecbe9158c6e
6627549: ISO 3166 code addition: Saint Barthelemy and Saint Martin
naoto
parents:
892
diff
changeset
|
92 |
{"BL", "EUR", "978", "2"}, // Saint Barthelemy |
6ecbe9158c6e
6627549: ISO 3166 code addition: Saint Barthelemy and Saint Martin
naoto
parents:
892
diff
changeset
|
93 |
{"MF", "EUR", "978", "2"}, // Saint Martin |
2 | 94 |
}; |
95 |
||
96 |
/* Codes that are obsolete, do not have related country */ |
|
97 |
static final String otherCodes = |
|
48537 | 98 |
"ADP-AFA-ATS-AYM-AZM-BEF-BGL-BOV-BYB-BYR-CHE-CHW-CLF-COU-CUC-CYP-" |
99 |
+ "DEM-EEK-ESP-FIM-FRF-GHC-GRD-GWP-IEP-ITL-LUF-MGF-MTL-MXV-MZM-NLG-" |
|
100 |
+ "PTE-ROL-RUR-SDD-SIT-SKK-SRG-STD-TMM-TPE-TRL-VEF-UYI-USN-USS-VEB-" |
|
101 |
+ "XAG-XAU-XBA-XBB-XBC-XBD-XDR-XFO-XFU-XPD-XPT-XSU-XTS-XUA-XXX-" |
|
102 |
+ "YUM-ZMK-ZWD-ZWN-ZWR"; |
|
2 | 103 |
|
104 |
static boolean err = false; |
|
105 |
||
106 |
static Set<Currency> testCurrencies = new HashSet<Currency>(); |
|
107 |
||
108 |
public static void main(String[] args) throws Exception { |
|
109 |
CheckDataVersion.check(); |
|
110 |
test1(); |
|
111 |
test2(); |
|
112 |
getAvailableCurrenciesTest(); |
|
113 |
||
114 |
if (err) { |
|
115 |
throw new RuntimeException("Failed: Validation ISO 4217 data"); |
|
116 |
} |
|
117 |
} |
|
118 |
||
119 |
static void test1() throws Exception { |
|
120 |
||
8543
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
121 |
try (FileReader fr = new FileReader(new File(System.getProperty("test.src", "."), datafile)); |
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
122 |
BufferedReader in = new BufferedReader(fr)) |
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
123 |
{ |
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
124 |
String line; |
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
125 |
SimpleDateFormat format = null; |
2 | 126 |
|
8543
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
127 |
while ((line = in.readLine()) != null) { |
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
128 |
if (line.length() == 0 || line.charAt(0) == '#') { |
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
129 |
continue; |
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
130 |
} |
2 | 131 |
|
8543
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
132 |
StringTokenizer tokens = new StringTokenizer(line, "\t"); |
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
133 |
String country = tokens.nextToken(); |
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
134 |
if (country.length() != 2) { |
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
135 |
continue; |
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
136 |
} |
2 | 137 |
|
8543
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
138 |
String currency; |
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
139 |
String numeric; |
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
140 |
String minorUnit; |
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
141 |
int tokensCount = tokens.countTokens(); |
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
142 |
if (tokensCount < 3) { |
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
143 |
currency = ""; |
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
144 |
numeric = "0"; |
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
145 |
minorUnit = "0"; |
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
146 |
} else { |
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
147 |
currency = tokens.nextToken(); |
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
148 |
numeric = tokens.nextToken(); |
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
149 |
minorUnit = tokens.nextToken(); |
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
150 |
testCurrencies.add(Currency.getInstance(currency)); |
2 | 151 |
|
8543
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
152 |
// check for the cutover |
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
153 |
if (tokensCount > 3) { |
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
154 |
if (format == null) { |
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
155 |
format = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss", Locale.US); |
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
156 |
format.setTimeZone(TimeZone.getTimeZone("GMT")); |
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
157 |
format.setLenient(false); |
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
158 |
} |
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
159 |
if (format.parse(tokens.nextToken()).getTime() < |
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
160 |
System.currentTimeMillis()) { |
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
161 |
currency = tokens.nextToken(); |
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
162 |
numeric = tokens.nextToken(); |
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
163 |
minorUnit = tokens.nextToken(); |
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
164 |
testCurrencies.add(Currency.getInstance(currency)); |
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
165 |
} |
2 | 166 |
} |
167 |
} |
|
8543
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
168 |
int index = toIndex(country); |
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
169 |
testCountryCurrency(country, currency, Integer.parseInt(numeric), |
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
170 |
Integer.parseInt(minorUnit), index); |
2 | 171 |
} |
172 |
} |
|
173 |
||
174 |
for (int i = 0; i < additionalCodes.length; i++) { |
|
175 |
int index = toIndex(additionalCodes[i][0]); |
|
176 |
if (additionalCodes[i][1].length() != 0) { |
|
177 |
testCountryCurrency(additionalCodes[i][0], additionalCodes[i][1], |
|
178 |
Integer.parseInt(additionalCodes[i][2]), |
|
179 |
Integer.parseInt(additionalCodes[i][3]), index); |
|
180 |
testCurrencies.add(Currency.getInstance(additionalCodes[i][1])); |
|
181 |
} else { |
|
182 |
codes[index] = SKIPPED; |
|
183 |
} |
|
184 |
} |
|
185 |
} |
|
186 |
||
187 |
static int toIndex(String s) { |
|
188 |
return ((s.charAt(0) - 'A') * ALPHA_NUM + s.charAt(1) - 'A'); |
|
189 |
} |
|
190 |
||
191 |
static void testCountryCurrency(String country, String currencyCode, |
|
192 |
int numericCode, int digits, int index) { |
|
193 |
if (currencyCode.length() == 0) { |
|
194 |
return; |
|
195 |
} |
|
196 |
testCurrencyDefined(currencyCode, numericCode, digits); |
|
197 |
||
198 |
Locale loc = new Locale("", country); |
|
199 |
try { |
|
200 |
Currency currency = Currency.getInstance(loc); |
|
201 |
if (!currency.getCurrencyCode().equals(currencyCode)) { |
|
202 |
System.err.println("Error: [" + country + ":" + |
|
203 |
loc.getDisplayCountry() + "] expected: " + currencyCode + |
|
204 |
", got: " + currency.getCurrencyCode()); |
|
205 |
err = true; |
|
206 |
} |
|
207 |
||
208 |
if (codes[index] != UNDEFINED) { |
|
209 |
System.out.println("Warning: [" + country + ":" + |
|
210 |
loc.getDisplayCountry() + |
|
211 |
"] multiple definitions. currency code=" + currencyCode); |
|
212 |
} |
|
213 |
codes[index] = DEFINED; |
|
214 |
} |
|
215 |
catch (Exception e) { |
|
216 |
System.err.println("Error: " + e + ": Country=" + country); |
|
217 |
err = true; |
|
218 |
} |
|
219 |
} |
|
220 |
||
221 |
static void testCurrencyDefined(String currencyCode, int numericCode, int digits) { |
|
222 |
try { |
|
223 |
Currency currency = currency = Currency.getInstance(currencyCode); |
|
224 |
||
225 |
if (currency.getNumericCode() != numericCode) { |
|
226 |
System.err.println("Error: [" + currencyCode + "] expected: " + |
|
227 |
numericCode + "; got: " + currency.getNumericCode()); |
|
228 |
err = true; |
|
229 |
} |
|
230 |
||
231 |
if (currency.getDefaultFractionDigits() != digits) { |
|
232 |
System.err.println("Error: [" + currencyCode + "] expected: " + |
|
233 |
digits + "; got: " + currency.getDefaultFractionDigits()); |
|
234 |
err = true; |
|
235 |
} |
|
236 |
} |
|
237 |
catch (Exception e) { |
|
238 |
System.err.println("Error: " + e + ": Currency code=" + |
|
239 |
currencyCode); |
|
240 |
err = true; |
|
241 |
} |
|
242 |
} |
|
243 |
||
244 |
static void test2() { |
|
245 |
for (int i = 0; i < ALPHA_NUM; i++) { |
|
246 |
for (int j = 0; j < ALPHA_NUM; j++) { |
|
247 |
char[] code = new char[2]; |
|
248 |
code[0] = (char)('A'+ i); |
|
249 |
code[1] = (char)('A'+ j); |
|
250 |
String country = new String(code); |
|
251 |
boolean ex; |
|
252 |
||
253 |
if (codes[toIndex(country)] == UNDEFINED) { |
|
254 |
ex = false; |
|
255 |
try { |
|
256 |
Currency.getInstance(new Locale("", country)); |
|
257 |
} |
|
258 |
catch (IllegalArgumentException e) { |
|
259 |
ex = true; |
|
260 |
} |
|
261 |
if (!ex) { |
|
262 |
System.err.println("Error: This should be an undefined code and throw IllegalArgumentException: " + |
|
263 |
country); |
|
264 |
err = true; |
|
265 |
} |
|
266 |
} else if (codes[toIndex(country)] == SKIPPED) { |
|
267 |
Currency cur = null; |
|
268 |
try { |
|
269 |
cur = Currency.getInstance(new Locale("", country)); |
|
270 |
} |
|
271 |
catch (Exception e) { |
|
272 |
System.err.println("Error: " + e + ": Country=" + |
|
273 |
country); |
|
274 |
err = true; |
|
275 |
} |
|
276 |
if (cur != null) { |
|
277 |
System.err.println("Error: Currency.getInstance() for an this locale should return null: " + |
|
278 |
country); |
|
279 |
err = true; |
|
280 |
} |
|
281 |
} |
|
282 |
} |
|
283 |
} |
|
284 |
} |
|
285 |
||
286 |
/** |
|
287 |
* This test depends on test1(), where 'testCurrencies' set is constructed |
|
288 |
*/ |
|
289 |
static void getAvailableCurrenciesTest() { |
|
290 |
Set<Currency> jreCurrencies = Currency.getAvailableCurrencies(); |
|
291 |
||
292 |
// add otherCodes |
|
293 |
StringTokenizer st = new StringTokenizer(otherCodes, "-"); |
|
294 |
while (st.hasMoreTokens()) { |
|
295 |
testCurrencies.add(Currency.getInstance(st.nextToken())); |
|
296 |
} |
|
297 |
||
298 |
if (!testCurrencies.containsAll(jreCurrencies)) { |
|
299 |
System.err.print("Error: getAvailableCurrencies() returned extra currencies than expected: "); |
|
300 |
jreCurrencies.removeAll(testCurrencies); |
|
301 |
for (Currency c : jreCurrencies) { |
|
302 |
System.err.print(" "+c); |
|
303 |
} |
|
304 |
System.err.println(); |
|
305 |
err = true; |
|
306 |
} |
|
307 |
} |
|
308 |
} |