17935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/* 27935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ******************************************************************************* 37935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Copyright (C) 2007-2014, International Business Machines Corporation and 47935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * others. All Rights Reserved. 57935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ******************************************************************************* 67935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 77935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 87935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpackage com.ibm.icu.dev.test.format; 97935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.text.ParsePosition; 117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Collection; 127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.LinkedHashMap; 137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.LinkedHashSet; 147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Locale; 157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Map; 167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Set; 177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.dev.test.TestFmwk; 197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.text.DecimalFormat; 207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.text.DecimalFormatSymbols; 217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.text.MessageFormat; 227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.text.NumberFormat; 237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.text.PluralFormat; 247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.text.PluralRules; 257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.text.PluralRules.PluralType; 267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.text.PluralRules.SampleType; 277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.util.ULocale; 287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/** 307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @author tschumann (Tim Schumann) 317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpublic class PluralFormatUnitTest extends TestFmwk { 347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public static void main(String[] args) throws Exception { 357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert new PluralFormatUnitTest().run(args); 367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void TestConstructor() { 397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Test correct formatting of numbers. 407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PluralFormat plFmts[] = new PluralFormat[10]; 417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert plFmts[0] = new PluralFormat(); 427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert plFmts[0].applyPattern("other{#}"); 437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert plFmts[1] = new PluralFormat(PluralRules.DEFAULT); 447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert plFmts[1].applyPattern("other{#}"); 457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert plFmts[2] = new PluralFormat(PluralRules.DEFAULT, "other{#}"); 467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert plFmts[3] = new PluralFormat("other{#}"); 477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert plFmts[4] = new PluralFormat(ULocale.getDefault()); 487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert plFmts[4].applyPattern("other{#}"); 497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert plFmts[5] = new PluralFormat(ULocale.getDefault(), PluralRules.DEFAULT); 507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert plFmts[5].applyPattern("other{#}"); 517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert plFmts[6] = new PluralFormat(ULocale.getDefault(), 527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PluralRules.DEFAULT, 537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert "other{#}"); 547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert plFmts[7] = new PluralFormat(ULocale.getDefault(), "other{#}"); 557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Constructors with Java Locale 577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert plFmts[8] = new PluralFormat(Locale.getDefault()); 587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert plFmts[8].applyPattern("other{#}"); 597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert plFmts[9] = new PluralFormat(Locale.getDefault(), PluralRules.DEFAULT); 607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert plFmts[9].applyPattern("other{#}"); 617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // These plural formats should produce the same output as a 637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // NumberFormat for the default locale. 647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert NumberFormat numberFmt = NumberFormat.getInstance(ULocale.getDefault()); 657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int n = 1; n < 13; n++) { 667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String result = numberFmt.format(n); 677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int k = 0; k < plFmts.length; ++k) { 687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this.assertEquals("PluralFormat's output is not as expected", 697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result, plFmts[k].format(n)); 707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Test some bigger numbers. 737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int n = 100; n < 113; n++) { 747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String result = numberFmt.format(n*n); 757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int k = 0; k < plFmts.length; ++k) { 767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this.assertEquals("PluralFormat's output is not as expected", 777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result, plFmts[k].format(n*n)); 787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void TestApplyPatternAndFormat() { 837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Create rules for testing. 847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PluralRules oddAndEven = PluralRules.createRules("odd: n mod 2 is 1"); 857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Test full specified case for testing RuleSet 877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PluralFormat plfOddAndEven = new PluralFormat(oddAndEven); 887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert plfOddAndEven.applyPattern("odd{# is odd.} other{# is even.}"); 897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Test fall back to other. 917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PluralFormat plfOddOrEven = new PluralFormat(oddAndEven); 927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert plfOddOrEven.applyPattern("other{# is odd or even.}"); 937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert NumberFormat numberFormat = 957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert NumberFormat.getInstance(ULocale.getDefault()); 967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int i = 0; i < 22; ++i) { 977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert assertEquals("Fallback to other gave wrong results", 987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert numberFormat.format(i) + " is odd or even.", 997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert plfOddOrEven.format(i)); 1007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert assertEquals("Fully specified PluralFormat gave wrong results", 1017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert numberFormat.format(i) + ((i%2 == 1) ? " is odd." 1027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert : " is even."), 1037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert plfOddAndEven.format(i)); 1047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // ICU 4.8 does not check for duplicate keywords any more. 1077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PluralFormat pf = new PluralFormat(ULocale.ENGLISH, oddAndEven, 1087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert "odd{foo} odd{bar} other{foobar}"); 1097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert assertEquals("should use first occurrence of the 'odd' keyword", "foo", pf.format(1)); 1107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pf.applyPattern("odd{foo} other{bar} other{foobar}"); 1117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert assertEquals("should use first occurrence of the 'other' keyword", "bar", pf.format(2)); 1127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // This sees the first "other" before calling the PluralSelector which then selects "other". 1137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pf.applyPattern("other{foo} odd{bar} other{foobar}"); 1147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert assertEquals("should use first occurrence of the 'other' keyword", "foo", pf.format(2)); 1157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // omit other keyword. 1177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert try { 1187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PluralFormat plFmt = new PluralFormat(oddAndEven); 1197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert plFmt.applyPattern("odd{foo}"); 1207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert errln("Not defining plural case other should result in an " + 1217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert "exception but did not."); 1227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert }catch (IllegalArgumentException e){} 1237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // ICU 4.8 does not check for unknown keywords any more. 1257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 1267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PluralFormat pf = new PluralFormat(ULocale.ENGLISH, oddAndEven, "otto{foo} other{bar}"); 1277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert assertEquals("should ignore unknown keywords", "bar", pf.format(1)); 1287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Test invalid keyword. 1317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert try { 1327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PluralFormat plFmt = new PluralFormat(oddAndEven); 1337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert plFmt.applyPattern("*odd{foo} other{bar}"); 1347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert errln("Defining a message for an invalid keyword should result in " + 1357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert "an exception but did not."); 1367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert }catch (IllegalArgumentException e){} 1377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Test invalid syntax 1397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // -- comma between keyword{message} clauses 1407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // -- space in keywords 1417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // -- keyword{message1}{message2} 1427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert try { 1437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PluralFormat plFmt = new PluralFormat(oddAndEven); 1447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert plFmt.applyPattern("odd{foo},other{bar}"); 1457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert errln("Separating keyword{message} items with other characters " + 1467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert "than space should provoke an exception but did not."); 1477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert }catch (IllegalArgumentException e){} 1487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert try { 1497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PluralFormat plFmt = new PluralFormat(oddAndEven); 1507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert plFmt.applyPattern("od d{foo} other{bar}"); 1517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert errln("Spaces inside keywords should provoke an exception but " + 1527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert "did not."); 1537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert }catch (IllegalArgumentException e){} 1547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert try { 1557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PluralFormat plFmt = new PluralFormat(oddAndEven); 1567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert plFmt.applyPattern("odd{foo}{foobar}other{foo}"); 1577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert errln("Defining multiple messages after a keyword should provoke " + 1587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert "an exception but did not."); 1597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert }catch (IllegalArgumentException e){} 1607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Check that nested format is preserved. 1627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 1637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PluralFormat plFmt = new PluralFormat(oddAndEven); 1647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert plFmt.applyPattern("odd{The number {0, number, #.#0} is odd.}" + 1657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert "other{The number {0, number, #.#0} is even.}"); 1667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int i = 1; i < 3; ++i) { 1677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert assertEquals("format did not preserve a nested format string.", 1687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ((i % 2 == 1) ? 1697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert "The number {0, number, #.#0} is odd." 1707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert : "The number {0, number, #.#0} is even."), 1717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert plFmt.format(i)); 1727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Check that a pound sign in curly braces is preserved. 1767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 1777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PluralFormat plFmt = new PluralFormat(oddAndEven); 1787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert plFmt.applyPattern("odd{The number {1,number,#} is odd.}" + 1797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert "other{The number {2,number,#} is even.}"); 1807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int i = 1; i < 3; ++i) { 1817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert assertEquals("format did not preserve # inside curly braces.", 1827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ((i % 2 == 1) ? "The number {1,number,#} is odd." 1837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert : "The number {2,number,#} is even."), 1847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert plFmt.format(i)); 1857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void TestSamples() { 1927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Map<ULocale,Set<ULocale>> same = new LinkedHashMap(); 1937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (ULocale locale : PluralRules.getAvailableULocales()) { 1947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ULocale otherLocale = PluralRules.getFunctionalEquivalent(locale, null); 1957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Set<ULocale> others = same.get(otherLocale); 1967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (others == null) same.put(otherLocale, others = new LinkedHashSet()); 1977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert others.add(locale); 1987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert continue; 1997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (ULocale locale0 : same.keySet()) { 2017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PluralRules rules = PluralRules.forLocale(locale0); 2027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String localeName = locale0.toString().length() == 0 ? "root" : locale0.toString(); 2037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert logln(localeName + "\t=\t" + same.get(locale0)); 2047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert logln(localeName + "\ttoString\t" + rules.toString()); 2057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Set<String> keywords = rules.getKeywords(); 2067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (String keyword : keywords) { 2077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Collection<Double> list = rules.getSamples(keyword); 2087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (list.size() == 0) { 2097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // if there aren't any integer samples, get the decimal ones. 2107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert list = rules.getSamples(keyword, SampleType.DECIMAL); 2117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (list == null || list.size() == 0) { 2147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert errln("Empty list for " + localeName + " : " + keyword); 2157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 2167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert logln("\t" + localeName + " : " + keyword + " ; " + list); 2177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void TestSetLocale() { 2237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Create rules for testing. 2247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PluralRules oddAndEven = PluralRules.createRules("odd__: n mod 2 is 1"); 2257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PluralFormat plFmt = new PluralFormat(oddAndEven); 2277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert plFmt.applyPattern("odd__{odd} other{even}"); 2287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert plFmt.setLocale(ULocale.ENGLISH); 2297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Check that pattern gets deleted. 2317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert NumberFormat nrFmt = NumberFormat.getInstance(ULocale.ENGLISH); 2327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert assertEquals("pattern was not resetted by setLocale() call.", 2337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert nrFmt.format(5), 2347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert plFmt.format(5)); 2357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Check that rules got updated. 2377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert plFmt.applyPattern("odd__{odd} other{even}"); 2387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert assertEquals("SetLocale should reset rules but did not.", "even", plFmt.format(1)); 2397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert plFmt.applyPattern("one{one} other{not one}"); 2417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int i = 0; i < 20; ++i) { 2427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert assertEquals("Wrong ruleset loaded by setLocale()", 2437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ((i==1) ? "one" : "not one"), 2447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert plFmt.format(i)); 2457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void TestParse() { 2497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PluralFormat plFmt = new PluralFormat("other{test}"); 2507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert try { 2517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert plFmt.parse("test", new ParsePosition(0)); 2527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert errln("parse() should throw an UnsupportedOperationException but " + 2537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert "did not"); 2547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } catch (UnsupportedOperationException e) { 2557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert plFmt = new PluralFormat("other{test}"); 2587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert try { 2597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert plFmt.parseObject("test", new ParsePosition(0)); 2607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert errln("parse() should throw an UnsupportedOperationException but " + 2617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert "did not"); 2627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } catch (UnsupportedOperationException e) { 2637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void TestPattern() { 2677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Object[] args = { "acme", null }; 2687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 2707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // ICU 4.8 PluralFormat does not trim() its pattern any more. 2717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // None of the other *Format classes do. 2727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String pat = " one {one ''widget} other {# widgets} "; 2737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PluralFormat pf = new PluralFormat(pat); 2747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert assertEquals("should not trim() the pattern", pat, pf.toPattern()); 2757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert MessageFormat pfmt = new MessageFormat("The disk ''{0}'' contains {1, plural, one {one ''''{1, number, #.0}'''' widget} other {# widgets}}."); 2787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert logln(""); 2797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int i = 0; i < 3; ++i) { 2807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert args[1] = new Integer(i); 2817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert logln(pfmt.format(args)); 2827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* ICU 4.8 returns null instead of a choice/plural/select Format object 2847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * (because it does not create an object for any "complex" argument). 2857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PluralFormat pf = (PluralFormat)pfmt.getFormatsByArgumentIndex()[1]; 2867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert logln(pf.toPattern()); 2877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 2887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert logln(pfmt.toPattern()); 2897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert MessageFormat pfmt2 = new MessageFormat(pfmt.toPattern()); 2907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert assertEquals("message formats are equal", pfmt, pfmt2); 2917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void TestExtendedPluralFormat() { 2947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String[] targets = { 2957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert "There are no widgets.", 2967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert "There is one widget.", 2977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert "There is a bling widget and one other widget.", 2987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert "There is a bling widget and 2 other widgets.", 2997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert "There is a bling widget and 3 other widgets.", 3007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert "Widgets, five (5-1=4) there be.", 3017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert "There is a bling widget and 5 other widgets.", 3027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert "There is a bling widget and 6 other widgets.", 3037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert }; 3047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String pluralStyle = 3057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert "offset:1.0 " 3067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert + "=0 {There are no widgets.} " 3077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert + "=1.0 {There is one widget.} " 3087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert + "=5 {Widgets, five (5-1=#) there be.} " 3097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert + "one {There is a bling widget and one other widget.} " 3107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert + "other {There is a bling widget and # other widgets.}"; 3117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PluralFormat pf = new PluralFormat(ULocale.ENGLISH, pluralStyle); 3127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert MessageFormat mf = new MessageFormat("{0,plural," + pluralStyle + "}", ULocale.ENGLISH); 3137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Integer args[] = new Integer[1]; 3147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (int i = 0; i <= 7; ++i) { 3157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String result = pf.format(i); 3167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert assertEquals("PluralFormat.format(value " + i + ")", targets[i], result); 3177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert args[0] = i; 3187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result = mf.format(args); 3197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert assertEquals("MessageFormat.format(value " + i + ")", targets[i], result); 3207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Try explicit values after keywords. 3237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pf.applyPattern("other{zz}other{yy}one{xx}one{ww}=1{vv}=1{uu}"); 3247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert assertEquals("should find first matching *explicit* value", "vv", pf.format(1)); 3257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void TestExtendedPluralFormatParsing() { 3287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String[] failures = { 3297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert "offset:1..0 =0 {Foo}", 3307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert "offset:1.0 {Foo}", 3317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert "=0= {Foo}", 3327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert "=0 {Foo} =0.0 {Bar}", 3337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert " = {Foo}", 3347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert }; 3357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (String fmt : failures) { 3367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert try { 3377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert new PluralFormat(fmt); 3387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert fail("expected exception when parsing '" + fmt + "'"); 3397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } catch (IllegalArgumentException e) { 3407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // ok 3417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void TestOrdinalFormat() { 3467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String pattern = "one{#st file}two{#nd file}few{#rd file}other{#th file}"; 3477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PluralFormat pf = new PluralFormat(ULocale.ENGLISH, PluralType.ORDINAL, pattern); 3487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert assertEquals("PluralFormat.format(321)", "321st file", pf.format(321)); 3497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert assertEquals("PluralFormat.format(22)", "22nd file", pf.format(22)); 3507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert assertEquals("PluralFormat.format(3)", "3rd file", pf.format(3)); 3517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Code coverage: Use the other new-for-PluralType constructor as well. 3537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pf = new PluralFormat(ULocale.ENGLISH, PluralType.ORDINAL); 3547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pf.applyPattern(pattern); 3557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert assertEquals("PluralFormat.format(456)", "456th file", pf.format(456)); 3567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert assertEquals("PluralFormat.format(111)", "111th file", pf.format(111)); 3577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void TestDecimals() { 3607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Simple number replacement. 3617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PluralFormat pf = new PluralFormat(ULocale.ENGLISH, "one{one meter}other{# meters}"); 3627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert assertEquals("simple format(1)", "one meter", pf.format(1)); 3637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert assertEquals("simple format(1.5)", "1.5 meters", pf.format(1.5)); 3647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PluralFormat pf2 = new PluralFormat(ULocale.ENGLISH, 3657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert "offset:1 one{another meter}other{another # meters}"); 3667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pf2.setNumberFormat(new DecimalFormat("0.0", new DecimalFormatSymbols(ULocale.ENGLISH))); 3677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert assertEquals("offset-decimals format(1)", "another 0.0 meters", pf2.format(1)); 3687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert assertEquals("offset-decimals format(2)", "another 1.0 meters", pf2.format(2)); 3697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert assertEquals("offset-decimals format(2.5)", "another 1.5 meters", pf2.format(2.5)); 3707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert} 372