17935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/* 27935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ******************************************************************************* 3f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert * Copyright (C) 2007-2015, International Business Machines Corporation and 47935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * others. All Rights Reserved. 57935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ******************************************************************************* 67935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 77935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 87935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpackage com.ibm.icu.text; 97935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.io.IOException; 117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.io.ObjectInputStream; 127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.text.FieldPosition; 137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.text.ParsePosition; 147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Locale; 157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Map; 167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.impl.Utility; 187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.text.PluralRules.FixedDecimal; 197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.text.PluralRules.PluralType; 207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.util.ULocale; 217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.util.ULocale.Category; 227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/** 247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p> 257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>PluralFormat</code> supports the creation of internationalized 267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * messages with plural inflection. It is based on <i>plural 277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * selection</i>, i.e. the caller specifies messages for each 287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * plural case that can appear in the user's language and the 297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>PluralFormat</code> selects the appropriate message based on 307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the number. 317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </p> 327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <h4>The Problem of Plural Forms in Internationalized Messages</h4> 337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p> 347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Different languages have different ways to inflect 357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * plurals. Creating internationalized messages that include plural 367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * forms is only feasible when the framework is able to handle plural 377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * forms of <i>all</i> languages correctly. <code>ChoiceFormat</code> 387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * doesn't handle this well, because it attaches a number interval to 397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * each message and selects the message whose interval contains a 407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * given number. This can only handle a finite number of 417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * intervals. But in some languages, like Polish, one plural case 427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * applies to infinitely many intervals (e.g., the paucal case applies to 437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * numbers ending with 2, 3, or 4 except those ending with 12, 13, or 447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 14). Thus <code>ChoiceFormat</code> is not adequate. 457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </p><p> 467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>PluralFormat</code> deals with this by breaking the problem 477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * into two parts: 487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <ul> 497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>It uses <code>PluralRules</code> that can define more complex 507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * conditions for a plural case than just a single interval. These plural 517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * rules define both what plural cases exist in a language, and to 527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * which numbers these cases apply. 537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <li>It provides predefined plural rules for many languages. Thus, the programmer 547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * need not worry about the plural cases of a language and 557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * does not have to define the plural cases; they can simply 567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * use the predefined keywords. The whole plural formatting of messages can 577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * be done using localized patterns from resource bundles. For predefined plural 587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * rules, see the CLDR <i>Language Plural Rules</i> page at 597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html 607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </ul> 617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </p> 627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <h4>Usage of <code>PluralFormat</code></h4> 637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>Note: Typically, plural formatting is done via <code>MessageFormat</code> 647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * with a <code>plural</code> argument type, 657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * rather than using a stand-alone <code>PluralFormat</code>. 667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </p><p> 677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * This discussion assumes that you use <code>PluralFormat</code> with 687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * a predefined set of plural rules. You can create one using one of 697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the constructors that takes a <code>ULocale</code> object. To 707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * specify the message pattern, you can either pass it to the 717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * constructor or set it explicitly using the 727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>applyPattern()</code> method. The <code>format()</code> 737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * method takes a number object and selects the message of the 747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * matching plural case. This message will be returned. 757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </p> 767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <h5>Patterns and Their Interpretation</h5> 777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p> 787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The pattern text defines the message output for each plural case of the 797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * specified locale. Syntax: 807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <blockquote><pre> 817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * pluralStyle = [offsetValue] (selector '{' message '}')+ 827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * offsetValue = "offset:" number 837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * selector = explicitValue | keyword 847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * explicitValue = '=' number // adjacent, no white space in between 857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * keyword = [^[[:Pattern_Syntax:][:Pattern_White_Space:]]]+ 867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * message: see {@link MessageFormat} 877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </pre></blockquote> 887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Pattern_White_Space between syntax elements is ignored, except 897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * between the {curly braces} and their sub-message, 907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * and between the '=' and the number of an explicitValue. 917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </p><p> 937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * There are 6 predefined case keywords in CLDR/ICU - 'zero', 'one', 'two', 'few', 'many' and 947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 'other'. You always have to define a message text for the default plural case 957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * "<code>other</code>" which is contained in every rule set. 967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * If you do not specify a message text for a particular plural case, the 977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * message text of the plural case "<code>other</code>" gets assigned to this 987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * plural case. 997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </p><p> 1007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * When formatting, the input number is first matched against the explicitValue clauses. 1017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * If there is no exact-number match, then a keyword is selected by calling 1027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the <code>PluralRules</code> with the input number <em>minus the offset</em>. 1037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * (The offset defaults to 0 if it is omitted from the pattern string.) 1047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * If there is no clause with that keyword, then the "other" clauses is returned. 1057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </p><p> 1067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * An unquoted pound sign (<code>#</code>) in the selected sub-message 1077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * itself (i.e., outside of arguments nested in the sub-message) 1087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * is replaced by the input number minus the offset. 1097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The number-minus-offset value is formatted using a 1107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>NumberFormat</code> for the <code>PluralFormat</code>'s locale. If you 1117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * need special number formatting, you have to use a <code>MessageFormat</code> 1127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * and explicitly specify a <code>NumberFormat</code> argument. 1137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <strong>Note:</strong> That argument is formatting without subtracting the offset! 1147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * If you need a custom format and have a non-zero offset, then you need to pass the 1157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * number-minus-offset value as a separate parameter. 1167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </p> 1177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * For a usage example, see the {@link MessageFormat} class documentation. 1187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <h4>Defining Custom Plural Rules</h4> 1207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>If you need to use <code>PluralFormat</code> with custom rules, you can 1217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * create a <code>PluralRules</code> object and pass it to 1227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>PluralFormat</code>'s constructor. If you also specify a locale in this 1237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * constructor, this locale will be used to format the number in the message 1247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * texts. 1257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </p><p> 1267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * For more information about <code>PluralRules</code>, see 1277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@link PluralRules}. 1287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * </p> 1297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @author tschumann (Tim Schumann) 1317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.8 1327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 1337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpublic class PluralFormat extends UFormat { 1347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final long serialVersionUID = 1L; 1357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 1377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The locale used for standard number formatting and getting the predefined 1387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * plural rules (if they were not defined explicitely). 1397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @serial 1407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 1417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private ULocale ulocale = null; 1427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 1447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The plural rules used for plural selection. 1457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @serial 1467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 1477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private PluralRules pluralRules = null; 1487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 1507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The applied pattern string. 1517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @serial 1527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 1537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private String pattern = null; 1547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 1567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The MessagePattern which contains the parsed structure of the pattern string. 1577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 1587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert transient private MessagePattern msgPattern; 1597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 1617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Obsolete with use of MessagePattern since ICU 4.8. Used to be: 1627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The format messages for each plural case. It is a mapping: 1637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>String</code>(plural case keyword) --> <code>String</code> 1647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * (message for this plural case). 1657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @serial 1667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 1677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private Map<String, String> parsedValues = null; 1687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 1707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * This <code>NumberFormat</code> is used for the standard formatting of 1717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the number inserted into the message. 1727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @serial 1737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 1747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private NumberFormat numberFormat = null; 1757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 1777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The offset to subtract before invoking plural rules. 1787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 1797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert transient private double offset = 0; 1807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 1827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Creates a new cardinal-number <code>PluralFormat</code> for the default <code>FORMAT</code> locale. 1837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * This locale will be used to get the set of plural rules and for standard 1847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * number formatting. 1857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see Category#FORMAT 1867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.8 1877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 1887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public PluralFormat() { 1897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert init(null, PluralType.CARDINAL, ULocale.getDefault(Category.FORMAT), null); 1907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 1937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Creates a new cardinal-number <code>PluralFormat</code> for a given locale. 1947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param ulocale the <code>PluralFormat</code> will be configured with 1957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * rules for this locale. This locale will also be used for standard 1967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * number formatting. 1977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.8 1987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 1997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public PluralFormat(ULocale ulocale) { 2007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert init(null, PluralType.CARDINAL, ulocale, null); 2017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 2047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Creates a new cardinal-number <code>PluralFormat</code> for a given JDK locale. 2057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param locale the <code>PluralFormat</code> will be configured with 2067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * rules for this locale. This locale will also be used for standard 2077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * number formatting. 2087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @draft ICU 54 2097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @provisional This API might change or be removed in a future release. 2107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 2117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public PluralFormat(Locale locale) { 2127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this(ULocale.forLocale(locale)); 2137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 2167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Creates a new cardinal-number <code>PluralFormat</code> for a given set of rules. 2177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The standard number formatting will be done using the default <code>FORMAT</code> locale. 2187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param rules defines the behavior of the <code>PluralFormat</code> 2197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * object. 2207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see Category#FORMAT 2217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.8 2227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 2237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public PluralFormat(PluralRules rules) { 2247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert init(rules, PluralType.CARDINAL, ULocale.getDefault(Category.FORMAT), null); 2257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 2287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Creates a new cardinal-number <code>PluralFormat</code> for a given set of rules. 2297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The standard number formatting will be done using the given locale. 2307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param ulocale the default number formatting will be done using this 2317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * locale. 2327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param rules defines the behavior of the <code>PluralFormat</code> 2337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * object. 2347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.8 2357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 2367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public PluralFormat(ULocale ulocale, PluralRules rules) { 2377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert init(rules, PluralType.CARDINAL, ulocale, null); 2387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 2417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Creates a new cardinal-number <code>PluralFormat</code> for a given set of rules. 2427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The standard number formatting will be done using the given locale. 2437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param locale the default number formatting will be done using this 2447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * locale. 2457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param rules defines the behavior of the <code>PluralFormat</code> 2467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * object. 2477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @draft ICU 54 2487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @provisional This API might change or be removed in a future release. 2497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 2507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public PluralFormat(Locale locale, PluralRules rules) { 2517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this(ULocale.forLocale(locale), rules); 2527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 2557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Creates a new <code>PluralFormat</code> for the plural type. 2567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The standard number formatting will be done using the given locale. 2577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param ulocale the default number formatting will be done using this 2587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * locale. 2597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param type The plural type (e.g., cardinal or ordinal). 2607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 50 2617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 2627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public PluralFormat(ULocale ulocale, PluralType type) { 2637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert init(null, type, ulocale, null); 2647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 2677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Creates a new <code>PluralFormat</code> for the plural type. 2687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The standard number formatting will be done using the given JDK locale. 2697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param locale the default number formatting will be done using this 2707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * locale. 2717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param type The plural type (e.g., cardinal or ordinal). 2727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @draft ICU 54 2737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @provisional This API might change or be removed in a future release. 2747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 2757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public PluralFormat(Locale locale, PluralType type) { 2767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this(ULocale.forLocale(locale), type); 2777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 2807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Creates a new cardinal-number <code>PluralFormat</code> for a given pattern string. 2817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The default <code>FORMAT</code> locale will be used to get the set of plural rules and for 2827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * standard number formatting. 2837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param pattern the pattern for this <code>PluralFormat</code>. 2847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @throws IllegalArgumentException if the pattern is invalid. 2857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see Category#FORMAT 2867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.8 2877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 2887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public PluralFormat(String pattern) { 2897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert init(null, PluralType.CARDINAL, ULocale.getDefault(Category.FORMAT), null); 2907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert applyPattern(pattern); 2917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 2947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Creates a new cardinal-number <code>PluralFormat</code> for a given pattern string and 2957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * locale. 2967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The locale will be used to get the set of plural rules and for 2977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * standard number formatting. 2987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>Example code:{@.jcite com.ibm.icu.samples.text.pluralformat.PluralFormatSample:---PluralFormatExample} 2997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param ulocale the <code>PluralFormat</code> will be configured with 3007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * rules for this locale. This locale will also be used for standard 3017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * number formatting. 3027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param pattern the pattern for this <code>PluralFormat</code>. 3037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @throws IllegalArgumentException if the pattern is invalid. 3047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.8 3057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 3067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public PluralFormat(ULocale ulocale, String pattern) { 3077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert init(null, PluralType.CARDINAL, ulocale, null); 3087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert applyPattern(pattern); 3097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 3127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Creates a new cardinal-number <code>PluralFormat</code> for a given set of rules and a 3137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * pattern. 3147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The standard number formatting will be done using the default <code>FORMAT</code> locale. 3157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param rules defines the behavior of the <code>PluralFormat</code> 3167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * object. 3177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param pattern the pattern for this <code>PluralFormat</code>. 3187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @throws IllegalArgumentException if the pattern is invalid. 3197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see Category#FORMAT 3207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.8 3217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 3227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public PluralFormat(PluralRules rules, String pattern) { 3237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert init(rules, PluralType.CARDINAL, ULocale.getDefault(Category.FORMAT), null); 3247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert applyPattern(pattern); 3257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 3287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Creates a new cardinal-number <code>PluralFormat</code> for a given set of rules, a 3297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * pattern and a locale. 3307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param ulocale the <code>PluralFormat</code> will be configured with 3317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * rules for this locale. This locale will also be used for standard 3327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * number formatting. 3337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param rules defines the behavior of the <code>PluralFormat</code> 3347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * object. 3357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param pattern the pattern for this <code>PluralFormat</code>. 3367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @throws IllegalArgumentException if the pattern is invalid. 3377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.8 3387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 3397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public PluralFormat(ULocale ulocale, PluralRules rules, String pattern) { 3407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert init(rules, PluralType.CARDINAL, ulocale, null); 3417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert applyPattern(pattern); 3427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 3457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Creates a new <code>PluralFormat</code> for a plural type, a 3467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * pattern and a locale. 3477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param ulocale the <code>PluralFormat</code> will be configured with 3487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * rules for this locale. This locale will also be used for standard 3497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * number formatting. 3507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param type The plural type (e.g., cardinal or ordinal). 3517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param pattern the pattern for this <code>PluralFormat</code>. 3527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @throws IllegalArgumentException if the pattern is invalid. 3537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 50 3547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 3557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public PluralFormat(ULocale ulocale, PluralType type, String pattern) { 3567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert init(null, type, ulocale, null); 3577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert applyPattern(pattern); 3587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 3617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Creates a new <code>PluralFormat</code> for a plural type, a 3627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * pattern and a locale. 3637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param ulocale the <code>PluralFormat</code> will be configured with 3647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * rules for this locale. This locale will also be used for standard 3657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * number formatting. 3667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param type The plural type (e.g., cardinal or ordinal). 3677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param pattern the pattern for this <code>PluralFormat</code>. 3687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param numberFormat The number formatter to use. 3697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @throws IllegalArgumentException if the pattern is invalid. 3707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 3717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*package*/ PluralFormat(ULocale ulocale, PluralType type, String pattern, NumberFormat numberFormat) { 3727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert init(null, type, ulocale, numberFormat); 3737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert applyPattern(pattern); 3747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 3777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Initializes the <code>PluralRules</code> object. 3787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Postcondition:<br/> 3797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>ulocale</code> : is <code>locale</code><br/> 3807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>pluralRules</code>: if <code>rules</code> != <code>null</code> 3817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * it's set to rules, otherwise it is the 3827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * predefined plural rule set for the locale 3837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>ulocale</code>.<br/> 3847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>parsedValues</code>: is <code>null</code><br/> 3857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>pattern</code>: is <code>null</code><br/> 3867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>numberFormat</code>: a <code>NumberFormat</code> for the locale 3877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>ulocale</code>. 3887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 3897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private void init(PluralRules rules, PluralType type, ULocale locale, NumberFormat numberFormat) { 3907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ulocale = locale; 3917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pluralRules = (rules == null) ? PluralRules.forLocale(ulocale, type) 3927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert : rules; 3937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert resetPattern(); 3947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this.numberFormat = (numberFormat == null) ? NumberFormat.getInstance(ulocale) : numberFormat; 3957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private void resetPattern() { 3987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pattern = null; 3997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if(msgPattern != null) { 4007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert msgPattern.clear(); 4017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert offset = 0; 4037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 4057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 4067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Sets the pattern used by this plural format. 4077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The method parses the pattern and creates a map of format strings 4087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * for the plural rules. 4097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Patterns and their interpretation are specified in the class description. 4107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 4117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param pattern the pattern for this plural format. 4127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @throws IllegalArgumentException if the pattern is invalid. 4137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.8 4147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 4157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void applyPattern(String pattern) { 4167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this.pattern = pattern; 4177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (msgPattern == null) { 4187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert msgPattern = new MessagePattern(); 4197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert try { 4217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert msgPattern.parsePluralStyle(pattern); 4227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert offset = msgPattern.getPluralOffset(0); 4237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } catch(RuntimeException e) { 4247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert resetPattern(); 4257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw e; 4267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 4297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 4307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Returns the pattern for this PluralFormat. 4317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 4327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return the pattern string 4337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 4.2 4347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 4357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public String toPattern() { 4367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return pattern; 4377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 4397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 4407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Finds the PluralFormat sub-message for the given number, or the "other" sub-message. 4417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param pattern A MessagePattern. 4427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param partIndex the index of the first PluralFormat argument style part. 4437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param selector the PluralSelector for mapping the number (minus offset) to a keyword. 4447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param context worker object for the selector. 4457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param number a number to be matched to one of the PluralFormat argument's explicit values, 4467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * or mapped via the PluralSelector. 4477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return the sub-message start part index. 4487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 4497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*package*/ static int findSubMessage( 4507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert MessagePattern pattern, int partIndex, 4517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PluralSelector selector, Object context, double number) { 4527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int count=pattern.countParts(); 4537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert double offset; 4547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert MessagePattern.Part part=pattern.getPart(partIndex); 4557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if(part.getType().hasNumericValue()) { 4567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert offset=pattern.getNumericValue(part); 4577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ++partIndex; 4587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 4597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert offset=0; 4607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // The keyword is null until we need to match against a non-explicit, not-"other" value. 4627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Then we get the keyword from the selector. 4637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // (In other words, we never call the selector if we match against an explicit value, 4647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // or if the only non-explicit keyword is "other".) 4657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String keyword=null; 4667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // When we find a match, we set msgStart>0 and also set this boolean to true 4677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // to avoid matching the keyword again (duplicates are allowed) 4687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // while we continue to look for an explicit-value match. 4697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean haveKeywordMatch=false; 4707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // msgStart is 0 until we find any appropriate sub-message. 4717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // We remember the first "other" sub-message if we have not seen any 4727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // appropriate sub-message before. 4737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // We remember the first matching-keyword sub-message if we have not seen 4747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // one of those before. 4757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // (The parser allows [does not check for] duplicate keywords. 4767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // We just have to make sure to take the first one.) 4777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // We avoid matching the keyword twice by also setting haveKeywordMatch=true 4787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // at the first keyword match. 4797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // We keep going until we find an explicit-value match or reach the end of the plural style. 4807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int msgStart=0; 4817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Iterate over (ARG_SELECTOR [ARG_INT|ARG_DOUBLE] message) tuples 4827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // until ARG_LIMIT or end of plural-only pattern. 4837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert do { 4847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert part=pattern.getPart(partIndex++); 4857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert MessagePattern.Part.Type type=part.getType(); 4867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if(type==MessagePattern.Part.Type.ARG_LIMIT) { 4877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert break; 4887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert assert type==MessagePattern.Part.Type.ARG_SELECTOR; 4907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // part is an ARG_SELECTOR followed by an optional explicit value, and then a message 4917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if(pattern.getPartType(partIndex).hasNumericValue()) { 4927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // explicit value like "=2" 4937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert part=pattern.getPart(partIndex++); 4947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if(number==pattern.getNumericValue(part)) { 4957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // matches explicit value 4967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return partIndex; 4977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if(!haveKeywordMatch) { 4997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // plural keyword like "few" or "other" 5007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Compare "other" first and call the selector if this is not "other". 5017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if(pattern.partSubstringMatches(part, "other")) { 5027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if(msgStart==0) { 5037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert msgStart=partIndex; 5047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if(keyword!=null && keyword.equals("other")) { 5057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // This is the first "other" sub-message, 5067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // and the selected keyword is also "other". 5077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Do not match "other" again. 5087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert haveKeywordMatch=true; 5097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 5127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if(keyword==null) { 5137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert keyword=selector.select(context, number-offset); 5147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if(msgStart!=0 && keyword.equals("other")) { 5157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // We have already seen an "other" sub-message. 5167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Do not match "other" again. 5177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert haveKeywordMatch=true; 5187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Skip keyword matching but do getLimitPartIndex(). 5197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if(!haveKeywordMatch && pattern.partSubstringMatches(part, keyword)) { 5227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // keyword matches 5237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert msgStart=partIndex; 5247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Do not match this keyword again. 5257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert haveKeywordMatch=true; 5267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert partIndex=pattern.getLimitPartIndex(partIndex); 5307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } while(++partIndex<count); 5317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return msgStart; 5327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 5347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 5357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Interface for selecting PluralFormat keywords for numbers. 5367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * The PluralRules class was intended to implement this interface, 5377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * but there is no public API that uses a PluralSelector, 5387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * only MessageFormat and PluralFormat have PluralSelector implementations. 5397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Therefore, PluralRules is not marked to implement this non-public interface, 5407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * to avoid confusing users. 5417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @internal 5427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 5437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*package*/ interface PluralSelector { 5447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 5457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Given a number, returns the appropriate PluralFormat keyword. 5467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 5477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param context worker object for the selector. 5487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param number The number to be plural-formatted. 5497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return The selected PluralFormat keyword. 5507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 5517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public String select(Object context, double number); 5527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 5547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // See PluralSelector: 5557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // We could avoid this adapter class if we made PluralSelector public 5567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // (or at least publicly visible) and had PluralRules implement PluralSelector. 5577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private final class PluralSelectorAdapter implements PluralSelector { 5587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public String select(Object context, double number) { 5597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert FixedDecimal dec = (FixedDecimal) context; 5607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert assert dec.source == number; 5617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return pluralRules.select(dec); 5627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert transient private PluralSelectorAdapter pluralRulesWrapper = new PluralSelectorAdapter(); 5657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 5667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 5677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Formats a plural message for a given number. 5687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 5697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param number a number for which the plural message should be formatted. 5707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * If no pattern has been applied to this 5717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>PluralFormat</code> object yet, the formatted number will 5727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * be returned. 5737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return the string containing the formatted plural message. 5747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 4.0 5757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 5767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public final String format(double number) { 5777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return format(number, number); 5787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 5797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 5807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 5817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Formats a plural message for a given number and appends the formatted 5827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * message to the given <code>StringBuffer</code>. 5837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param number a number object (instance of <code>Number</code> for which 5847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the plural message should be formatted. If no pattern has been 5857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * applied to this <code>PluralFormat</code> object yet, the 5867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * formatted number will be returned. 5877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Note: If this object is not an instance of <code>Number</code>, 5887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the <code>toAppendTo</code> will not be modified. 5897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param toAppendTo the formatted message will be appended to this 5907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <code>StringBuffer</code>. 5917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param pos will be ignored by this method. 5927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return the string buffer passed in as toAppendTo, with formatted text 5937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * appended. 5947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @throws IllegalArgumentException if number is not an instance of Number 5957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.8 5967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 5977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public StringBuffer format(Object number, StringBuffer toAppendTo, 5987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert FieldPosition pos) { 5997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!(number instanceof Number)) { 6007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException("'" + number + "' is not a Number"); 6017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 6027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Number numberObject = (Number) number; 6037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert toAppendTo.append(format(numberObject, numberObject.doubleValue())); 6047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return toAppendTo; 6057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 6067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 6077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private String format(Number numberObject, double number) { 6087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // If no pattern was applied, return the formatted number. 6097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (msgPattern == null || msgPattern.countParts() == 0) { 6107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return numberFormat.format(numberObject); 6117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 6127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 6137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Get the appropriate sub-message. 6147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Select it based on the formatted number-offset. 6157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert double numberMinusOffset = number - offset; 6167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String numberString; 6177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (offset == 0) { 6187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert numberString = numberFormat.format(numberObject); // could be BigDecimal etc. 6197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 6207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert numberString = numberFormat.format(numberMinusOffset); 6217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 6227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert FixedDecimal dec; 6237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if(numberFormat instanceof DecimalFormat) { 6247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert dec = ((DecimalFormat) numberFormat).getFixedDecimal(numberMinusOffset); 6257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 6267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert dec = new FixedDecimal(numberMinusOffset); 6277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 6287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int partIndex = findSubMessage(msgPattern, 0, pluralRulesWrapper, dec, number); 6297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Replace syntactic # signs in the top level of this sub-message 6307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // (not in nested arguments) with the formatted number-offset. 6317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert StringBuilder result = null; 6327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int prevIndex = msgPattern.getPart(partIndex).getLimit(); 6337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for (;;) { 6347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert MessagePattern.Part part = msgPattern.getPart(++partIndex); 6357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert MessagePattern.Part.Type type = part.getType(); 6367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int index = part.getIndex(); 6377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (type == MessagePattern.Part.Type.MSG_LIMIT) { 6387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (result == null) { 6397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return pattern.substring(prevIndex, index); 6407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 6417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return result.append(pattern, prevIndex, index).toString(); 6427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 6437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (type == MessagePattern.Part.Type.REPLACE_NUMBER || 6447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // JDK compatibility mode: Remove SKIP_SYNTAX. 6457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert (type == MessagePattern.Part.Type.SKIP_SYNTAX && msgPattern.jdkAposMode())) { 6467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (result == null) { 6477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result = new StringBuilder(); 6487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 6497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result.append(pattern, prevIndex, index); 6507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (type == MessagePattern.Part.Type.REPLACE_NUMBER) { 6517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result.append(numberString); 6527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 6537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert prevIndex = part.getLimit(); 6547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else if (type == MessagePattern.Part.Type.ARG_START) { 6557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (result == null) { 6567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result = new StringBuilder(); 6577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 6587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result.append(pattern, prevIndex, index); 6597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert prevIndex = index; 6607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert partIndex = msgPattern.getLimitPartIndex(partIndex); 6617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert index = msgPattern.getPart(partIndex).getLimit(); 6627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert MessagePattern.appendReducedApostrophes(pattern, prevIndex, index, result); 6637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert prevIndex = index; 6647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 6657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 6667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 6677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 6687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 6697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * This method is not yet supported by <code>PluralFormat</code>. 6707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param text the string to be parsed. 6717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param parsePosition defines the position where parsing is to begin, 6727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * and upon return, the position where parsing left off. If the position 6737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * has not changed upon return, then parsing failed. 6747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return nothing because this method is not yet implemented. 6757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @throws UnsupportedOperationException will always be thrown by this method. 6767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.8 6777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 6787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public Number parse(String text, ParsePosition parsePosition) { 6797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // You get number ranges from this. You can't get an exact number. 6807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new UnsupportedOperationException(); 6817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 6827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 6837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 6847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * This method is not yet supported by <code>PluralFormat</code>. 6857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param source the string to be parsed. 6867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param pos defines the position where parsing is to begin, 6877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * and upon return, the position where parsing left off. If the position 6887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * has not changed upon return, then parsing failed. 6897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return nothing because this method is not yet implemented. 6907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @throws UnsupportedOperationException will always be thrown by this method. 6917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.8 6927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 6937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public Object parseObject(String source, ParsePosition pos) { 6947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new UnsupportedOperationException(); 6957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 6967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 6977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 6987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * This method returns the PluralRules type found from parsing. 6997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param source the string to be parsed. 7007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param pos defines the position where parsing is to begin, 7017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * and upon return, the position where parsing left off. If the position 7027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * is a negative index, then parsing failed. 7037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return Returns the PluralRules type. For example, it could be "zero", "one", "two", "few", "many" or "other") 7047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 7057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*package*/ String parseType(String source, RbnfLenientScanner scanner, FieldPosition pos) { 7067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // If no pattern was applied, return null. 7077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (msgPattern == null || msgPattern.countParts() == 0) { 7087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos.setBeginIndex(-1); 7097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos.setEndIndex(-1); 7107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return null; 7117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int partIndex = 0; 7137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int currMatchIndex; 7147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int count=msgPattern.countParts(); 7157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int startingAt = pos.getBeginIndex(); 7167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (startingAt < 0) { 7177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert startingAt = 0; 7187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 7207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // The keyword is null until we need to match against a non-explicit, not-"other" value. 7217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Then we get the keyword from the selector. 7227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // (In other words, we never call the selector if we match against an explicit value, 7237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // or if the only non-explicit keyword is "other".) 7247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String keyword = null; 7257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String matchedWord = null; 7267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int matchedIndex = -1; 7277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Iterate over (ARG_SELECTOR ARG_START message ARG_LIMIT) tuples 7287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // until the end of the plural-only pattern. 7297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert while (partIndex < count) { 7307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert MessagePattern.Part partSelector=msgPattern.getPart(partIndex++); 7317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (partSelector.getType() != MessagePattern.Part.Type.ARG_SELECTOR) { 7327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Bad format 7337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert continue; 7347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 7367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert MessagePattern.Part partStart=msgPattern.getPart(partIndex++); 7377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (partStart.getType() != MessagePattern.Part.Type.MSG_START) { 7387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Bad format 7397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert continue; 7407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 7427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert MessagePattern.Part partLimit=msgPattern.getPart(partIndex++); 7437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (partLimit.getType() != MessagePattern.Part.Type.MSG_LIMIT) { 7447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Bad format 7457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert continue; 7467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 7487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String currArg = pattern.substring(partStart.getLimit(), partLimit.getIndex()); 7497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (scanner != null) { 7507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // If lenient parsing is turned ON, we've got some time consuming parsing ahead of us. 7517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int[] scannerMatchResult = scanner.findText(source, currArg, startingAt); 7527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert currMatchIndex = scannerMatchResult[0]; 7537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert else { 755f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert currMatchIndex = source.indexOf(currArg, startingAt); 7567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (currMatchIndex >= 0 && currMatchIndex >= matchedIndex && (matchedWord == null || currArg.length() > matchedWord.length())) { 7587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert matchedIndex = currMatchIndex; 7597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert matchedWord = currArg; 7607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert keyword = pattern.substring(partStart.getLimit(), partLimit.getIndex()); 7617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (keyword != null) { 7647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos.setBeginIndex(matchedIndex); 7657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos.setEndIndex(matchedIndex + matchedWord.length()); 7667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return keyword; 7677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 7697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Not found! 7707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos.setBeginIndex(-1); 7717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos.setEndIndex(-1); 7727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return null; 7737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 7757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 7767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Sets the locale used by this <code>PluraFormat</code> object. 7777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Note: Calling this method resets this <code>PluraFormat</code> object, 7787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * i.e., a pattern that was applied previously will be removed, 7797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * and the NumberFormat is set to the default number format for 7807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * the locale. The resulting format behaves the same as one 7817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * constructed from {@link #PluralFormat(ULocale, PluralRules.PluralType)} 7827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * with PluralType.CARDINAL. 7837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param ulocale the <code>ULocale</code> used to configure the 7847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * formatter. If <code>ulocale</code> is <code>null</code>, the 7857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * default <code>FORMAT</code> locale will be used. 7867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see Category#FORMAT 7877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @deprecated ICU 50 This method clears the pattern and might create 7887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * a different kind of PluralRules instance; 7897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * use one of the constructors to create a new instance instead. 7907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 7917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Deprecated 7927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setLocale(ULocale ulocale) { 7937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (ulocale == null) { 7947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ulocale = ULocale.getDefault(Category.FORMAT); 7957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert init(null, PluralType.CARDINAL, ulocale, null); 7977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 7987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 7997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 8007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Sets the number format used by this formatter. You only need to 8017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * call this if you want a different number format than the default 8027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * formatter for the locale. 8037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param format the number format to use. 8047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.8 8057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 8067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setNumberFormat(NumberFormat format) { 8077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert numberFormat = format; 8087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 8097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 8117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@inheritDoc} 8127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.8 8137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 8147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Override 8157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public boolean equals(Object rhs) { 8167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if(this == rhs) { 8177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return true; 8187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 8197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if(rhs == null || getClass() != rhs.getClass()) { 8207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return false; 8217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 8227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert PluralFormat pf = (PluralFormat)rhs; 8237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return 8247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Utility.objectEquals(ulocale, pf.ulocale) && 8257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Utility.objectEquals(pluralRules, pf.pluralRules) && 8267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Utility.objectEquals(msgPattern, pf.msgPattern) && 8277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Utility.objectEquals(numberFormat, pf.numberFormat); 8287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 8297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 8317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Returns true if this equals the provided PluralFormat. 8327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param rhs the PluralFormat to compare against 8337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return true if this equals rhs 8347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.8 8357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 8367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public boolean equals(PluralFormat rhs) { 8377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return equals((Object)rhs); 8387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 8397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 8417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@inheritDoc} 8427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.8 8437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 8447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Override 8457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public int hashCode() { 8467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return pluralRules.hashCode() ^ parsedValues.hashCode(); 8477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 8487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 8507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * {@inheritDoc} 8517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.8 8527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 8537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Override 8547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public String toString() { 8557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert StringBuilder buf = new StringBuilder(); 8567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert buf.append("locale=" + ulocale); 8577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert buf.append(", rules='" + pluralRules + "'"); 8587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert buf.append(", pattern='" + pattern + "'"); 8597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert buf.append(", format='" + numberFormat + "'"); 8607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return buf.toString(); 8617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 8627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 8637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { 8647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert in.defaultReadObject(); 8657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pluralRulesWrapper = new PluralSelectorAdapter(); 8667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Ignore the parsedValues from an earlier class version (before ICU 4.8) 8677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // and rebuild the msgPattern. 8687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert parsedValues = null; 8697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (pattern != null) { 8707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert applyPattern(pattern); 8717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 8727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 8737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert} 874