OLD | NEW |
| (Empty) |
1 // © 2016 and later: Unicode, Inc. and others. | |
2 // License & terms of use: http://www.unicode.org/copyright.html#License | |
3 /* | |
4 ******************************************************************************* | |
5 * Copyright (C) 2015, International Business Machines Corporation and * | |
6 * others. All Rights Reserved. * | |
7 ******************************************************************************* | |
8 */ | |
9 package com.ibm.icu.dev.test.format; | |
10 | |
11 import java.lang.reflect.Field; | |
12 import java.lang.reflect.InvocationTargetException; | |
13 import java.lang.reflect.Method; | |
14 import java.util.HashMap; | |
15 import java.util.HashSet; | |
16 import java.util.Map; | |
17 | |
18 import com.ibm.icu.math.BigDecimal; | |
19 import com.ibm.icu.text.DecimalFormat; | |
20 import com.ibm.icu.text.NumberFormat; | |
21 import com.ibm.icu.util.Currency; | |
22 import com.ibm.icu.util.ULocale; | |
23 | |
24 /** | |
25 * A representation of a single NumberFormat specification test from a data driv
en test file. | |
26 * <p> | |
27 * The purpose of this class is to hide the details of the data driven test file
from the | |
28 * main testing code. | |
29 * <p> | |
30 * This class contains fields describing an attribute of the test that may or ma
y | |
31 * not be set. The name of each attribute corresponds to the name used in the | |
32 * data driven test file. | |
33 * <p> | |
34 * <b>Adding new attributes</b> | |
35 * <p> | |
36 * Each attribute name is lower case. Moreover, for each attribute there is also
a | |
37 * setXXX method for that attribute that is used to initialize the attribute fro
m a | |
38 * String value read from the data file. For example, there is a setLocale(Strin
g) method | |
39 * for the locale attribute and a setCurrency(String) method for the currency at
tribute. | |
40 * In general, for an attribute named abcd, the setter will be setAbcd(String). | |
41 * This naming rule must be strictly followed or else the test runner will not k
now how to | |
42 * initialize instances of this class. | |
43 * <p> | |
44 * In addition each attribute is listed in the fieldOrdering static array which
specifies | |
45 * The order that attributes are printed whenever there is a test failure. | |
46 * <p>· | |
47 * To add a new attribute, first create a public field for it. | |
48 * Next, add the attribute name to the fieldOrdering array. | |
49 * Finally, create a setter method for it. | |
50 *· | |
51 * @author rocketman | |
52 */ | |
53 public class NumberFormatTestData { | |
54 ···· | |
55 /** | |
56 * The locale. | |
57 */ | |
58 public ULocale locale = null; | |
59 ···· | |
60 /** | |
61 * The currency. | |
62 */ | |
63 public Currency currency = null; | |
64 ···· | |
65 /** | |
66 * The pattern to initialize the formatter, for example 0.00" | |
67 */ | |
68 public String pattern = null; | |
69 ···· | |
70 /** | |
71 * The value to format as a string. For example 1234.5 would be "1234.5" | |
72 */ | |
73 public String format = null; | |
74 ···· | |
75 /** | |
76 * The formatted value. | |
77 */ | |
78 public String output = null; | |
79 ···· | |
80 /** | |
81 * Field for arbitrary comments. | |
82 */ | |
83 public String comment = null; | |
84 ···· | |
85 public Integer minIntegerDigits = null; | |
86 public Integer maxIntegerDigits = null; | |
87 public Integer minFractionDigits = null; | |
88 public Integer maxFractionDigits = null; | |
89 public Integer minGroupingDigits = null; | |
90 public Integer useSigDigits = null; | |
91 public Integer minSigDigits = null; | |
92 public Integer maxSigDigits = null; | |
93 public Integer useGrouping = null; | |
94 public Integer multiplier = null; | |
95 public Double roundingIncrement = null; | |
96 public Integer formatWidth = null; | |
97 public String padCharacter = null; | |
98 public Integer useScientific = null; | |
99 public Integer grouping = null; | |
100 public Integer grouping2 = null; | |
101 public Integer roundingMode = null; | |
102 public Currency.CurrencyUsage currencyUsage = null; | |
103 public Integer minimumExponentDigits = null; | |
104 public Integer exponentSignAlwaysShown = null; | |
105 public Integer decimalSeparatorAlwaysShown = null; | |
106 public Integer padPosition = null; | |
107 public String positivePrefix = null; | |
108 public String positiveSuffix = null; | |
109 public String negativePrefix = null; | |
110 public String negativeSuffix = null; | |
111 public String localizedPattern = null; | |
112 public String toPattern = null; | |
113 public String toLocalizedPattern = null; | |
114 public Integer style = null; | |
115 public String parse = null; | |
116 public Integer lenient = null; | |
117 public String plural = null; | |
118 public Integer parseIntegerOnly = null; | |
119 public Integer decimalPatternMatchRequired = null; | |
120 public Integer parseNoExponent = null; | |
121 public String outputCurrency = null; | |
122 ···· | |
123 ···· | |
124 ···· | |
125 /** | |
126 * nothing or empty means that test ought to work for both C and JAVA; | |
127 * "C" means test is known to fail in C. "J" means test is known to fail in
JAVA. | |
128 * "CJ" means test is known to fail for both languages. | |
129 */ | |
130 public String breaks = null; | |
131 ···· | |
132 private static Map<String, Integer> roundingModeMap = | |
133 new HashMap<String, Integer>(); | |
134 ···· | |
135 static { | |
136 roundingModeMap.put("ceiling", BigDecimal.ROUND_CEILING); | |
137 roundingModeMap.put("floor", BigDecimal.ROUND_FLOOR); | |
138 roundingModeMap.put("down", BigDecimal.ROUND_DOWN); | |
139 roundingModeMap.put("up", BigDecimal.ROUND_UP); | |
140 roundingModeMap.put("halfEven", BigDecimal.ROUND_HALF_EVEN); | |
141 roundingModeMap.put("halfDown", BigDecimal.ROUND_HALF_DOWN); | |
142 roundingModeMap.put("halfUp", BigDecimal.ROUND_HALF_UP); | |
143 roundingModeMap.put("unnecessary", BigDecimal.ROUND_UNNECESSARY); | |
144 } | |
145 ···· | |
146 private static Map<String, Currency.CurrencyUsage> currencyUsageMap = | |
147 new HashMap<String, Currency.CurrencyUsage>(); | |
148 ···· | |
149 static { | |
150 currencyUsageMap.put("standard", Currency.CurrencyUsage.STANDARD); | |
151 currencyUsageMap.put("cash", Currency.CurrencyUsage.CASH); | |
152 } | |
153 ···· | |
154 private static Map<String, Integer> padPositionMap = | |
155 new HashMap<String, Integer>(); | |
156 ···· | |
157 static { | |
158 // TODO: Fix so that it doesn't depend on DecimalFormat. | |
159 padPositionMap.put("beforePrefix", DecimalFormat.PAD_BEFORE_PREFIX); | |
160 padPositionMap.put("afterPrefix", DecimalFormat.PAD_AFTER_PREFIX); | |
161 padPositionMap.put("beforeSuffix", DecimalFormat.PAD_BEFORE_SUFFIX); | |
162 padPositionMap.put("afterSuffix", DecimalFormat.PAD_AFTER_SUFFIX); | |
163 } | |
164 ···· | |
165 private static Map<String, Integer> formatStyleMap = | |
166 new HashMap<String, Integer>(); | |
167 ···· | |
168 static { | |
169 formatStyleMap.put("decimal", NumberFormat.NUMBERSTYLE); | |
170 formatStyleMap.put("currency", NumberFormat.CURRENCYSTYLE); | |
171 formatStyleMap.put("percent", NumberFormat.PERCENTSTYLE); | |
172 formatStyleMap.put("scientific", NumberFormat.SCIENTIFICSTYLE); | |
173 formatStyleMap.put("currencyIso", NumberFormat.ISOCURRENCYSTYLE); | |
174 formatStyleMap.put("currencyPlural", NumberFormat.PLURALCURRENCYSTYLE); | |
175 formatStyleMap.put("currencyAccounting", NumberFormat.ACCOUNTINGCURRENCY
STYLE); | |
176 formatStyleMap.put("cashCurrency", NumberFormat.CASHCURRENCYSTYLE); | |
177 } | |
178 ···· | |
179 // Add any new fields here. On test failures, fields are printed in the same
order they | |
180 // appear here. | |
181 private static String[] fieldOrdering = { | |
182 "locale", | |
183 "currency", | |
184 "pattern", | |
185 "format", | |
186 "output", | |
187 "comment", | |
188 "minIntegerDigits", | |
189 "maxIntegerDigits", | |
190 "minFractionDigits", | |
191 "maxFractionDigits", | |
192 "minGroupingDigits", | |
193 "breaks", | |
194 "useSigDigits", | |
195 "minSigDigits", | |
196 "maxSigDigits", | |
197 "useGrouping", | |
198 "multiplier", | |
199 "roundingIncrement", | |
200 "formatWidth", | |
201 "padCharacter", | |
202 "useScientific", | |
203 "grouping", | |
204 "grouping2", | |
205 "roundingMode", | |
206 "currencyUsage", | |
207 "minimumExponentDigits", | |
208 "exponentSignAlwaysShown", | |
209 "decimalSeparatorAlwaysShown", | |
210 "padPosition", | |
211 "positivePrefix", | |
212 "positiveSuffix", | |
213 "negativePrefix", | |
214 "negativeSuffix", | |
215 "localizedPattern", | |
216 "toPattern", | |
217 "toLocalizedPattern", | |
218 "style", | |
219 "parse", | |
220 "lenient", | |
221 "plural", | |
222 "parseIntegerOnly", | |
223 "decimalPatternMatchRequired", | |
224 "parseNoExponent", | |
225 "outputCurrency" | |
226 }; | |
227 ···· | |
228 static { | |
229 HashSet<String> set = new HashSet<String>(); | |
230 for (String s : fieldOrdering) { | |
231 if (!set.add(s)) { | |
232 throw new ExceptionInInitializerError(s + "is a duplicate field.
");···· | |
233 } | |
234 } | |
235 } | |
236 ···· | |
237 private static <T> T fromString(Map<String, T> map, String key) { | |
238 T value = map.get(key); | |
239 if (value == null) { | |
240 throw new IllegalArgumentException("Bad value: "+ key); | |
241 } | |
242 return value; | |
243 } | |
244 ···· | |
245 // start field setters. | |
246 // add setter for each new field in this block. | |
247 ···· | |
248 public void setLocale(String value) { | |
249 locale = new ULocale(value); | |
250 } | |
251 ···· | |
252 public void setCurrency(String value) { | |
253 currency = Currency.getInstance(value); | |
254 } | |
255 ···· | |
256 public void setPattern(String value) { | |
257 pattern = value; | |
258 } | |
259 ···· | |
260 public void setFormat(String value) { | |
261 format = value; | |
262 } | |
263 ···· | |
264 public void setOutput(String value) { | |
265 output = value; | |
266 } | |
267 ···· | |
268 public void setComment(String value) { | |
269 comment = value; | |
270 } | |
271 ···· | |
272 public void setMinIntegerDigits(String value) { | |
273 minIntegerDigits = Integer.valueOf(value); | |
274 } | |
275 ···· | |
276 public void setMaxIntegerDigits(String value) { | |
277 maxIntegerDigits = Integer.valueOf(value); | |
278 } | |
279 ···· | |
280 public void setMinFractionDigits(String value) { | |
281 minFractionDigits = Integer.valueOf(value); | |
282 } | |
283 ···· | |
284 public void setMaxFractionDigits(String value) { | |
285 maxFractionDigits = Integer.valueOf(value); | |
286 } | |
287 ···· | |
288 public void setMinGroupingDigits(String value) { | |
289 minGroupingDigits = Integer.valueOf(value); | |
290 } | |
291 ···· | |
292 public void setBreaks(String value) { | |
293 breaks = value; | |
294 } | |
295 ···· | |
296 public void setUseSigDigits(String value) { | |
297 useSigDigits = Integer.valueOf(value); | |
298 } | |
299 ···· | |
300 public void setMinSigDigits(String value) { | |
301 minSigDigits = Integer.valueOf(value); | |
302 } | |
303 ···· | |
304 public void setMaxSigDigits(String value) { | |
305 maxSigDigits = Integer.valueOf(value); | |
306 } | |
307 ···· | |
308 public void setUseGrouping(String value) { | |
309 useGrouping = Integer.valueOf(value); | |
310 } | |
311 ···· | |
312 public void setMultiplier(String value) { | |
313 multiplier = Integer.valueOf(value); | |
314 } | |
315 ···· | |
316 public void setRoundingIncrement(String value) { | |
317 roundingIncrement = Double.valueOf(value); | |
318 } | |
319 ···· | |
320 public void setFormatWidth(String value) { | |
321 formatWidth = Integer.valueOf(value); | |
322 } | |
323 ···· | |
324 public void setPadCharacter(String value) { | |
325 padCharacter = value; | |
326 } | |
327 ···· | |
328 public void setUseScientific(String value) { | |
329 useScientific = Integer.valueOf(value); | |
330 } | |
331 ···· | |
332 public void setGrouping(String value) { | |
333 grouping = Integer.valueOf(value); | |
334 } | |
335 ···· | |
336 public void setGrouping2(String value) { | |
337 grouping2 = Integer.valueOf(value); | |
338 } | |
339 ···· | |
340 public void setRoundingMode(String value) { | |
341 roundingMode = fromString(roundingModeMap, value); | |
342 } | |
343 ···· | |
344 public void setCurrencyUsage(String value) { | |
345 currencyUsage = fromString(currencyUsageMap, value); | |
346 } | |
347 ···· | |
348 public void setMinimumExponentDigits(String value) { | |
349 minimumExponentDigits = Integer.valueOf(value); | |
350 } | |
351 ···· | |
352 public void setExponentSignAlwaysShown(String value) { | |
353 exponentSignAlwaysShown = Integer.valueOf(value); | |
354 } | |
355 ···· | |
356 public void setDecimalSeparatorAlwaysShown(String value) { | |
357 decimalSeparatorAlwaysShown = Integer.valueOf(value); | |
358 } | |
359 ···· | |
360 public void setPadPosition(String value) { | |
361 padPosition = fromString(padPositionMap, value); | |
362 } | |
363 ···· | |
364 public void setPositivePrefix(String value) { | |
365 positivePrefix = value; | |
366 } | |
367 ···· | |
368 public void setPositiveSuffix(String value) { | |
369 positiveSuffix = value; | |
370 } | |
371 ···· | |
372 public void setNegativePrefix(String value) { | |
373 negativePrefix = value; | |
374 } | |
375 ···· | |
376 public void setNegativeSuffix(String value) { | |
377 negativeSuffix = value; | |
378 } | |
379 ···· | |
380 public void setLocalizedPattern(String value) { | |
381 localizedPattern = value; | |
382 } | |
383 ···· | |
384 public void setToPattern(String value) { | |
385 toPattern = value; | |
386 } | |
387 ···· | |
388 public void setToLocalizedPattern(String value) { | |
389 toLocalizedPattern = value; | |
390 } | |
391 ···· | |
392 public void setStyle(String value) { | |
393 style = fromString(formatStyleMap, value); | |
394 } | |
395 ···· | |
396 public void setParse(String value) { | |
397 parse = value; | |
398 } | |
399 ···· | |
400 public void setLenient(String value) { | |
401 lenient = Integer.valueOf(value); | |
402 } | |
403 ···· | |
404 public void setPlural(String value) { | |
405 plural = value; | |
406 } | |
407 ···· | |
408 public void setParseIntegerOnly(String value) { | |
409 parseIntegerOnly = Integer.valueOf(value); | |
410 } | |
411 ···· | |
412 public void setDecimalPatternMatchRequired(String value) { | |
413 decimalPatternMatchRequired = Integer.valueOf(value); | |
414 } | |
415 ···· | |
416 public void setParseNoExponent(String value) { | |
417 parseNoExponent = Integer.valueOf(value); | |
418 } | |
419 ···· | |
420 public void setOutputCurrency(String value) { | |
421 outputCurrency = value; | |
422 } | |
423 ···· | |
424 // end field setters. | |
425 ···· | |
426 // start of field clearers | |
427 // Add clear methods that can be set in one test and cleared | |
428 // in the next i.e the breaks field. | |
429 ···· | |
430 public void clearBreaks() { | |
431 breaks = null; | |
432 } | |
433 ···· | |
434 public void clearUseGrouping() { | |
435 useGrouping = null; | |
436 } | |
437 ···· | |
438 public void clearGrouping2() { | |
439 grouping2 = null; | |
440 } | |
441 ···· | |
442 public void clearGrouping() { | |
443 grouping = null; | |
444 } | |
445 ···· | |
446 public void clearMinGroupingDigits() { | |
447 minGroupingDigits = null; | |
448 } | |
449 ···· | |
450 public void clearUseScientific() { | |
451 useScientific = null; | |
452 } | |
453 ···· | |
454 public void clearDecimalSeparatorAlwaysShown() { | |
455 decimalSeparatorAlwaysShown = null; | |
456 } | |
457 ···· | |
458 // end field clearers | |
459 ···· | |
460 public void setField(String fieldName, String valueString) | |
461 throws NoSuchMethodException { | |
462 Method m = getClass().getMethod( | |
463 fieldToSetter(fieldName), String.class); | |
464 try { | |
465 m.invoke(this, valueString); | |
466 } catch (IllegalAccessException e) { | |
467 throw new RuntimeException(e); | |
468 } catch (InvocationTargetException e) { | |
469 throw new RuntimeException(e); | |
470 } | |
471 } | |
472 ···· | |
473 public void clearField(String fieldName) | |
474 throws NoSuchMethodException { | |
475 Method m = getClass().getMethod(fieldToClearer(fieldName)); | |
476 try { | |
477 m.invoke(this); | |
478 } catch (IllegalAccessException e) { | |
479 throw new RuntimeException(e); | |
480 } catch (InvocationTargetException e) { | |
481 throw new RuntimeException(e); | |
482 } | |
483 } | |
484 ···· | |
485 public String toString() { | |
486 StringBuilder result = new StringBuilder(); | |
487 result.append("{"); | |
488 boolean first = true; | |
489 for (String fieldName : fieldOrdering) { | |
490 try { | |
491 Field field = getClass().getField(fieldName); | |
492 Object optionalValue = field.get(this); | |
493 if (optionalValue == null) { | |
494 continue; | |
495 } | |
496 if (!first) { | |
497 result.append(", "); | |
498 } | |
499 first = false; | |
500 result.append(fieldName); | |
501 result.append(": "); | |
502 result.append(optionalValue); | |
503 } catch (NoSuchFieldException e) { | |
504 throw new RuntimeException(e); | |
505 } catch (SecurityException e) { | |
506 throw new RuntimeException(e); | |
507 } catch (IllegalAccessException e) { | |
508 throw new RuntimeException(e); | |
509 } | |
510 } | |
511 result.append("}"); | |
512 return result.toString(); | |
513 } | |
514 | |
515 private static String fieldToSetter(String fieldName) { | |
516 return "set" | |
517 + Character.toUpperCase(fieldName.charAt(0)) | |
518 + fieldName.substring(1); | |
519 } | |
520 ···· | |
521 private static String fieldToClearer(String fieldName) { | |
522 return "clear" | |
523 + Character.toUpperCase(fieldName.charAt(0)) | |
524 + fieldName.substring(1); | |
525 } | |
526 | |
527 } | |
OLD | NEW |