1 package org.unicode.cldr.unittest; 2 3 import com.google.common.base.Objects; 4 import com.ibm.icu.impl.locale.XCldrStub.Splitter; 5 import com.ibm.icu.impl.number.DecimalQuantity; 6 import com.ibm.icu.impl.number.DecimalQuantity_DualStorageBCD; 7 import com.ibm.icu.text.CompactDecimalFormat; 8 import com.ibm.icu.text.CompactDecimalFormat.CompactStyle; 9 import com.ibm.icu.text.DecimalFormat; 10 import com.ibm.icu.text.NumberFormat; 11 import com.ibm.icu.util.Currency; 12 import com.ibm.icu.util.ULocale; 13 import java.util.LinkedHashSet; 14 import java.util.Map; 15 import java.util.Map.Entry; 16 import java.util.Set; 17 import org.unicode.cldr.test.BuildIcuCompactDecimalFormat; 18 import org.unicode.cldr.test.BuildIcuCompactDecimalFormat.CurrencyStyle; 19 import org.unicode.cldr.util.CLDRConfig; 20 import org.unicode.cldr.util.CLDRFile; 21 import org.unicode.cldr.util.Factory; 22 import org.unicode.cldr.util.ICUServiceBuilder; 23 import org.unicode.cldr.util.StandardCodes; 24 import org.unicode.cldr.util.SupplementalDataInfo; 25 import org.unicode.cldr.util.SupplementalDataInfo.PluralInfo; 26 import org.unicode.cldr.util.SupplementalDataInfo.PluralInfo.Count; 27 import org.unicode.cldr.util.VerifyCompactNumbers; 28 29 public class TestCompactNumbers extends TestFmwkPlus { 30 static final boolean DEBUG = false; 31 private static StandardCodes sc = StandardCodes.make(); 32 private static final CLDRConfig CLDRCONFIG = CLDRConfig.getInstance(); 33 private static final SupplementalDataInfo SDI = CLDRCONFIG.getSupplementalDataInfo(); 34 private static final CLDRFile ENGLISH = CLDRCONFIG.getEnglish(); 35 private static final Factory factory2 = CLDRCONFIG.getCldrFactory(); 36 main(String[] args)37 public static void main(String[] args) { 38 new TestCompactNumbers().run(args); 39 } 40 TestVerify()41 public void TestVerify() { 42 // Just verify no crashes 43 CLDRFile cldrFile = factory2.make("it", true); 44 Appendable out = new StringBuilder(); 45 VerifyCompactNumbers.showNumbers(cldrFile, true, "EUR", out, factory2); 46 if (DEBUG) { 47 System.out.println(out); 48 } 49 } 50 TestInternals()51 public void TestInternals() { 52 // Just verify no crashes 53 String locale = "it"; 54 String currencyCode = "EUR"; 55 ULocale locale2 = ULocale.forLanguageTag(locale); 56 CLDRFile cldrFile = factory2.make(locale, true); 57 Set<String> debugCreationErrors = new LinkedHashSet<>(); 58 String[] debugOriginals = null; 59 60 ICUServiceBuilder builder = new ICUServiceBuilder().setCldrFile(cldrFile); 61 NumberFormat nf = builder.getNumberFormat(1); 62 63 CompactDecimalFormat cdf = 64 BuildIcuCompactDecimalFormat.build( 65 cldrFile, 66 debugCreationErrors, 67 debugOriginals, 68 CompactStyle.SHORT, 69 locale2, 70 CurrencyStyle.PLAIN, 71 currencyCode); 72 73 Map<String, Map<String, String>> data = 74 BuildIcuCompactDecimalFormat.buildCustomData( 75 cldrFile, CompactStyle.SHORT, CurrencyStyle.PLAIN); 76 if (DEBUG) { 77 for (Entry<String, Map<String, String>> entry : data.entrySet()) { 78 System.out.println(entry); 79 } 80 } 81 82 CompactDecimalFormat cdfs = 83 BuildIcuCompactDecimalFormat.build( 84 cldrFile, 85 debugCreationErrors, 86 debugOriginals, 87 CompactStyle.LONG, 88 locale2, 89 CurrencyStyle.PLAIN, 90 currencyCode); 91 CompactDecimalFormat cdfCurr = 92 BuildIcuCompactDecimalFormat.build( 93 cldrFile, 94 debugCreationErrors, 95 debugOriginals, 96 CompactStyle.SHORT, 97 locale2, 98 CurrencyStyle.CURRENCY, 99 currencyCode); 100 101 Set<Double> allSamples = 102 VerifyCompactNumbers.collectSamplesAndSetFormats( 103 currencyCode, locale, SDI, cdf, cdfs, cdfCurr); 104 105 for (double source : allSamples) { 106 if (false && source == 22000000 && locale.equals("cs")) { 107 System.out.println("**"); 108 } 109 110 String formattedNumber = nf.format(source); 111 String compactFormattedNumber = cdf == null ? "n/a" : cdf.format(source); 112 String compactLongFormattedNumber = cdfs == null ? "n/a" : cdfs.format(source); 113 String compactCurrFormattedNumber = cdfs == null ? "n/a" : cdfCurr.format(source); 114 if (DEBUG) 115 System.out.println( 116 source 117 + "\tnf:\t" 118 + formattedNumber 119 + "\tcnf:\t" 120 + compactFormattedNumber 121 + "\tclnf:\t" 122 + compactLongFormattedNumber 123 + "\tccnf:\t" 124 + compactCurrFormattedNumber); 125 } 126 } 127 128 /** 129 * Test case for VerifyCompactNumbers https://unicode-org.atlassian.net/browse/CLDR-15737 130 * https://unicode-org.atlassian.net/browse/CLDR-15762 131 */ TestVerifyCompactNumbers()132 public void TestVerifyCompactNumbers() { 133 Set<String> debugCreationErrors = new LinkedHashSet<>(); 134 String[] debugOriginals = null; 135 String oldLocale = ""; 136 String oldCurrencyCode = ""; 137 CompactDecimalFormat cdfCurr = null; 138 CompactStyle compactStyle = null; 139 CurrencyStyle currencyStyle = null; 140 CLDRFile cldrFile = null; 141 142 Object[][] tests = { 143 {"cs", null, 1100000d, "1,1 milionu"}, // should be 'many', not 1,1 milionů == 'other' 144 /* Background for cs 145 * <pattern type="1000000" count="one">0 milion</pattern> 146 * <pattern type="1000000" count="few">0 miliony</pattern> 147 * <pattern type="1000000" count="many">0 milionu</pattern> 148 * <pattern type="1000000" count="other">0 milionů</pattern> 149 * https://unicode-org.github.io/cldr-staging/charts/41/supplemental/language_plural_rules.html#cs 150 */ 151 {"fr", "EUR", 100d, "100 €"}, 152 {"fr", "EUR", 1000d, "1 k €"}, 153 }; 154 155 for (Object[] row : tests) { 156 String locale = row[0].toString(); 157 String currencyCode = row[1] == null ? null : row[1].toString(); 158 double value = (double) row[2]; 159 String expected = row[3].toString(); 160 161 if (!locale.equals(oldLocale) || Objects.equal(currencyCode, oldCurrencyCode)) { 162 oldLocale = locale; 163 oldCurrencyCode = currencyCode; 164 cldrFile = factory2.make(locale, true); 165 166 debugCreationErrors.clear(); 167 if (currencyCode == null) { 168 compactStyle = CompactStyle.LONG; 169 currencyStyle = CurrencyStyle.PLAIN; 170 171 cdfCurr = 172 BuildIcuCompactDecimalFormat.build( 173 cldrFile, 174 debugCreationErrors, 175 debugOriginals, 176 compactStyle, 177 ULocale.forLanguageTag(locale), 178 currencyStyle, 179 null); 180 181 // note: custom data looks good: 182 // 1000000={other=0 milionů, one=0 milion, few=0 miliony, many=0 milionu} 183 184 } else { 185 compactStyle = CompactStyle.SHORT; 186 currencyStyle = CurrencyStyle.CURRENCY; 187 188 cdfCurr = 189 BuildIcuCompactDecimalFormat.build( 190 cldrFile, 191 debugCreationErrors, 192 debugOriginals, 193 compactStyle, 194 ULocale.forLanguageTag(locale), 195 currencyStyle, 196 currencyCode); 197 198 cdfCurr.setCurrency(Currency.getInstance(currencyCode)); 199 int sigDigits = 3; 200 cdfCurr.setMaximumSignificantDigits(sigDigits); 201 } 202 } 203 String actual = cdfCurr.format(value); 204 if (!assertEquals("Formatted " + value, expected, actual)) { 205 if (DEBUG) { 206 PluralInfo rules = SupplementalDataInfo.getInstance().getPlurals(locale); 207 int v, f, e; 208 DecimalQuantity dq = DecimalQuantity_DualStorageBCD.fromExponentString("1.1"); 209 Count count = rules.getCount(dq); 210 System.out.println("Locale: " + locale); 211 ICUServiceBuilder builder = new ICUServiceBuilder().setCldrFile(cldrFile); 212 213 DecimalFormat decimalFormat = 214 currencyStyle == CurrencyStyle.PLAIN 215 ? builder.getNumberFormat(1) 216 : builder.getCurrencyFormat(currencyCode); 217 final String pattern = decimalFormat.toPattern(); 218 219 System.out.println("Fallback pattern: " + pattern); 220 System.out.println("Plural Rules: "); 221 semiSplit 222 .split(rules.getRules()) 223 .forEach(x -> System.out.println("\t" + x + ";")); 224 System.out.println("Plural sample result: " + dq + " => " + count); 225 226 Map<String, Map<String, String>> customData = 227 BuildIcuCompactDecimalFormat.buildCustomData( 228 cldrFile, compactStyle, currencyStyle); 229 customData.forEach((k, vv) -> System.out.println("\t" + k + "\t" + vv)); 230 } 231 } 232 } 233 } 234 235 static final Splitter semiSplit = Splitter.on(';').trimResults(); 236 } 237