| // © 2016 and later: Unicode, Inc. and others. |
| // License & terms of use: http://www.unicode.org/copyright.html |
| /* |
| ******************************************************************************* |
| * Copyright (C) 2015, International Business Machines Corporation and * |
| * others. All Rights Reserved. * |
| ******************************************************************************* |
| */ |
| package com.ibm.icu.dev.test.format; |
| |
| import java.lang.reflect.Field; |
| import java.lang.reflect.InvocationTargetException; |
| import java.lang.reflect.Method; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Map; |
| |
| import com.ibm.icu.math.BigDecimal; |
| import com.ibm.icu.text.DecimalFormat; |
| import com.ibm.icu.text.NumberFormat; |
| import com.ibm.icu.util.Currency; |
| import com.ibm.icu.util.ULocale; |
| |
| /** |
| * A representation of a single NumberFormat specification test from a data driven test file. |
| * <p> |
| * The purpose of this class is to hide the details of the data driven test file from the |
| * main testing code. |
| * <p> |
| * This class contains fields describing an attribute of the test that may or may |
| * not be set. The name of each attribute corresponds to the name used in the |
| * data driven test file. |
| * <p> |
| * <b>Adding new attributes</b> |
| * <p> |
| * Each attribute name is lower case. Moreover, for each attribute there is also a |
| * setXXX method for that attribute that is used to initialize the attribute from a |
| * String value read from the data file. For example, there is a setLocale(String) method |
| * for the locale attribute and a setCurrency(String) method for the currency attribute. |
| * In general, for an attribute named abcd, the setter will be setAbcd(String). |
| * This naming rule must be strictly followed or else the test runner will not know how to |
| * initialize instances of this class. |
| * <p> |
| * In addition each attribute is listed in the fieldOrdering static array which specifies |
| * The order that attributes are printed whenever there is a test failure. |
| * <p> |
| * To add a new attribute, first create a public field for it. |
| * Next, add the attribute name to the fieldOrdering array. |
| * Finally, create a setter method for it. |
| * |
| * @author rocketman |
| */ |
| public class DataDrivenNumberFormatTestData { |
| |
| /** |
| * The locale. |
| */ |
| public ULocale locale = null; |
| |
| /** |
| * The currency. |
| */ |
| public Currency currency = null; |
| |
| /** |
| * The pattern to initialize the formatter, for example 0.00" |
| */ |
| public String pattern = null; |
| |
| /** |
| * The value to format as a string. For example 1234.5 would be "1234.5" |
| */ |
| public String format = null; |
| |
| /** |
| * The formatted value. |
| */ |
| public String output = null; |
| |
| /** |
| * Field for arbitrary comments. |
| */ |
| public String comment = null; |
| |
| public Integer minIntegerDigits = null; |
| public Integer maxIntegerDigits = null; |
| public Integer minFractionDigits = null; |
| public Integer maxFractionDigits = null; |
| public Integer minGroupingDigits = null; |
| public Integer useSigDigits = null; |
| public Integer minSigDigits = null; |
| public Integer maxSigDigits = null; |
| public Integer useGrouping = null; |
| public Integer multiplier = null; |
| public Double roundingIncrement = null; |
| public Integer formatWidth = null; |
| public String padCharacter = null; |
| public Integer useScientific = null; |
| public Integer grouping = null; |
| public Integer grouping2 = null; |
| public Integer roundingMode = null; |
| public Currency.CurrencyUsage currencyUsage = null; |
| public Integer minimumExponentDigits = null; |
| public Integer exponentSignAlwaysShown = null; |
| public Integer decimalSeparatorAlwaysShown = null; |
| public Integer padPosition = null; |
| public String positivePrefix = null; |
| public String positiveSuffix = null; |
| public String negativePrefix = null; |
| public String negativeSuffix = null; |
| public Integer signAlwaysShown = null; |
| public String localizedPattern = null; |
| public String toPattern = null; |
| public String toLocalizedPattern = null; |
| public Integer style = null; |
| public String parse = null; |
| public Integer lenient = null; |
| public String plural = null; |
| public Integer parseIntegerOnly = null; |
| public Integer decimalPatternMatchRequired = null; |
| public Integer parseCaseSensitive = null; |
| public Integer parseNoExponent = null; |
| public String outputCurrency = null; |
| |
| |
| |
| /** |
| * nothing or empty means that test ought to work for both C and JAVA; |
| * "C" means test is known to fail in C. "J" means test is known to fail in JAVA. |
| * "CJ" means test is known to fail for both languages. |
| */ |
| public String breaks = null; |
| |
| private static Map<String, Integer> roundingModeMap = |
| new HashMap<String, Integer>(); |
| |
| static { |
| roundingModeMap.put("ceiling", BigDecimal.ROUND_CEILING); |
| roundingModeMap.put("floor", BigDecimal.ROUND_FLOOR); |
| roundingModeMap.put("down", BigDecimal.ROUND_DOWN); |
| roundingModeMap.put("up", BigDecimal.ROUND_UP); |
| roundingModeMap.put("halfEven", BigDecimal.ROUND_HALF_EVEN); |
| roundingModeMap.put("halfDown", BigDecimal.ROUND_HALF_DOWN); |
| roundingModeMap.put("halfUp", BigDecimal.ROUND_HALF_UP); |
| roundingModeMap.put("unnecessary", BigDecimal.ROUND_UNNECESSARY); |
| } |
| |
| private static Map<String, Currency.CurrencyUsage> currencyUsageMap = |
| new HashMap<String, Currency.CurrencyUsage>(); |
| |
| static { |
| currencyUsageMap.put("standard", Currency.CurrencyUsage.STANDARD); |
| currencyUsageMap.put("cash", Currency.CurrencyUsage.CASH); |
| } |
| |
| private static Map<String, Integer> padPositionMap = |
| new HashMap<String, Integer>(); |
| |
| static { |
| // TODO: Fix so that it doesn't depend on DecimalFormat. |
| padPositionMap.put("beforePrefix", DecimalFormat.PAD_BEFORE_PREFIX); |
| padPositionMap.put("afterPrefix", DecimalFormat.PAD_AFTER_PREFIX); |
| padPositionMap.put("beforeSuffix", DecimalFormat.PAD_BEFORE_SUFFIX); |
| padPositionMap.put("afterSuffix", DecimalFormat.PAD_AFTER_SUFFIX); |
| } |
| |
| private static Map<String, Integer> formatStyleMap = |
| new HashMap<String, Integer>(); |
| |
| static { |
| formatStyleMap.put("decimal", NumberFormat.NUMBERSTYLE); |
| formatStyleMap.put("currency", NumberFormat.CURRENCYSTYLE); |
| formatStyleMap.put("percent", NumberFormat.PERCENTSTYLE); |
| formatStyleMap.put("scientific", NumberFormat.SCIENTIFICSTYLE); |
| formatStyleMap.put("currencyIso", NumberFormat.ISOCURRENCYSTYLE); |
| formatStyleMap.put("currencyPlural", NumberFormat.PLURALCURRENCYSTYLE); |
| formatStyleMap.put("currencyAccounting", NumberFormat.ACCOUNTINGCURRENCYSTYLE); |
| formatStyleMap.put("cashCurrency", NumberFormat.CASHCURRENCYSTYLE); |
| } |
| |
| // Add any new fields here. On test failures, fields are printed in the same order they |
| // appear here. |
| private static String[] fieldOrdering = { |
| "locale", |
| "currency", |
| "pattern", |
| "format", |
| "output", |
| "comment", |
| "minIntegerDigits", |
| "maxIntegerDigits", |
| "minFractionDigits", |
| "maxFractionDigits", |
| "minGroupingDigits", |
| "breaks", |
| "useSigDigits", |
| "minSigDigits", |
| "maxSigDigits", |
| "useGrouping", |
| "multiplier", |
| "roundingIncrement", |
| "formatWidth", |
| "padCharacter", |
| "useScientific", |
| "grouping", |
| "grouping2", |
| "roundingMode", |
| "currencyUsage", |
| "minimumExponentDigits", |
| "exponentSignAlwaysShown", |
| "decimalSeparatorAlwaysShown", |
| "padPosition", |
| "positivePrefix", |
| "positiveSuffix", |
| "negativePrefix", |
| "negativeSuffix", |
| "signAlwaysShown", |
| "localizedPattern", |
| "toPattern", |
| "toLocalizedPattern", |
| "style", |
| "parse", |
| "lenient", |
| "plural", |
| "parseIntegerOnly", |
| "decimalPatternMatchRequired", |
| "parseNoExponent", |
| "outputCurrency" |
| }; |
| |
| static { |
| HashSet<String> set = new HashSet<String>(); |
| for (String s : fieldOrdering) { |
| if (!set.add(s)) { |
| throw new ExceptionInInitializerError(s + "is a duplicate field."); |
| } |
| } |
| } |
| |
| private static <T> T fromString(Map<String, T> map, String key) { |
| T value = map.get(key); |
| if (value == null) { |
| throw new IllegalArgumentException("Bad value: "+ key); |
| } |
| return value; |
| } |
| |
| // start field setters. |
| // add setter for each new field in this block. |
| |
| public void setLocale(String value) { |
| locale = new ULocale(value); |
| } |
| |
| public void setCurrency(String value) { |
| currency = Currency.getInstance(value); |
| } |
| |
| public void setPattern(String value) { |
| pattern = value; |
| } |
| |
| public void setFormat(String value) { |
| format = value; |
| } |
| |
| public void setOutput(String value) { |
| output = value; |
| } |
| |
| public void setComment(String value) { |
| comment = value; |
| } |
| |
| public void setMinIntegerDigits(String value) { |
| minIntegerDigits = Integer.valueOf(value); |
| } |
| |
| public void setMaxIntegerDigits(String value) { |
| maxIntegerDigits = Integer.valueOf(value); |
| } |
| |
| public void setMinFractionDigits(String value) { |
| minFractionDigits = Integer.valueOf(value); |
| } |
| |
| public void setMaxFractionDigits(String value) { |
| maxFractionDigits = Integer.valueOf(value); |
| } |
| |
| public void setMinGroupingDigits(String value) { |
| minGroupingDigits = Integer.valueOf(value); |
| } |
| |
| public void setBreaks(String value) { |
| breaks = value; |
| } |
| |
| public void setUseSigDigits(String value) { |
| useSigDigits = Integer.valueOf(value); |
| } |
| |
| public void setMinSigDigits(String value) { |
| minSigDigits = Integer.valueOf(value); |
| } |
| |
| public void setMaxSigDigits(String value) { |
| maxSigDigits = Integer.valueOf(value); |
| } |
| |
| public void setUseGrouping(String value) { |
| useGrouping = Integer.valueOf(value); |
| } |
| |
| public void setMultiplier(String value) { |
| multiplier = Integer.valueOf(value); |
| } |
| |
| public void setRoundingIncrement(String value) { |
| roundingIncrement = Double.valueOf(value); |
| } |
| |
| public void setFormatWidth(String value) { |
| formatWidth = Integer.valueOf(value); |
| } |
| |
| public void setPadCharacter(String value) { |
| padCharacter = value; |
| } |
| |
| public void setUseScientific(String value) { |
| useScientific = Integer.valueOf(value); |
| } |
| |
| public void setGrouping(String value) { |
| grouping = Integer.valueOf(value); |
| } |
| |
| public void setGrouping2(String value) { |
| grouping2 = Integer.valueOf(value); |
| } |
| |
| public void setRoundingMode(String value) { |
| roundingMode = fromString(roundingModeMap, value); |
| } |
| |
| public void setCurrencyUsage(String value) { |
| currencyUsage = fromString(currencyUsageMap, value); |
| } |
| |
| public void setMinimumExponentDigits(String value) { |
| minimumExponentDigits = Integer.valueOf(value); |
| } |
| |
| public void setExponentSignAlwaysShown(String value) { |
| exponentSignAlwaysShown = Integer.valueOf(value); |
| } |
| |
| public void setDecimalSeparatorAlwaysShown(String value) { |
| decimalSeparatorAlwaysShown = Integer.valueOf(value); |
| } |
| |
| public void setPadPosition(String value) { |
| padPosition = fromString(padPositionMap, value); |
| } |
| |
| public void setPositivePrefix(String value) { |
| positivePrefix = value; |
| } |
| |
| public void setPositiveSuffix(String value) { |
| positiveSuffix = value; |
| } |
| |
| public void setNegativePrefix(String value) { |
| negativePrefix = value; |
| } |
| |
| public void setNegativeSuffix(String value) { |
| negativeSuffix = value; |
| } |
| |
| public void setSignAlwaysShown(String value) { |
| signAlwaysShown = Integer.valueOf(value); |
| } |
| |
| public void setLocalizedPattern(String value) { |
| localizedPattern = value; |
| } |
| |
| public void setToPattern(String value) { |
| toPattern = value; |
| } |
| |
| public void setToLocalizedPattern(String value) { |
| toLocalizedPattern = value; |
| } |
| |
| public void setStyle(String value) { |
| style = fromString(formatStyleMap, value); |
| } |
| |
| public void setParse(String value) { |
| parse = value; |
| } |
| |
| public void setLenient(String value) { |
| lenient = Integer.valueOf(value); |
| } |
| |
| public void setPlural(String value) { |
| plural = value; |
| } |
| |
| public void setParseIntegerOnly(String value) { |
| parseIntegerOnly = Integer.valueOf(value); |
| } |
| |
| public void setParseCaseSensitive(String value) { |
| parseCaseSensitive = Integer.valueOf(value); |
| } |
| |
| public void setDecimalPatternMatchRequired(String value) { |
| decimalPatternMatchRequired = Integer.valueOf(value); |
| } |
| |
| public void setParseNoExponent(String value) { |
| parseNoExponent = Integer.valueOf(value); |
| } |
| |
| public void setOutputCurrency(String value) { |
| outputCurrency = value; |
| } |
| |
| // end field setters. |
| |
| // start of field clearers |
| // Add clear methods that can be set in one test and cleared |
| // in the next i.e the breaks field. |
| |
| public void clearBreaks() { |
| breaks = null; |
| } |
| |
| public void clearUseGrouping() { |
| useGrouping = null; |
| } |
| |
| public void clearGrouping2() { |
| grouping2 = null; |
| } |
| |
| public void clearGrouping() { |
| grouping = null; |
| } |
| |
| public void clearMinGroupingDigits() { |
| minGroupingDigits = null; |
| } |
| |
| public void clearUseScientific() { |
| useScientific = null; |
| } |
| |
| public void clearDecimalSeparatorAlwaysShown() { |
| decimalSeparatorAlwaysShown = null; |
| } |
| |
| // end field clearers |
| |
| public void setField(String fieldName, String valueString) |
| throws NoSuchMethodException { |
| Method m = getClass().getMethod( |
| fieldToSetter(fieldName), String.class); |
| try { |
| m.invoke(this, valueString); |
| } catch (IllegalAccessException e) { |
| throw new RuntimeException(e); |
| } catch (InvocationTargetException e) { |
| throw new RuntimeException(e); |
| } |
| } |
| |
| public void clearField(String fieldName) |
| throws NoSuchMethodException { |
| Method m = getClass().getMethod(fieldToClearer(fieldName)); |
| try { |
| m.invoke(this); |
| } catch (IllegalAccessException e) { |
| throw new RuntimeException(e); |
| } catch (InvocationTargetException e) { |
| throw new RuntimeException(e); |
| } |
| } |
| |
| @Override |
| public String toString() { |
| StringBuilder result = new StringBuilder(); |
| result.append("{"); |
| boolean first = true; |
| for (String fieldName : fieldOrdering) { |
| try { |
| Field field = getClass().getField(fieldName); |
| Object optionalValue = field.get(this); |
| if (optionalValue == null) { |
| continue; |
| } |
| if (!first) { |
| result.append(", "); |
| } |
| first = false; |
| result.append(fieldName); |
| result.append(": "); |
| result.append(optionalValue); |
| } catch (NoSuchFieldException e) { |
| throw new RuntimeException(e); |
| } catch (SecurityException e) { |
| throw new RuntimeException(e); |
| } catch (IllegalAccessException e) { |
| throw new RuntimeException(e); |
| } |
| } |
| result.append("}"); |
| return result.toString(); |
| } |
| |
| private static String fieldToSetter(String fieldName) { |
| return "set" |
| + Character.toUpperCase(fieldName.charAt(0)) |
| + fieldName.substring(1); |
| } |
| |
| private static String fieldToClearer(String fieldName) { |
| return "clear" |
| + Character.toUpperCase(fieldName.charAt(0)) |
| + fieldName.substring(1); |
| } |
| |
| } |