12ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller/* GENERATED SOURCE. DO NOT MODIFY. */ 2f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert// © 2016 and later: Unicode, Inc. and others. 3f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert// License & terms of use: http://www.unicode.org/copyright.html#License 42ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller/* 52ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller ******************************************************************************* 6f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert * Copyright (C) 1996-2016, International Business Machines Corporation and 7f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert * others. All Rights Reserved. 82ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller ******************************************************************************* 92ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerpackage android.icu.text; 122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.math.BigInteger; 142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.text.FieldPosition; 152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.text.ParsePosition; 162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.util.Arrays; 172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.util.HashMap; 182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.util.Locale; 192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.util.Map; 202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.util.MissingResourceException; 212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.util.Set; 222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 23f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubertimport android.icu.impl.ICUData; 242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport android.icu.impl.ICUDebug; 252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport android.icu.impl.ICUResourceBundle; 262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport android.icu.impl.PatternProps; 272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport android.icu.lang.UCharacter; 282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport android.icu.math.BigDecimal; 292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport android.icu.util.ULocale; 302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport android.icu.util.ULocale.Category; 312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport android.icu.util.UResourceBundle; 322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport android.icu.util.UResourceBundleIterator; 332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller/** 362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <p>A class that formats numbers according to a set of rules. This number formatter is 372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * typically used for spelling out numeric values in words (e.g., 25,3476 as 382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * "twenty-five thousand three hundred seventy-six" or "vingt-cinq mille trois 392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * cents soixante-seize" or 402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * "funfundzwanzigtausenddreihundertsechsundsiebzig"), but can also be used for 412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * other complicated formatting tasks, such as formatting a number of seconds as hours, 422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * minutes and seconds (e.g., 3,730 as "1:02:10").</p> 432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <p>The resources contain three predefined formatters for each locale: spellout, which 452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * spells out a value in words (123 is "one hundred twenty-three"); ordinal, which 462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * appends an ordinal suffix to the end of a numeral (123 is "123rd"); and 472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * duration, which shows a duration in seconds as hours, minutes, and seconds (123 is 482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * "2:03"). The client can also define more specialized <tt>RuleBasedNumberFormat</tt>s 492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * by supplying programmer-defined rule sets.</p> 502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <p>The behavior of a <tt>RuleBasedNumberFormat</tt> is specified by a textual description 522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * that is either passed to the constructor as a <tt>String</tt> or loaded from a resource 532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * bundle. In its simplest form, the description consists of a semicolon-delimited list of <em>rules.</em> 542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Each rule has a string of output text and a value or range of values it is applicable to. 552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * In a typical spellout rule set, the first twenty rules are the words for the numbers from 562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 0 to 19:</p> 572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <pre>zero; one; two; three; four; five; six; seven; eight; nine; 592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * ten; eleven; twelve; thirteen; fourteen; fifteen; sixteen; seventeen; eighteen; nineteen;</pre> 602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <p>For larger numbers, we can use the preceding set of rules to format the ones place, and 622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * we only have to supply the words for the multiples of 10:</p> 632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <pre>20: twenty[->>]; 652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 30: thirty{->>]; 662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 40: forty[->>]; 672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 50: fifty[->>]; 682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 60: sixty[->>]; 692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 70: seventy[->>]; 702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 80: eighty[->>]; 712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 90: ninety[->>];</pre> 722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <p>In these rules, the <em>base value</em> is spelled out explicitly and set off from the 742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * rule's output text with a colon. The rules are in a sorted list, and a rule is applicable 752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * to all numbers from its own base value to one less than the next rule's base value. The 762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * ">>" token is called a <em>substitution</em> and tells the formatter to 772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * isolate the number's ones digit, format it using this same set of rules, and place the 782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * result at the position of the ">>" token. Text in brackets is omitted if 792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * the number being formatted is an even multiple of 10 (the hyphen is a literal hyphen; 24 802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * is "twenty-four," not "twenty four").</p> 812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <p>For even larger numbers, we can actually look up several parts of the number in the 832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * list:</p> 842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <pre>100: << hundred[ >>];</pre> 862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <p>The "<<" represents a new kind of substitution. The << isolates 882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * the hundreds digit (and any digits to its left), formats it using this same rule set, and 892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * places the result where the "<<" was. Notice also that the meaning of 902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * >> has changed: it now refers to both the tens and the ones digits. The meaning of 912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * both substitutions depends on the rule's base value. The base value determines the rule's <em>divisor,</em> 922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * which is the highest power of 10 that is less than or equal to the base value (the user 932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * can change this). To fill in the substitutions, the formatter divides the number being 942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * formatted by the divisor. The integral quotient is used to fill in the << 952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * substitution, and the remainder is used to fill in the >> substitution. The meaning 962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * of the brackets changes similarly: text in brackets is omitted if the value being 972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * formatted is an even multiple of the rule's divisor. The rules are applied recursively, so 982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * if a substitution is filled in with text that includes another substitution, that 992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * substitution is also filled in.</p> 1002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 1012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <p>This rule covers values up to 999, at which point we add another rule:</p> 1022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 1032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <pre>1000: << thousand[ >>];</pre> 1042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 1052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <p>Again, the meanings of the brackets and substitution tokens shift because the rule's 1062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * base value is a higher power of 10, changing the rule's divisor. This rule can actually be 1072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * used all the way up to 999,999. This allows us to finish out the rules as follows:</p> 1082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 1092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <pre>1,000,000: << million[ >>]; 1102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 1,000,000,000: << billion[ >>]; 1112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 1,000,000,000,000: << trillion[ >>]; 1122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 1,000,000,000,000,000: OUT OF RANGE!;</pre> 1132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 1142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <p>Commas, periods, and spaces can be used in the base values to improve legibility and 1152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * are ignored by the rule parser. The last rule in the list is customarily treated as an 1162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * "overflow rule," applying to everything from its base value on up, and often (as 1172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * in this example) being used to print out an error message or default representation. 1182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Notice also that the size of the major groupings in large numbers is controlled by the 1192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * spacing of the rules: because in English we group numbers by thousand, the higher rules 1202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * are separated from each other by a factor of 1,000.</p> 1212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 1222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <p>To see how these rules actually work in practice, consider the following example: 1232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Formatting 25,430 with this rule set would work like this:</p> 1242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 1252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <table border="0" width="630"> 1262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <tr> 127bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 21;"></td> 128bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 257; vertical-align: top;"><strong><< thousand >></strong></td> 129bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 340; vertical-align: top;">[the rule whose base value is 1,000 is applicable to 25,340]</td> 1302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * </tr> 1312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <tr> 132bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 21;"></td> 133bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 257; vertical-align: top;"><strong>twenty->></strong> thousand >></td> 134bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 340; vertical-align: top;">[25,340 over 1,000 is 25. The rule for 20 applies.]</td> 1352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * </tr> 1362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <tr> 137bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 21;"></td> 138bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 257; vertical-align: top;">twenty-<strong>five</strong> thousand >></td> 139bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 340; vertical-align: top;">[25 mod 10 is 5. The rule for 5 is "five."</td> 1402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * </tr> 1412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <tr> 142bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 21;"></td> 143bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 257; vertical-align: top;">twenty-five thousand <strong><< hundred >></strong></td> 144bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 340; vertical-align: top;">[25,340 mod 1,000 is 340. The rule for 100 applies.]</td> 1452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * </tr> 1462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <tr> 147bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 21;"></td> 148bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 257; vertical-align: top;">twenty-five thousand <strong>three</strong> hundred >></td> 149bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 340; vertical-align: top;">[340 over 100 is 3. The rule for 3 is "three."]</td> 1502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * </tr> 1512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <tr> 152bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 21;"></td> 153bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 257; vertical-align: top;">twenty-five thousand three hundred <strong>forty</strong></td> 154bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 340; vertical-align: top;">[340 mod 100 is 40. The rule for 40 applies. Since 40 divides 1552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * evenly by 10, the hyphen and substitution in the brackets are omitted.]</td> 1562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * </tr> 1572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * </table> 1582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 1592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <p>The above syntax suffices only to format positive integers. To format negative numbers, 1602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * we add a special rule:</p> 1612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 1622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <pre>-x: minus >>;</pre> 1632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 1642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <p>This is called a <em>negative-number rule,</em> and is identified by "-x" 1652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * where the base value would be. This rule is used to format all negative numbers. the 1662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * >> token here means "find the number's absolute value, format it with these 1672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * rules, and put the result here."</p> 1682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 1692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <p>We also add a special rule called a <em>fraction rule </em>for numbers with fractional 1702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * parts:</p> 1712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 1722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <pre>x.x: << point >>;</pre> 1732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 1742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <p>This rule is used for all positive non-integers (negative non-integers pass through the 1752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * negative-number rule first and then through this rule). Here, the << token refers to 1762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * the number's integral part, and the >> to the number's fractional part. The 1772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * fractional part is formatted as a series of single-digit numbers (e.g., 123.456 would be 1782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * formatted as "one hundred twenty-three point four five six").</p> 1792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 1802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <p>To see how this rule syntax is applied to various languages, examine the resource data.</p> 1812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 1822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <p>There is actually much more flexibility built into the rule language than the 1832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * description above shows. A formatter may own multiple rule sets, which can be selected by 1842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * the caller, and which can use each other to fill in their substitutions. Substitutions can 1852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * also be filled in with digits, using a DecimalFormat object. There is syntax that can be 1862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * used to alter a rule's divisor in various ways. And there is provision for much more 1872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * flexible fraction handling. A complete description of the rule syntax follows:</p> 1882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 1892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <hr> 1902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 1912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <p>The description of a <tt>RuleBasedNumberFormat</tt>'s behavior consists of one or more <em>rule 1922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * sets.</em> Each rule set consists of a name, a colon, and a list of <em>rules.</em> A rule 1932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * set name must begin with a % sign. Rule sets with names that begin with a single % sign 1942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * are <em>public:</em> the caller can specify that they be used to format and parse numbers. 1952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Rule sets with names that begin with %% are <em>private:</em> they exist only for the use 1962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * of other rule sets. If a formatter only has one rule set, the name may be omitted.</p> 1972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 1982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <p>The user can also specify a special "rule set" named <tt>%%lenient-parse</tt>. 1992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * The body of <tt>%%lenient-parse</tt> isn't a set of number-formatting rules, but a <tt>RuleBasedCollator</tt> 2002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * description which is used to define equivalences for lenient parsing. For more information 2012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * on the syntax, see <tt>RuleBasedCollator</tt>. For more information on lenient parsing, 2022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * see <tt>setLenientParse()</tt>. <em>Note:</em> symbols that have syntactic meaning 2032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * in collation rules, such as '&', have no particular meaning when appearing outside 2042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * of the <tt>lenient-parse</tt> rule set.</p> 2052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 2062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <p>The body of a rule set consists of an ordered, semicolon-delimited list of <em>rules.</em> 2072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Internally, every rule has a base value, a divisor, rule text, and zero, one, or two <em>substitutions.</em> 2082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * These parameters are controlled by the description syntax, which consists of a <em>rule 2092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * descriptor,</em> a colon, and a <em>rule body.</em></p> 2102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 2112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <p>A rule descriptor can take one of the following forms (text in <em>italics</em> is the 2122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * name of a token):</p> 2132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 2142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <table border="0" width="100%"> 2152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <tr> 216bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 5%; vertical-align: top;"></td> 217bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 8%; vertical-align: top;"><em>bv</em>:</td> 2182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <td valign="top"><em>bv</em> specifies the rule's base value. <em>bv</em> is a decimal 2192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * number expressed using ASCII digits. <em>bv</em> may contain spaces, period, and commas, 2202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * which are ignored. The rule's divisor is the highest power of 10 less than or equal to 2212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * the base value.</td> 2222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * </tr> 2232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <tr> 224bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 5%; vertical-align: top;"></td> 225bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 8%; vertical-align: top;"><em>bv</em>/<em>rad</em>:</td> 2262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <td valign="top"><em>bv</em> specifies the rule's base value. The rule's divisor is the 2272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * highest power of <em>rad</em> less than or equal to the base value.</td> 2282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * </tr> 2292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <tr> 230bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 5%; vertical-align: top;"></td> 231bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 8%; vertical-align: top;"><em>bv</em>>:</td> 2322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <td valign="top"><em>bv</em> specifies the rule's base value. To calculate the divisor, 2332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * let the radix be 10, and the exponent be the highest exponent of the radix that yields a 2342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * result less than or equal to the base value. Every > character after the base value 2352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * decreases the exponent by 1. If the exponent is positive or 0, the divisor is the radix 2362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * raised to the power of the exponent; otherwise, the divisor is 1.</td> 2372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * </tr> 2382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <tr> 239bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 5%; vertical-align: top;"></td> 240bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 8%; vertical-align: top;"><em>bv</em>/<em>rad</em>>:</td> 2412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <td valign="top"><em>bv</em> specifies the rule's base value. To calculate the divisor, 2422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * let the radix be <em>rad</em>, and the exponent be the highest exponent of the radix that 2432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * yields a result less than or equal to the base value. Every > character after the radix 2442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * decreases the exponent by 1. If the exponent is positive or 0, the divisor is the radix 2452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * raised to the power of the exponent; otherwise, the divisor is 1.</td> 2462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * </tr> 2472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <tr> 248bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 5%; vertical-align: top;"></td> 249bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 8%; vertical-align: top;">-x:</td> 2502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <td valign="top">The rule is a negative-number rule.</td> 2512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * </tr> 2522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <tr> 253bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 5%; vertical-align: top;"></td> 254bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 8%; vertical-align: top;">x.x:</td> 2552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <td valign="top">The rule is an <em>improper fraction rule</em>. If the full stop in 2562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * the middle of the rule name is replaced with the decimal point 2572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * that is used in the language or DecimalFormatSymbols, then that rule will 2582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * have precedence when formatting and parsing this rule. For example, some 2592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * languages use the comma, and can thus be written as x,x instead. For example, 2602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * you can use "x.x: << point >>;x,x: << comma >>;" to 2612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * handle the decimal point that matches the language's natural spelling of 2622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * the punctuation of either the full stop or comma.</td> 2632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * </tr> 2642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <tr> 265bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 5%; vertical-align: top;"></td> 266bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 8%; vertical-align: top;">0.x:</td> 2672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <td valign="top">The rule is a <em>proper fraction rule</em>. If the full stop in 2682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * the middle of the rule name is replaced with the decimal point 2692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * that is used in the language or DecimalFormatSymbols, then that rule will 2702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * have precedence when formatting and parsing this rule. For example, some 2712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * languages use the comma, and can thus be written as 0,x instead. For example, 2722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * you can use "0.x: point >>;0,x: comma >>;" to 2732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * handle the decimal point that matches the language's natural spelling of 2742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * the punctuation of either the full stop or comma</td> 2752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * </tr> 2762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <tr> 277bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 5%; vertical-align: top;"></td> 278bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 8%; vertical-align: top;">x.0:</td> 2792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <td valign="top">The rule is a <em>master rule</em>. If the full stop in 2802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * the middle of the rule name is replaced with the decimal point 2812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * that is used in the language or DecimalFormatSymbols, then that rule will 2822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * have precedence when formatting and parsing this rule. For example, some 2832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * languages use the comma, and can thus be written as x,0 instead. For example, 2842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * you can use "x.0: << point;x,0: << comma;" to 2852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * handle the decimal point that matches the language's natural spelling of 2862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * the punctuation of either the full stop or comma</td> 2872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * </tr> 2882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <tr> 289bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 5%; vertical-align: top;"></td> 290bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 8%; vertical-align: top;">Inf:</td> 291bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="vertical-align: top;">The rule for infinity.</td> 2922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * </tr> 2932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <tr> 294bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 5%; vertical-align: top;"></td> 295bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 8%; vertical-align: top;">NaN:</td> 296bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="vertical-align: top;">The rule for an IEEE 754 NaN (not a number).</td> 2972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * </tr> 2982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <tr> 299bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 5%; vertical-align: top;"></td> 300bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 8%; vertical-align: top;"><em>nothing</em></td> 301bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="vertical-align: top;">If the rule's rule descriptor is left out, the base value is one plus the 3022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * preceding rule's base value (or zero if this is the first rule in the list) in a normal 3032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * rule set. In a fraction rule set, the base value is the same as the preceding rule's 3042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * base value.</td> 3052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * </tr> 3062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * </table> 3072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 3082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <p>A rule set may be either a regular rule set or a <em>fraction rule set,</em> depending 3092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * on whether it is used to format a number's integral part (or the whole number) or a 3102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * number's fractional part. Using a rule set to format a rule's fractional part makes it a 3112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * fraction rule set.</p> 3122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 3132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <p>Which rule is used to format a number is defined according to one of the following 3142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * algorithms: If the rule set is a regular rule set, do the following: 3152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 3162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <ul> 3172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <li>If the rule set includes a master rule (and the number was passed in as a <tt>double</tt>), 3182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * use the master rule. (If the number being formatted was passed in as a <tt>long</tt>, 3192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * the master rule is ignored.)</li> 3202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <li>If the number is negative, use the negative-number rule.</li> 3212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <li>If the number has a fractional part and is greater than 1, use the improper fraction 3222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * rule.</li> 3232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <li>If the number has a fractional part and is between 0 and 1, use the proper fraction 3242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * rule.</li> 3252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <li>Binary-search the rule list for the rule with the highest base value less than or equal 3262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * to the number. If that rule has two substitutions, its base value is not an even multiple 3272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * of its divisor, and the number <em>is</em> an even multiple of the rule's divisor, use the 3282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * rule that precedes it in the rule list. Otherwise, use the rule itself.</li> 3292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * </ul> 3302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 3312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <p>If the rule set is a fraction rule set, do the following: 3322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 3332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <ul> 3342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <li>Ignore negative-number and fraction rules.</li> 3352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <li>For each rule in the list, multiply the number being formatted (which will always be 3362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * between 0 and 1) by the rule's base value. Keep track of the distance between the result 3372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * the nearest integer.</li> 3382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <li>Use the rule that produced the result closest to zero in the above calculation. In the 3392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * event of a tie or a direct hit, use the first matching rule encountered. (The idea here is 3402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * to try each rule's base value as a possible denominator of a fraction. Whichever 3412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * denominator produces the fraction closest in value to the number being formatted wins.) If 3422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * the rule following the matching rule has the same base value, use it if the numerator of 3432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * the fraction is anything other than 1; if the numerator is 1, use the original matching 3442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * rule. (This is to allow singular and plural forms of the rule text without a lot of extra 3452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * hassle.)</li> 3462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * </ul> 3472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 3482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <p>A rule's body consists of a string of characters terminated by a semicolon. The rule 3492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * may include zero, one, or two <em>substitution tokens,</em> and a range of text in 3502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * brackets. The brackets denote optional text (and may also include one or both 3512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * substitutions). The exact meanings of the substitution tokens, and under what conditions 3522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * optional text is omitted, depend on the syntax of the substitution token and the context. 3532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * The rest of the text in a rule body is literal text that is output when the rule matches 3542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * the number being formatted.</p> 3552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 3562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <p>A substitution token begins and ends with a <em>token character.</em> The token 3572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * character and the context together specify a mathematical operation to be performed on the 3582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * number being formatted. An optional <em>substitution descriptor </em>specifies how the 3592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * value resulting from that operation is used to fill in the substitution. The position of 3602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * the substitution token in the rule body specifies the location of the resultant text in 3612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * the original rule text.</p> 3622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 3632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <p>The meanings of the substitution token characters are as follows:</p> 3642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 3652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <table border="0" width="100%"> 3662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <tr> 367bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 37;"></td> 368bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 23;">>></td> 369bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 165; vertical-align: top;">in normal rule</td> 3702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <td>Divide the number by the rule's divisor and format the remainder</td> 3712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * </tr> 3722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <tr> 373bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 37;"></td> 374bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 23;"></td> 375bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 165; vertical-align: top;">in negative-number rule</td> 3762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <td>Find the absolute value of the number and format the result</td> 3772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * </tr> 3782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <tr> 379bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 37;"></td> 380bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 23;"></td> 381bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 165; vertical-align: top;">in fraction or master rule</td> 3822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <td>Isolate the number's fractional part and format it.</td> 3832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * </tr> 3842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <tr> 385bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 37;"></td> 386bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 23;"></td> 387bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 165; vertical-align: top;">in rule in fraction rule set</td> 3882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <td>Not allowed.</td> 3892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * </tr> 3902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <tr> 391bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 37;"></td> 392bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 23;">>>></td> 393bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 165; vertical-align: top;">in normal rule</td> 3942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <td>Divide the number by the rule's divisor and format the remainder, 3952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * but bypass the normal rule-selection process and just use the 3962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * rule that precedes this one in this rule list.</td> 3972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * </tr> 3982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <tr> 399bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 37;"></td> 400bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 23;"></td> 401bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 165; vertical-align: top;">in all other rules</td> 4022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <td>Not allowed.</td> 4032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * </tr> 4042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <tr> 405bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 37;"></td> 406bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 23;"><<</td> 407bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 165; vertical-align: top;">in normal rule</td> 4082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <td>Divide the number by the rule's divisor and format the quotient</td> 4092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * </tr> 4102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <tr> 411bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 37;"></td> 412bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 23;"></td> 413bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 165; vertical-align: top;">in negative-number rule</td> 4142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <td>Not allowed.</td> 4152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * </tr> 4162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <tr> 417bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 37;"></td> 418bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 23;"></td> 419bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 165; vertical-align: top;">in fraction or master rule</td> 4202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <td>Isolate the number's integral part and format it.</td> 4212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * </tr> 4222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <tr> 423bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 37;"></td> 424bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 23;"></td> 425bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 165; vertical-align: top;">in rule in fraction rule set</td> 4262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <td>Multiply the number by the rule's base value and format the result.</td> 4272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * </tr> 4282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <tr> 429bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 37;"></td> 430bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 23;">==</td> 431bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 165; vertical-align: top;">in all rule sets</td> 4322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <td>Format the number unchanged</td> 4332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * </tr> 4342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <tr> 435bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 37;"></td> 436bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 23;">[]</td> 437bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 165; vertical-align: top;">in normal rule</td> 4382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <td>Omit the optional text if the number is an even multiple of the rule's divisor</td> 4392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * </tr> 4402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <tr> 441bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 37;"></td> 442bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 23;"></td> 443bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 165; vertical-align: top;">in negative-number rule</td> 4442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <td>Not allowed.</td> 4452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * </tr> 4462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <tr> 447bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 37;"></td> 448bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 23;"></td> 449bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 165; vertical-align: top;">in improper-fraction rule</td> 4502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <td>Omit the optional text if the number is between 0 and 1 (same as specifying both an 4512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * x.x rule and a 0.x rule)</td> 4522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * </tr> 4532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <tr> 454bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 37;"></td> 455bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 23;"></td> 456bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 165; vertical-align: top;">in master rule</td> 4572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <td>Omit the optional text if the number is an integer (same as specifying both an x.x 4582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * rule and an x.0 rule)</td> 4592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * </tr> 4602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <tr> 461bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 37;"></td> 462bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 23;"></td> 463bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 165; vertical-align: top;">in proper-fraction rule</td> 4642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <td>Not allowed.</td> 4652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * </tr> 4662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <tr> 467bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 37;"></td> 468bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 23;"></td> 469bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 165; vertical-align: top;">in rule in fraction rule set</td> 4702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <td>Omit the optional text if multiplying the number by the rule's base value yields 1.</td> 4712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * </tr> 4722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <tr> 473bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 37;">$(cardinal,<i>plural syntax</i>)$</td> 474bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 23;"></td> 475bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 165; vertical-align: top;">in all rule sets</td> 4762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <td>This provides the ability to choose a word based on the number divided by the radix to the power of the 4772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * exponent of the base value for the specified locale, which is normally equivalent to the << value. 4782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * This uses the cardinal plural rules from PluralFormat. All strings used in the plural format are treated 4792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * as the same base value for parsing.</td> 4802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * </tr> 4812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <tr> 482bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 37;">$(ordinal,<i>plural syntax</i>)$</td> 483bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 23;"></td> 484bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 165; vertical-align: top;">in all rule sets</td> 4852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <td>This provides the ability to choose a word based on the number divided by the radix to the power of the 4862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * exponent of the base value for the specified locale, which is normally equivalent to the << value. 4872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * This uses the ordinal plural rules from PluralFormat. All strings used in the plural format are treated 4882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * as the same base value for parsing.</td> 4892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * </tr> 4902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * </table> 4912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 4922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <p>The substitution descriptor (i.e., the text between the token characters) may take one 4932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * of three forms:</p> 4942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 4952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <table border="0" width="100%"> 4962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <tr> 497bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 42;"></td> 498bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 166; vertical-align: top;">a rule set name</td> 4992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <td>Perform the mathematical operation on the number, and format the result using the 5002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * named rule set.</td> 5012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * </tr> 5022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <tr> 503bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 42;"></td> 504bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 166; vertical-align: top;">a DecimalFormat pattern</td> 5052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <td>Perform the mathematical operation on the number, and format the result using a 5062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * DecimalFormat with the specified pattern. The pattern must begin with 0 or #.</td> 5072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * </tr> 5082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <tr> 509bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 42;"></td> 510bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <td style="width: 166; vertical-align: top;">nothing</td> 5112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <td>Perform the mathematical operation on the number, and format the result using the rule 5122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * set containing the current rule, except:<ul> 5132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <li>You can't have an empty substitution descriptor with a == substitution.</li> 5142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <li>If you omit the substitution descriptor in a >> substitution in a fraction rule, 5152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * format the result one digit at a time using the rule set containing the current rule.</li> 5162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <li>If you omit the substitution descriptor in a << substitution in a rule in a 5172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * fraction rule set, format the result using the default rule set for this formatter.</li> 5182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * </ul> 5192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * </td> 5202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * </tr> 5212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * </table> 5222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 5232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <p>Whitespace is ignored between a rule set name and a rule set body, between a rule 5242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * descriptor and a rule body, or between rules. If a rule body begins with an apostrophe, 5252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * the apostrophe is ignored, but all text after it becomes significant (this is how you can 5262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * have a rule's rule text begin with whitespace). There is no escape function: the semicolon 5272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * is not allowed in rule set names or in rule text, and the colon is not allowed in rule set 5282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * names. The characters beginning a substitution token are always treated as the beginning 5292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * of a substitution token.</p> 5302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 5312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <p>See the resource data and the demo program for annotated examples of real rule sets 5322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * using these features.</p> 5332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 5342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @author Richard Gillam 5352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @see NumberFormat 5362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @see DecimalFormat 5372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @see PluralFormat 5382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @see PluralRules 539836e6b40a94ec3fb7545a76cb072960442b7eee9Neil Fuller * @hide Only a subset of ICU is exposed in Android 5402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 5412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerpublic class RuleBasedNumberFormat extends NumberFormat { 5422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 5432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller //----------------------------------------------------------------------- 5442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // constants 5452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller //----------------------------------------------------------------------- 5462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 5472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // Generated by serialver from JDK 1.4.1_01 5482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller static final long serialVersionUID = -7664252765575395068L; 5492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 5502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 5512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Selector code that tells the constructor to create a spellout formatter 5522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 5532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public static final int SPELLOUT = 1; 5542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 5552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 5562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Selector code that tells the constructor to create an ordinal formatter 5572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 5582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public static final int ORDINAL = 2; 5592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 5602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 5612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Selector code that tells the constructor to create a duration formatter 5622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 5632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public static final int DURATION = 3; 5642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 5652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 5662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Selector code that tells the constructor to create a numbering system formatter 5672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 5682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public static final int NUMBERING_SYSTEM = 4; 5692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 5702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller //----------------------------------------------------------------------- 5712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // data members 5722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller //----------------------------------------------------------------------- 5732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 5742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 5752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * The formatter's rule sets. 5762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 5772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller private transient NFRuleSet[] ruleSets = null; 5782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 5792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 5802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * The formatter's rule names mapped to rule sets. 5812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 5822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller private transient Map<String, NFRuleSet> ruleSetsMap = null; 5832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 5842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 5852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * A pointer to the formatter's default rule set. This is always included 5862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * in ruleSets. 5872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 5882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller private transient NFRuleSet defaultRuleSet = null; 5892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 5902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 5912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * The formatter's locale. This is used to create DecimalFormatSymbols and 5922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Collator objects. 5932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @serial 5942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 5952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller private ULocale locale = null; 5962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 5972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 5982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * The formatter's rounding mode. 5992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @serial 6002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 6012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller private int roundingMode = BigDecimal.ROUND_UNNECESSARY; 6022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 6032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 6042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Collator to be used in lenient parsing. This variable is lazy-evaluated: 6052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * the collator is actually created the first time the client does a parse 6062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * with lenient-parse mode turned on. 6072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 6082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller private transient RbnfLenientScannerProvider scannerProvider = null; 6092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 6102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // flag to mark whether we've previously looked for a scanner and failed 6112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller private transient boolean lookedForScanner; 6122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 6132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 6142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * The DecimalFormatSymbols object that any DecimalFormat objects this 6152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * formatter uses should use. This variable is lazy-evaluated: it isn't 6162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * filled in if the rule set never uses a DecimalFormat pattern. 6172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 6182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller private transient DecimalFormatSymbols decimalFormatSymbols = null; 6192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 6202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 6212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * The NumberFormat used when lenient parsing numbers. This needs to reflect 6222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * the locale. This is lazy-evaluated, like decimalFormatSymbols. It is 6232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * here so it can be shared by different NFSubstitutions. 6242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 6252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller private transient DecimalFormat decimalFormat = null; 6262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 6272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 6282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * The rule used when dealing with infinity. This is lazy-evaluated, and derived from decimalFormat. 6292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * It is here so it can be shared by different NFRuleSets. 6302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 6312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller private transient NFRule defaultInfinityRule = null; 6322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 6332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 6342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * The rule used when dealing with IEEE 754 NaN. This is lazy-evaluated, and derived from decimalFormat. 6352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * It is here so it can be shared by different NFRuleSets. 6362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 6372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller private transient NFRule defaultNaNRule = null; 6382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 6392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 6402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Flag specifying whether lenient parse mode is on or off. Off by default. 6412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @serial 6422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 6432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller private boolean lenientParse = false; 6442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 6452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 6462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * If the description specifies lenient-parse rules, they're stored here until 6472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * the collator is created. 6482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 6492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller private transient String lenientParseRules; 6502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 6512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 6522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * If the description specifies post-process rules, they're stored here until 6532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * post-processing is required. 6542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 6552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller private transient String postProcessRules; 6562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 6572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 6582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Post processor lazily constructed from the postProcessRules. 6592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 6602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller private transient RBNFPostProcessor postProcessor; 6612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 6622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 6632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Localizations for rule set names. 6642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @serial 6652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 6662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller private Map<String, String[]> ruleSetDisplayNames; 6672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 6682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 6692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * The public rule set names; 6702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @serial 6712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 6722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller private String[] publicRuleSetNames; 6732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 6742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 6752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Data for handling context-based capitalization 6762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 6772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller private boolean capitalizationInfoIsSet = false; 6782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller private boolean capitalizationForListOrMenu = false; 6792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller private boolean capitalizationForStandAlone = false; 6802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller private transient BreakIterator capitalizationBrkIter = null; 6812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 6822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 6832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller private static final boolean DEBUG = ICUDebug.enabled("rbnf"); 6842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 6852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller //----------------------------------------------------------------------- 6862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // constructors 6872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller //----------------------------------------------------------------------- 6882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 6892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 6902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Creates a RuleBasedNumberFormat that behaves according to the description 6912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * passed in. The formatter uses the default <code>FORMAT</code> locale. 6922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param description A description of the formatter's desired behavior. 6932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * See the class documentation for a complete explanation of the description 6942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * syntax. 6952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @see Category#FORMAT 6962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 6972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public RuleBasedNumberFormat(String description) { 6982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller locale = ULocale.getDefault(Category.FORMAT); 6992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller init(description, null); 7002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 7012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 7022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 7032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Creates a RuleBasedNumberFormat that behaves according to the description 7042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * passed in. The formatter uses the default <code>FORMAT</code> locale. 7052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <p> 7062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * The localizations data provides information about the public 7072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * rule sets and their localized display names for different 7082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * locales. The first element in the list is an array of the names 7092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * of the public rule sets. The first element in this array is 7102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * the initial default ruleset. The remaining elements in the 7112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * list are arrays of localizations of the names of the public 7122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * rule sets. Each of these is one longer than the initial array, 7132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * with the first String being the ULocale ID, and the remaining 7142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Strings being the localizations of the rule set names, in the 7152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * same order as the initial array. 7162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param description A description of the formatter's desired behavior. 7172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * See the class documentation for a complete explanation of the description 7182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * syntax. 7192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param localizations a list of localizations for the rule set 7202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * names in the description. 7212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @see Category#FORMAT 7222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 7232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public RuleBasedNumberFormat(String description, String[][] localizations) { 7242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller locale = ULocale.getDefault(Category.FORMAT); 7252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller init(description, localizations); 7262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 7272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 7282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 7292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Creates a RuleBasedNumberFormat that behaves according to the description 7302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * passed in. The formatter uses the specified locale to determine the 7312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * characters to use when formatting in numerals, and to define equivalences 7322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * for lenient parsing. 7332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param description A description of the formatter's desired behavior. 7342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * See the class documentation for a complete explanation of the description 7352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * syntax. 7362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param locale A locale, which governs which characters are used for 7372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * formatting values in numerals, and which characters are equivalent in 7382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * lenient parsing. 7392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 7402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public RuleBasedNumberFormat(String description, Locale locale) { 7412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller this(description, ULocale.forLocale(locale)); 7422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 7432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 7442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 7452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Creates a RuleBasedNumberFormat that behaves according to the description 7462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * passed in. The formatter uses the specified locale to determine the 7472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * characters to use when formatting in numerals, and to define equivalences 7482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * for lenient parsing. 7492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param description A description of the formatter's desired behavior. 7502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * See the class documentation for a complete explanation of the description 7512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * syntax. 7522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param locale A locale, which governs which characters are used for 7532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * formatting values in numerals, and which characters are equivalent in 7542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * lenient parsing. 7552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 7562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public RuleBasedNumberFormat(String description, ULocale locale) { 7572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller this.locale = locale; 7582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller init(description, null); 7592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 7602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 7612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 7622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Creates a RuleBasedNumberFormat that behaves according to the description 7632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * passed in. The formatter uses the specified locale to determine the 7642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * characters to use when formatting in numerals, and to define equivalences 7652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * for lenient parsing. 7662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <p> 7672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * The localizations data provides information about the public 7682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * rule sets and their localized display names for different 7692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * locales. The first element in the list is an array of the names 7702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * of the public rule sets. The first element in this array is 7712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * the initial default ruleset. The remaining elements in the 7722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * list are arrays of localizations of the names of the public 7732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * rule sets. Each of these is one longer than the initial array, 7742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * with the first String being the ULocale ID, and the remaining 7752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Strings being the localizations of the rule set names, in the 7762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * same order as the initial array. 7772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param description A description of the formatter's desired behavior. 7782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * See the class documentation for a complete explanation of the description 7792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * syntax. 7802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param localizations a list of localizations for the rule set names in the description. 7812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param locale A ULocale that governs which characters are used for 7822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * formatting values in numerals, and determines which characters are equivalent in 7832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * lenient parsing. 7842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 7852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public RuleBasedNumberFormat(String description, String[][] localizations, ULocale locale) { 7862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller this.locale = locale; 7872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller init(description, localizations); 7882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 7892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 7902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 7912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Creates a RuleBasedNumberFormat from a predefined description. The selector 7922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * code chooses among three possible predefined formats: spellout, ordinal, 7932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * and duration. 7942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param locale The locale for the formatter. 7952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param format A selector code specifying which kind of formatter to create for that 7962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * locale. There are three legal values: SPELLOUT, which creates a formatter that 7972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * spells out a value in words in the desired language, ORDINAL, which attaches 7982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * an ordinal suffix from the desired language to the end of a number (e.g. "123rd"), 7992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * and DURATION, which formats a duration in seconds as hours, minutes, and seconds. 8002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 8012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public RuleBasedNumberFormat(Locale locale, int format) { 8022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller this(ULocale.forLocale(locale), format); 8032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 8042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 8052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 8062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Creates a RuleBasedNumberFormat from a predefined description. The selector 8072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * code chooses among three possible predefined formats: spellout, ordinal, 8082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * and duration. 8092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param locale The locale for the formatter. 8102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param format A selector code specifying which kind of formatter to create for that 8112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * locale. There are four legal values: SPELLOUT, which creates a formatter that 8122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * spells out a value in words in the desired language, ORDINAL, which attaches 8132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * an ordinal suffix from the desired language to the end of a number (e.g. "123rd"), 8142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * DURATION, which formats a duration in seconds as hours, minutes, and seconds, and 8152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * NUMBERING_SYSTEM, which is used to invoke rules for alternate numbering 8162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * systems such as the Hebrew numbering system, or for Roman numerals, etc.. 8172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 8182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public RuleBasedNumberFormat(ULocale locale, int format) { 8192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller this.locale = locale; 8202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 8212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller ICUResourceBundle bundle = (ICUResourceBundle)UResourceBundle. 822f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert getBundleInstance(ICUData.ICU_RBNF_BASE_NAME, locale); 8232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 8242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // TODO: determine correct actual/valid locale. Note ambiguity 8252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // here -- do actual/valid refer to pattern, DecimalFormatSymbols, 8262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // or Collator? 8272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller ULocale uloc = bundle.getULocale(); 8282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller setLocale(uloc, uloc); 8292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 8302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller StringBuilder description = new StringBuilder(); 8312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller String[][] localizations = null; 8322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 8332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller try { 8342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller ICUResourceBundle rules = bundle.getWithFallback("RBNFRules/"+rulenames[format-1]); 8352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller UResourceBundleIterator it = rules.getIterator(); 8362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller while (it.hasNext()) { 8372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller description.append(it.nextString()); 8382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 8392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 8402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller catch (MissingResourceException e1) { 8412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 8422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 8432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // We use findTopLevel() instead of get() because 8442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // it's faster when we know that it's usually going to fail. 8452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller UResourceBundle locNamesBundle = bundle.findTopLevel(locnames[format - 1]); 8462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (locNamesBundle != null) { 8472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller localizations = new String[locNamesBundle.getSize()][]; 8482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller for (int i = 0; i < localizations.length; ++i) { 8492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller localizations[i] = locNamesBundle.get(i).getStringArray(); 8502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 8512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 8522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // else there are no localized names. It's not that important. 8532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 8542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller init(description.toString(), localizations); 8552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 8562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 8572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller private static final String[] rulenames = { 8582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller "SpelloutRules", "OrdinalRules", "DurationRules", "NumberingSystemRules", 8592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller }; 8602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller private static final String[] locnames = { 8612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller "SpelloutLocalizations", "OrdinalLocalizations", "DurationLocalizations", "NumberingSystemLocalizations", 8622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller }; 8632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 8642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 8652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Creates a RuleBasedNumberFormat from a predefined description. Uses the 8662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * default <code>FORMAT</code> locale. 8672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param format A selector code specifying which kind of formatter to create. 8682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * There are three legal values: SPELLOUT, which creates a formatter that spells 8692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * out a value in words in the default locale's language, ORDINAL, which attaches 8702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * an ordinal suffix from the default locale's language to a numeral, and 8712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * DURATION, which formats a duration in seconds as hours, minutes, and seconds always rounding down. 8722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * or NUMBERING_SYSTEM, which is used for alternate numbering systems such as Hebrew. 8732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @see Category#FORMAT 8742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 8752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public RuleBasedNumberFormat(int format) { 8762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller this(ULocale.getDefault(Category.FORMAT), format); 8772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 8782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 8792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller //----------------------------------------------------------------------- 8802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // boilerplate 8812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller //----------------------------------------------------------------------- 8822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 8832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 8842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Duplicates this formatter. 8852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @return A RuleBasedNumberFormat that is equal to this one. 8862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 887f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert @Override 8882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public Object clone() { 8892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return super.clone(); 8902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 8912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 8922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 8932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Tests two RuleBasedNumberFormats for equality. 8942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param that The formatter to compare against this one. 8952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @return true if the two formatters have identical behavior. 8962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 897f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert @Override 8982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public boolean equals(Object that) { 8992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // if the other object isn't a RuleBasedNumberFormat, that's 9002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // all we need to know 9012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // Test for capitalization info equality is adequately handled 9022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // by the NumberFormat test for capitalizationSetting equality; 9032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // the info here is just derived from that. 9042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (!(that instanceof RuleBasedNumberFormat)) { 9052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return false; 9062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } else { 9072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // cast the other object's pointer to a pointer to a 9082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // RuleBasedNumberFormat 9092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller RuleBasedNumberFormat that2 = (RuleBasedNumberFormat)that; 9102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 9112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // compare their locales and lenient-parse modes 9122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (!locale.equals(that2.locale) || lenientParse != that2.lenientParse) { 9132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return false; 9142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 9152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 9162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // if that succeeds, then compare their rule set lists 9172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (ruleSets.length != that2.ruleSets.length) { 9182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return false; 9192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 9202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller for (int i = 0; i < ruleSets.length; i++) { 9212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (!ruleSets[i].equals(that2.ruleSets[i])) { 9222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return false; 9232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 9242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 9252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 9262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return true; 9272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 9282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 929f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert 9302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 9312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Mock implementation of hashCode(). This implementation always returns a constant 9322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * value. When Java assertion is enabled, this method triggers an assertion failure. 9332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @deprecated This API is ICU internal only. 934836e6b40a94ec3fb7545a76cb072960442b7eee9Neil Fuller * @hide draft / provisional / internal are hidden on Android 9352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 936f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert @Override 9372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller @Deprecated 9382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public int hashCode() { 9392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return super.hashCode(); 9402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 9412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 9422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 9432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Generates a textual description of this formatter. 9442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @return a String containing a rule set that will produce a RuleBasedNumberFormat 9452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * with identical behavior to this one. This won't necessarily be identical 9462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * to the rule set description that was originally passed in, but will produce 9472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * the same result. 9482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 949f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert @Override 9502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public String toString() { 9512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 9522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // accumulate the descriptions of all the rule sets in a 9532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // StringBuffer, then cast it to a String and return it 9542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller StringBuilder result = new StringBuilder(); 9552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller for (NFRuleSet ruleSet : ruleSets) { 9562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller result.append(ruleSet.toString()); 9572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 9582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return result.toString(); 9592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 9602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 9612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 9622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Writes this object to a stream. 9632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param out The stream to write to. 9642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 9652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller private void writeObject(java.io.ObjectOutputStream out) 9662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller throws java.io.IOException { 9672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // we just write the textual description to the stream, so we 9682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // have an implementation-independent streaming format 9692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller out.writeUTF(this.toString()); 9702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller out.writeObject(this.locale); 9712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller out.writeInt(this.roundingMode); 9722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 9732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 9742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 9752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Reads this object in from a stream. 9762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param in The stream to read from. 9772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 9782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller private void readObject(java.io.ObjectInputStream in) 9792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller throws java.io.IOException { 9802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 9812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // read the description in from the stream 9822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller String description = in.readUTF(); 9832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller ULocale loc; 9842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 9852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller try { 9862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller loc = (ULocale) in.readObject(); 9872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } catch (Exception e) { 9882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller loc = ULocale.getDefault(Category.FORMAT); 9892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 9902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller try { 9912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller roundingMode = in.readInt(); 9922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } catch (Exception ignored) { 9932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 9942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 9952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // build a brand-new RuleBasedNumberFormat from the description, 9962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // then steal its substructure. This object's substructure and 9972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // the temporary RuleBasedNumberFormat drop on the floor and 9982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // get swept up by the garbage collector 9992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller RuleBasedNumberFormat temp = new RuleBasedNumberFormat(description, loc); 10002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller ruleSets = temp.ruleSets; 10012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller ruleSetsMap = temp.ruleSetsMap; 10022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller defaultRuleSet = temp.defaultRuleSet; 10032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller publicRuleSetNames = temp.publicRuleSetNames; 10042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller decimalFormatSymbols = temp.decimalFormatSymbols; 10052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller decimalFormat = temp.decimalFormat; 10062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller locale = temp.locale; 10072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller defaultInfinityRule = temp.defaultInfinityRule; 10082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller defaultNaNRule = temp.defaultNaNRule; 10092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 10102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 10112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 10122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller //----------------------------------------------------------------------- 10132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // public API functions 10142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller //----------------------------------------------------------------------- 10152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 10162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 10172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Returns a list of the names of all of this formatter's public rule sets. 10182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @return A list of the names of all of this formatter's public rule sets. 10192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 10202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public String[] getRuleSetNames() { 10212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return publicRuleSetNames.clone(); 10222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 10232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 10242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 10252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Return a list of locales for which there are locale-specific display names 10262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * for the rule sets in this formatter. If there are no localized display names, return null. 10272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @return an array of the ULocales for which there is rule set display name information 10282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 10292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public ULocale[] getRuleSetDisplayNameLocales() { 10302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (ruleSetDisplayNames != null) { 10312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller Set<String> s = ruleSetDisplayNames.keySet(); 10322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller String[] locales = s.toArray(new String[s.size()]); 10332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller Arrays.sort(locales, String.CASE_INSENSITIVE_ORDER); 10342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller ULocale[] result = new ULocale[locales.length]; 10352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller for (int i = 0; i < locales.length; ++i) { 10362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller result[i] = new ULocale(locales[i]); 10372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 10382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return result; 10392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 10402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return null; 10412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 10422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 10432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller private String[] getNameListForLocale(ULocale loc) { 10442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (loc != null && ruleSetDisplayNames != null) { 10452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller String[] localeNames = { loc.getBaseName(), ULocale.getDefault(Category.DISPLAY).getBaseName() }; 10462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller for (String lname : localeNames) { 10472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller while (lname.length() > 0) { 10482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller String[] names = ruleSetDisplayNames.get(lname); 10492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (names != null) { 10502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return names; 10512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 10522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller lname = ULocale.getFallback(lname); 10532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 10542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 10552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 10562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return null; 10572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 10582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 10592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 10602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Return the rule set display names for the provided locale. These are in the same order 10612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * as those returned by getRuleSetNames. The locale is matched against the locales for 10622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * which there is display name data, using normal fallback rules. If no locale matches, 10632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * the default display names are returned. (These are the internal rule set names minus 10642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * the leading '%'.) 10652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @return an array of the locales that have display name information 10662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @see #getRuleSetNames 10672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 10682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public String[] getRuleSetDisplayNames(ULocale loc) { 10692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller String[] names = getNameListForLocale(loc); 10702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (names != null) { 10712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return names.clone(); 10722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 10732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller names = getRuleSetNames(); 10742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller for (int i = 0; i < names.length; ++i) { 10752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller names[i] = names[i].substring(1); 10762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 10772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return names; 10782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 10792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 10802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 10812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Return the rule set display names for the current default <code>DISPLAY</code> locale. 10822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @return an array of the display names 10832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @see #getRuleSetDisplayNames(ULocale) 10842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @see Category#DISPLAY 10852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 10862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public String[] getRuleSetDisplayNames() { 10872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return getRuleSetDisplayNames(ULocale.getDefault(Category.DISPLAY)); 10882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 10892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 10902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 10912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Return the rule set display name for the provided rule set and locale. 10922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * The locale is matched against the locales for which there is display name data, using 10932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * normal fallback rules. If no locale matches, the default display name is returned. 10942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @return the display name for the rule set 10952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @see #getRuleSetDisplayNames 10962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @throws IllegalArgumentException if ruleSetName is not a valid rule set name for this format 10972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 10982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public String getRuleSetDisplayName(String ruleSetName, ULocale loc) { 10992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller String[] rsnames = publicRuleSetNames; 11002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller for (int ix = 0; ix < rsnames.length; ++ix) { 11012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (rsnames[ix].equals(ruleSetName)) { 11022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller String[] names = getNameListForLocale(loc); 11032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (names != null) { 11042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return names[ix]; 11052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 11062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return rsnames[ix].substring(1); 11072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 11082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 11092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller throw new IllegalArgumentException("unrecognized rule set name: " + ruleSetName); 11102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 11112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 11122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 11132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Return the rule set display name for the provided rule set in the current default <code>DISPLAY</code> locale. 11142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @return the display name for the rule set 11152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @see #getRuleSetDisplayName(String,ULocale) 11162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @see Category#DISPLAY 11172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 11182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public String getRuleSetDisplayName(String ruleSetName) { 11192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return getRuleSetDisplayName(ruleSetName, ULocale.getDefault(Category.DISPLAY)); 11202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 11212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 11222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 11232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Formats the specified number according to the specified rule set. 11242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param number The number to format. 11252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param ruleSet The name of the rule set to format the number with. 11262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * This must be the name of a valid public rule set for this formatter. 11272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @return A textual representation of the number. 11282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 11292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public String format(double number, String ruleSet) throws IllegalArgumentException { 11302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (ruleSet.startsWith("%%")) { 11312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller throw new IllegalArgumentException("Can't use internal rule set"); 11322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 11332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return adjustForContext(format(number, findRuleSet(ruleSet))); 11342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 11352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 11362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 11372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Formats the specified number according to the specified rule set. 11382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * (If the specified rule set specifies a master ["x.0"] rule, this function 11392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * ignores it. Convert the number to a double first if you ned it.) This 11402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * function preserves all the precision in the long-- it doesn't convert it 11412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * to a double. 11422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param number The number to format. 11432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param ruleSet The name of the rule set to format the number with. 11442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * This must be the name of a valid public rule set for this formatter. 11452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @return A textual representation of the number. 11462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 11472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public String format(long number, String ruleSet) throws IllegalArgumentException { 11482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (ruleSet.startsWith("%%")) { 11492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller throw new IllegalArgumentException("Can't use internal rule set"); 11502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 11512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return adjustForContext(format(number, findRuleSet(ruleSet))); 11522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 11532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 11542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 11552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Formats the specified number using the formatter's default rule set. 11562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * (The default rule set is the last public rule set defined in the description.) 11572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param number The number to format. 11582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param toAppendTo A StringBuffer that the result should be appended to. 11592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param ignore This function doesn't examine or update the field position. 11602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @return toAppendTo 11612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 1162f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert @Override 11632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public StringBuffer format(double number, 11642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller StringBuffer toAppendTo, 11652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller FieldPosition ignore) { 11662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // this is one of the inherited format() methods. Since it doesn't 11672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // have a way to select the rule set to use, it just uses the 11682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // default one 11692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // Note, the BigInteger/BigDecimal methods below currently go through this. 11702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (toAppendTo.length() == 0) { 11712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller toAppendTo.append(adjustForContext(format(number, defaultRuleSet))); 11722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } else { 11732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // appending to other text, don't capitalize 11742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller toAppendTo.append(format(number, defaultRuleSet)); 11752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 11762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return toAppendTo; 11772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 11782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 11792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 11802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Formats the specified number using the formatter's default rule set. 11812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * (The default rule set is the last public rule set defined in the description.) 11822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * (If the specified rule set specifies a master ["x.0"] rule, this function 11832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * ignores it. Convert the number to a double first if you ned it.) This 11842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * function preserves all the precision in the long-- it doesn't convert it 11852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * to a double. 11862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param number The number to format. 11872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param toAppendTo A StringBuffer that the result should be appended to. 11882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param ignore This function doesn't examine or update the field position. 11892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @return toAppendTo 11902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 1191f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert @Override 11922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public StringBuffer format(long number, 11932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller StringBuffer toAppendTo, 11942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller FieldPosition ignore) { 11952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // this is one of the inherited format() methods. Since it doesn't 11962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // have a way to select the rule set to use, it just uses the 11972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // default one 11982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (toAppendTo.length() == 0) { 11992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller toAppendTo.append(adjustForContext(format(number, defaultRuleSet))); 12002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } else { 12012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // appending to other text, don't capitalize 12022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller toAppendTo.append(format(number, defaultRuleSet)); 12032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 12042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return toAppendTo; 12052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 12062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 12072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 1208bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <strong style="font-family: helvetica; color: red;">NEW</strong> 12091fba789ac68efdd9120a7373f49daef42833e674Neil Fuller * Implement android.icu.text.NumberFormat: 12102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Format a BigInteger. 12112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 1212f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert @Override 12132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public StringBuffer format(BigInteger number, 12142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller StringBuffer toAppendTo, 12152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller FieldPosition pos) { 12162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return format(new android.icu.math.BigDecimal(number), toAppendTo, pos); 12172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 12182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 12192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 1220bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <strong style="font-family: helvetica; color: red;">NEW</strong> 12211fba789ac68efdd9120a7373f49daef42833e674Neil Fuller * Implement android.icu.text.NumberFormat: 12222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Format a BigDecimal. 12232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 1224f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert @Override 12252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public StringBuffer format(java.math.BigDecimal number, 12262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller StringBuffer toAppendTo, 12272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller FieldPosition pos) { 12282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return format(new android.icu.math.BigDecimal(number), toAppendTo, pos); 12292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 12302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 1231f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert private static final android.icu.math.BigDecimal MAX_VALUE = android.icu.math.BigDecimal.valueOf(Long.MAX_VALUE); 1232f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert private static final android.icu.math.BigDecimal MIN_VALUE = android.icu.math.BigDecimal.valueOf(Long.MIN_VALUE); 1233f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert 12342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 1235bfab1e7fec36dff93fb980c546ad64a565faf9fcPaul Duffin * <strong style="font-family: helvetica; color: red;">NEW</strong> 12361fba789ac68efdd9120a7373f49daef42833e674Neil Fuller * Implement android.icu.text.NumberFormat: 12372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Format a BigDecimal. 12382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 1239f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert @Override 12402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public StringBuffer format(android.icu.math.BigDecimal number, 12412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller StringBuffer toAppendTo, 12422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller FieldPosition pos) { 1243495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert if (MIN_VALUE.compareTo(number) > 0 || MAX_VALUE.compareTo(number) < 0) { 1244f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert // We're outside of our normal range that this framework can handle. 1245f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert // The DecimalFormat will provide more accurate results. 1246f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert return getDecimalFormat().format(number, toAppendTo, pos); 1247f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert } 1248f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert if (number.scale() == 0) { 1249f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert return format(number.longValue(), toAppendTo, pos); 1250f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert } 12512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return format(number.doubleValue(), toAppendTo, pos); 12522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 12532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 12542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 12552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Parses the specified string, beginning at the specified position, according 12562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * to this formatter's rules. This will match the string against all of the 12572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * formatter's public rule sets and return the value corresponding to the longest 12582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * parseable substring. This function's behavior is affected by the lenient 12592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * parse mode. 12602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param text The string to parse 12612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param parsePosition On entry, contains the position of the first character 12622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * in "text" to examine. On exit, has been updated to contain the position 12632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * of the first character in "text" that wasn't consumed by the parse. 12642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @return The number that corresponds to the parsed text. This will be an 12652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * instance of either Long or Double, depending on whether the result has a 12662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * fractional part. 12672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @see #setLenientParseMode 12682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 1269f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert @Override 12702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public Number parse(String text, ParsePosition parsePosition) { 12712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 12722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // parsePosition tells us where to start parsing. We copy the 12732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // text in the string from here to the end inro a new string, 12742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // and create a new ParsePosition and result variable to use 12752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // for the duration of the parse operation 12762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller String workingText = text.substring(parsePosition.getIndex()); 12772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller ParsePosition workingPos = new ParsePosition(0); 12782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller Number tempResult = null; 12792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 12802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // keep track of the largest number of characters consumed in 12812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // the various trials, and the result that corresponds to it 12822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller Number result = NFRule.ZERO; 12832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller ParsePosition highWaterMark = new ParsePosition(workingPos.getIndex()); 12842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 12852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // iterate over the public rule sets (beginning with the default one) 12862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // and try parsing the text with each of them. Keep track of which 12872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // one consumes the most characters: that's the one that determines 12882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // the result we return 12892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller for (int i = ruleSets.length - 1; i >= 0; i--) { 12902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // skip private or unparseable rule sets 12912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (!ruleSets[i].isPublic() || !ruleSets[i].isParseable()) { 12922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller continue; 12932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 12942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 12952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // try parsing the string with the rule set. If it gets past the 12962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // high-water mark, update the high-water mark and the result 12972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller tempResult = ruleSets[i].parse(workingText, workingPos, Double.MAX_VALUE); 12982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (workingPos.getIndex() > highWaterMark.getIndex()) { 12992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller result = tempResult; 13002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller highWaterMark.setIndex(workingPos.getIndex()); 13012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 13022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // commented out because this API on ParsePosition doesn't exist in 1.1.x 13032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // if (workingPos.getErrorIndex() > highWaterMark.getErrorIndex()) { 13042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // highWaterMark.setErrorIndex(workingPos.getErrorIndex()); 13052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // } 13062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 13072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // if we manage to use up all the characters in the string, 13082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // we don't have to try any more rule sets 13092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (highWaterMark.getIndex() == workingText.length()) { 13102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller break; 13112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 13122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 13132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // otherwise, reset our internal parse position to the 13142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // beginning and try again with the next rule set 13152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller workingPos.setIndex(0); 13162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 13172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 13182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // add the high water mark to our original parse position and 13192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // return the result 13202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller parsePosition.setIndex(parsePosition.getIndex() + highWaterMark.getIndex()); 13212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // commented out because this API on ParsePosition doesn't exist in 1.1.x 13222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // if (highWaterMark.getIndex() == 0) { 13232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // parsePosition.setErrorIndex(parsePosition.getIndex() + highWaterMark.getErrorIndex()); 13242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // } 13252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return result; 13262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 13272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 13282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 13292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Turns lenient parse mode on and off. 13302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 13312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * When in lenient parse mode, the formatter uses an RbnfLenientScanner 13322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * for parsing the text. Lenient parsing is only in effect if a scanner 13332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * is set. If a provider is not set, and this is used for parsing, 13342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * a default scanner <code>RbnfLenientScannerProviderImpl</code> will be set if 13352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * it is available on the classpath. Otherwise this will have no effect. 13362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 13372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param enabled If true, turns lenient-parse mode on; if false, turns it off. 13382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @see RbnfLenientScanner 13392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @see RbnfLenientScannerProvider 13402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 13412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public void setLenientParseMode(boolean enabled) { 13422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller lenientParse = enabled; 13432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 13442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 13452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 13462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Returns true if lenient-parse mode is turned on. Lenient parsing is off 13472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * by default. 13482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @return true if lenient-parse mode is turned on. 13492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @see #setLenientParseMode 13502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 13512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public boolean lenientParseEnabled() { 13522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return lenientParse; 13532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 13542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 13552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 1356f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert * Sets the provider for the lenient scanner. If this has not been set, 13572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * {@link #setLenientParseMode} 13582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * has no effect. This is necessary to decouple collation from format code. 13592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param scannerProvider the provider 13602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @see #setLenientParseMode 13612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @see #getLenientScannerProvider 13622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 13632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public void setLenientScannerProvider(RbnfLenientScannerProvider scannerProvider) { 13642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller this.scannerProvider = scannerProvider; 13652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 13662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 13672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 13682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Returns the lenient scanner provider. If none was set, and lenient parse is 13692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * enabled, this will attempt to instantiate a default scanner, setting it if 13702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * it was successful. Otherwise this returns false. 13712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 13722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @see #setLenientScannerProvider 13732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 13742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public RbnfLenientScannerProvider getLenientScannerProvider() { 13752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // there's a potential race condition if two threads try to set/get the scanner at 13762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // the same time, but you get what you get, and you shouldn't be using this from 13772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // multiple threads anyway. 13782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (scannerProvider == null && lenientParse && !lookedForScanner) { 13792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller try { 13802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller lookedForScanner = true; 13812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller Class<?> cls = Class.forName("android.icu.impl.text.RbnfScannerProviderImpl"); 13822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller RbnfLenientScannerProvider provider = (RbnfLenientScannerProvider)cls.newInstance(); 13832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller setLenientScannerProvider(provider); 13842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 13852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller catch (Exception e) { 13862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // any failure, we just ignore and return null 13872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 13882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 13892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 13902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return scannerProvider; 13912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 13922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 13932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 13942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Override the default rule set to use. If ruleSetName is null, reset 13952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * to the initial default rule set. 13962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param ruleSetName the name of the rule set, or null to reset the initial default. 13972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @throws IllegalArgumentException if ruleSetName is not the name of a public ruleset. 13982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 13992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public void setDefaultRuleSet(String ruleSetName) { 14002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (ruleSetName == null) { 14012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (publicRuleSetNames.length > 0) { 14022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller defaultRuleSet = findRuleSet(publicRuleSetNames[0]); 14032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } else { 14042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller defaultRuleSet = null; 14052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller int n = ruleSets.length; 14062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller while (--n >= 0) { 14072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller String currentName = ruleSets[n].getName(); 14082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (currentName.equals("%spellout-numbering") || 14092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller currentName.equals("%digits-ordinal") || 14102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller currentName.equals("%duration")) { 14112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 14122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller defaultRuleSet = ruleSets[n]; 14132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return; 14142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 14152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 14162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 14172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller n = ruleSets.length; 14182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller while (--n >= 0) { 14192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (ruleSets[n].isPublic()) { 14202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller defaultRuleSet = ruleSets[n]; 14212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller break; 14222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 14232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 14242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 14252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } else if (ruleSetName.startsWith("%%")) { 14262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller throw new IllegalArgumentException("cannot use private rule set: " + ruleSetName); 14272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } else { 14282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller defaultRuleSet = findRuleSet(ruleSetName); 14292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 14302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 14312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 14322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 14332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Return the name of the current default rule set. 14342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @return the name of the current default rule set, if it is public, else the empty string. 14352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 14362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public String getDefaultRuleSetName() { 14372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (defaultRuleSet != null && defaultRuleSet.isPublic()) { 14382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return defaultRuleSet.getName(); 14392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 14402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return ""; 14412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 1442f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert 14432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 14442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Sets the decimal format symbols used by this formatter. The formatter uses a copy of the 14452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * provided symbols. 1446f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert * 14472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param newSymbols desired DecimalFormatSymbols 14482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @see DecimalFormatSymbols 14492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 14502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public void setDecimalFormatSymbols(DecimalFormatSymbols newSymbols) { 14512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (newSymbols != null) { 14522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller decimalFormatSymbols = (DecimalFormatSymbols) newSymbols.clone(); 14532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (decimalFormat != null) { 14542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller decimalFormat.setDecimalFormatSymbols(decimalFormatSymbols); 14552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 14562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (defaultInfinityRule != null) { 14572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller defaultInfinityRule = null; 14582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller getDefaultInfinityRule(); // Reset with the new DecimalFormatSymbols 14592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 14602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (defaultNaNRule != null) { 14612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller defaultNaNRule = null; 14622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller getDefaultNaNRule(); // Reset with the new DecimalFormatSymbols 14632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 14642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 14652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // Apply the new decimalFormatSymbols by reparsing the rulesets 14662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller for (NFRuleSet ruleSet : ruleSets) { 14672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller ruleSet.setDecimalFormatSymbols(decimalFormatSymbols); 14682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 14692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 14702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 14712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 14722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 14731537b2f39245c07b00aa78c3600f7aebcb172490Neil Fuller * <strong>[icu]</strong> Set a particular DisplayContext value in the formatter, 1474f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert * such as CAPITALIZATION_FOR_STANDALONE. Note: For getContext, see 14752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * NumberFormat. 1476f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert * 1477f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert * @param context The DisplayContext value to set. 14782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 14792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // Here we override the NumberFormat implementation in order to 1480f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert // lazily initialize relevant items 1481f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert @Override 14822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public void setContext(DisplayContext context) { 14832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller super.setContext(context); 14842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (!capitalizationInfoIsSet && 14852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller (context==DisplayContext.CAPITALIZATION_FOR_UI_LIST_OR_MENU || context==DisplayContext.CAPITALIZATION_FOR_STANDALONE)) { 14862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller initCapitalizationContextInfo(locale); 14872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller capitalizationInfoIsSet = true; 14882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 14892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (capitalizationBrkIter == null && (context==DisplayContext.CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE || 14902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller (context==DisplayContext.CAPITALIZATION_FOR_UI_LIST_OR_MENU && capitalizationForListOrMenu) || 14912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller (context==DisplayContext.CAPITALIZATION_FOR_STANDALONE && capitalizationForStandAlone) )) { 14922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller capitalizationBrkIter = BreakIterator.getSentenceInstance(locale); 14932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 14942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 14952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 14962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 14972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Returns the rounding mode. 14982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 14992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @return A rounding mode, between <code>BigDecimal.ROUND_UP</code> and 15002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <code>BigDecimal.ROUND_UNNECESSARY</code>. 15012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @see #setRoundingMode 15022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @see java.math.BigDecimal 15032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 15042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller @Override 15052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public int getRoundingMode() { 15062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return roundingMode; 15072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 15082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 15092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 15102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Sets the rounding mode. This has no effect unless the rounding increment is greater 15112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * than zero. 15122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * 15132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param roundingMode A rounding mode, between <code>BigDecimal.ROUND_UP</code> and 15142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <code>BigDecimal.ROUND_UNNECESSARY</code>. 15152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @exception IllegalArgumentException if <code>roundingMode</code> is unrecognized. 15162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @see #getRoundingMode 15172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @see java.math.BigDecimal 15182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 15192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller @Override 15202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public void setRoundingMode(int roundingMode) { 15212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (roundingMode < BigDecimal.ROUND_UP || roundingMode > BigDecimal.ROUND_UNNECESSARY) { 15222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller throw new IllegalArgumentException("Invalid rounding mode: " + roundingMode); 15232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 15242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 15252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller this.roundingMode = roundingMode; 15262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 15272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 15282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 15292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller //----------------------------------------------------------------------- 15302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // package-internal API 15312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller //----------------------------------------------------------------------- 15322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 15332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 15342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Returns a reference to the formatter's default rule set. The default 15352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * rule set is the last public rule set in the description, or the one 15362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * most recently set by setDefaultRuleSet. 15372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @return The formatter's default rule set. 15382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 15392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller NFRuleSet getDefaultRuleSet() { 15402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return defaultRuleSet; 15412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 15422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 15432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 15442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Returns the scanner to use for lenient parsing. The scanner is 15452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * provided by the provider. 15462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @return The collator to use for lenient parsing, or null if lenient parsing 15472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * is turned off. 15482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 15492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller RbnfLenientScanner getLenientScanner() { 15502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (lenientParse) { 15512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller RbnfLenientScannerProvider provider = getLenientScannerProvider(); 15522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (provider != null) { 15532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return provider.get(locale, lenientParseRules); 15542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 15552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 15562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return null; 15572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 15582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 15592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 15602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Returns the DecimalFormatSymbols object that should be used by all DecimalFormat 15612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * instances owned by this formatter. This object is lazily created: this function 15622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * creates it the first time it's called. 15632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @return The DecimalFormatSymbols object that should be used by all DecimalFormat 15642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * instances owned by this formatter. 15652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 15662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller DecimalFormatSymbols getDecimalFormatSymbols() { 15672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // lazy-evaluate the DecimalFormatSymbols object. This object 15682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // is shared by all DecimalFormat instances belonging to this 15692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // formatter 15702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (decimalFormatSymbols == null) { 15712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller decimalFormatSymbols = new DecimalFormatSymbols(locale); 15722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 15732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return decimalFormatSymbols; 15742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 15752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 15762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller DecimalFormat getDecimalFormat() { 15772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (decimalFormat == null) { 15782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // Don't use NumberFormat.getInstance, which can cause a recursive call 15792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller String pattern = getPattern(locale, NUMBERSTYLE); 15802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller decimalFormat = new DecimalFormat(pattern, getDecimalFormatSymbols()); 15812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 15822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return decimalFormat; 15832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 15842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 15852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller PluralFormat createPluralFormat(PluralRules.PluralType pluralType, String pattern) { 15862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return new PluralFormat(locale, pluralType, pattern, getDecimalFormat()); 15872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 15882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 15892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 15902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Returns the default rule for infinity. This object is lazily created: this function 15912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * creates it the first time it's called. 15922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 15932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller NFRule getDefaultInfinityRule() { 15942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (defaultInfinityRule == null) { 15952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller defaultInfinityRule = new NFRule(this, "Inf: " + getDecimalFormatSymbols().getInfinity()); 15962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 15972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return defaultInfinityRule; 15982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 15992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 16002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 16012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Returns the default rule for NaN. This object is lazily created: this function 16022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * creates it the first time it's called. 16032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 16042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller NFRule getDefaultNaNRule() { 16052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (defaultNaNRule == null) { 16062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller defaultNaNRule = new NFRule(this, "NaN: " + getDecimalFormatSymbols().getNaN()); 16072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 16082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return defaultNaNRule; 16092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 16102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 16112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller //----------------------------------------------------------------------- 16122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // construction implementation 16132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller //----------------------------------------------------------------------- 16142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 16152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 16162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * This extracts the special information from the rule sets before the 16172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * main parsing starts. Extra whitespace must have already been removed 16182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * from the description. If found, the special information is removed from the 16192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * description and returned, otherwise the description is unchanged and null 16202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * is returned. Note: the trailing semicolon at the end of the special 16212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * rules is stripped. 16222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param description the rbnf description with extra whitespace removed 16232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param specialName the name of the special rule text to extract 16242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @return the special rule text, or null if the rule was not found 16252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 16262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller private String extractSpecial(StringBuilder description, String specialName) { 16272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller String result = null; 16282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller int lp = description.indexOf(specialName); 16292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (lp != -1) { 16302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // we've got to make sure we're not in the middle of a rule 16312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // (where specialName would actually get treated as 16322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // rule text) 16332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (lp == 0 || description.charAt(lp - 1) == ';') { 16342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // locate the beginning and end of the actual special 16352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // rules (there may be whitespace between the name and 16362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // the first token in the description) 16372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller int lpEnd = description.indexOf(";%", lp); 16382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 16392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (lpEnd == -1) { 16402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller lpEnd = description.length() - 1; // later we add 1 back to get the '%' 16412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 16422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller int lpStart = lp + specialName.length(); 16432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller while (lpStart < lpEnd && 16442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller PatternProps.isWhiteSpace(description.charAt(lpStart))) { 16452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller ++lpStart; 16462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 16472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 16482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // copy out the special rules 16492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller result = description.substring(lpStart, lpEnd); 16502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 16512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // remove the special rule from the description 16522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller description.delete(lp, lpEnd+1); // delete the semicolon but not the '%' 16532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 16542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 16552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return result; 16562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 16572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 16582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 16592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * This function parses the description and uses it to build all of 16602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * internal data structures that the formatter uses to do formatting 16612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param description The description of the formatter's desired behavior. 16622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * This is either passed in by the caller or loaded out of a resource 16632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * by one of the constructors, and is in the description format specified 16642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * in the class docs. 16652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 16662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller private void init(String description, String[][] localizations) { 16672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller initLocalizations(localizations); 16682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 16692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // start by stripping the trailing whitespace from all the rules 16702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // (this is all the whitespace follwing each semicolon in the 16712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // description). This allows us to look for rule-set boundaries 16722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // by searching for ";%" without having to worry about whitespace 16732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // between the ; and the % 16742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller StringBuilder descBuf = stripWhitespace(description); 16752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 16762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // check to see if there's a set of lenient-parse rules. If there 16772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // is, pull them out into our temporary holding place for them, 16782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // and delete them from the description before the real description- 16792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // parsing code sees them 16802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 16812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller lenientParseRules = extractSpecial(descBuf, "%%lenient-parse:"); 16822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller postProcessRules = extractSpecial(descBuf, "%%post-process:"); 16832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 16842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // pre-flight parsing the description and count the number of 16852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // rule sets (";%" marks the end of one rule set and the beginning 16862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // of the next) 16872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller int numRuleSets = 1; 16882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller int p = 0; 16892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller while ((p = descBuf.indexOf(";%", p)) != -1) { 16902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller ++numRuleSets; 16912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller p += 2; // Skip the length of ";%" 16922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 16932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 16942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // our rule list is an array of the appropriate size 16952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller ruleSets = new NFRuleSet[numRuleSets]; 16962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller ruleSetsMap = new HashMap<String, NFRuleSet>(numRuleSets * 2 + 1); 16972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller defaultRuleSet = null; 16982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 16992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // Used to count the number of public rule sets 17002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // Public rule sets have names that begin with % instead of %%. 17012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller int publicRuleSetCount = 0; 17022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 17032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // divide up the descriptions into individual rule-set descriptions 17042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // and store them in a temporary array. At each step, we also 17052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // new up a rule set, but all this does is initialize its name 17062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // and remove it from its description. We can't actually parse 17072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // the rest of the descriptions and finish initializing everything 17082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // because we have to know the names and locations of all the rule 17092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // sets before we can actually set everything up 17102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller String[] ruleSetDescriptions = new String[numRuleSets]; 17112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 17122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller int curRuleSet = 0; 17132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller int start = 0; 17142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 17152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller while (curRuleSet < ruleSets.length) { 17162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller p = descBuf.indexOf(";%", start); 17172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (p < 0) { 17182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller p = descBuf.length() - 1; 17192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 17202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller ruleSetDescriptions[curRuleSet] = descBuf.substring(start, p + 1); 17212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller NFRuleSet ruleSet = new NFRuleSet(this, ruleSetDescriptions, curRuleSet); 17222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller ruleSets[curRuleSet] = ruleSet; 17232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller String currentName = ruleSet.getName(); 17242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller ruleSetsMap.put(currentName, ruleSet); 17252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (!currentName.startsWith("%%")) { 17262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller ++publicRuleSetCount; 17272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (defaultRuleSet == null 17282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller && currentName.equals("%spellout-numbering") 17292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller || currentName.equals("%digits-ordinal") 17302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller || currentName.equals("%duration")) 17312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller { 17322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller defaultRuleSet = ruleSet; 17332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 17342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 17352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller ++curRuleSet; 17362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller start = p + 1; 17372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 17382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 17392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // now we can take note of the formatter's default rule set, which 17402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // is the last public rule set in the description (it's the last 17412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // rather than the first so that a user can create a new formatter 17422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // from an existing formatter and change its default behavior just 17432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // by appending more rule sets to the end) 17442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 17452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // {dlf} Initialization of a fraction rule set requires the default rule 17462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // set to be known. For purposes of initialization, this is always the 17472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // last public rule set, no matter what the localization data says. 17482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 17492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // Set the default ruleset to the last public ruleset, unless one of the predefined 17502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // ruleset names %spellout-numbering, %digits-ordinal, or %duration is found 17512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 17522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (defaultRuleSet == null) { 17532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller for (int i = ruleSets.length - 1; i >= 0; --i) { 17542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (!ruleSets[i].getName().startsWith("%%")) { 17552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller defaultRuleSet = ruleSets[i]; 17562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller break; 17572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 17582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 17592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 17602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (defaultRuleSet == null) { 17612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller defaultRuleSet = ruleSets[ruleSets.length - 1]; 17622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 17632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 17642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // finally, we can go back through the temporary descriptions 17652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // list and finish setting up the substructure 17662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller for (int i = 0; i < ruleSets.length; i++) { 17672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller ruleSets[i].parseRules(ruleSetDescriptions[i]); 17682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 17692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 17702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // Now that the rules are initialized, the 'real' default rule 17712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // set can be adjusted by the localization data. 17722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 17732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // prepare an array of the proper size and copy the names into it 17742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller String[] publicRuleSetTemp = new String[publicRuleSetCount]; 17752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller publicRuleSetCount = 0; 17762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller for (int i = ruleSets.length - 1; i >= 0; i--) { 17772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (!ruleSets[i].getName().startsWith("%%")) { 17782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller publicRuleSetTemp[publicRuleSetCount++] = ruleSets[i].getName(); 17792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 17802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 17812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 17822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (publicRuleSetNames != null) { 17832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // confirm the names, if any aren't in the rules, that's an error 17842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // it is ok if the rules contain public rule sets that are not in this list 17852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller loop: for (int i = 0; i < publicRuleSetNames.length; ++i) { 17862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller String name = publicRuleSetNames[i]; 17872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller for (int j = 0; j < publicRuleSetTemp.length; ++j) { 17882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (name.equals(publicRuleSetTemp[j])) { 17892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller continue loop; 17902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 17912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 17922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller throw new IllegalArgumentException("did not find public rule set: " + name); 17932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 17942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 17952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller defaultRuleSet = findRuleSet(publicRuleSetNames[0]); // might be different 17962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } else { 17972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller publicRuleSetNames = publicRuleSetTemp; 17982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 17992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 18002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 18012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 18022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Take the localizations array and create a Map from the locale strings to 18032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * the localization arrays. 18042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 18052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller private void initLocalizations(String[][] localizations) { 18062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (localizations != null) { 18072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller publicRuleSetNames = localizations[0].clone(); 18082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 18092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller Map<String, String[]> m = new HashMap<String, String[]>(); 18102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller for (int i = 1; i < localizations.length; ++i) { 18112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller String[] data = localizations[i]; 18122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller String loc = data[0]; 18132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller String[] names = new String[data.length-1]; 18142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (names.length != publicRuleSetNames.length) { 18152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller throw new IllegalArgumentException("public name length: " + publicRuleSetNames.length + 18162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller " != localized names[" + i + "] length: " + names.length); 18172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 18182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller System.arraycopy(data, 1, names, 0, names.length); 18192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller m.put(loc, names); 18202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 18212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 18222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (!m.isEmpty()) { 18232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller ruleSetDisplayNames = m; 18242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 18252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 18262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 18272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 18282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 1829f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert * Set capitalizationForListOrMenu, capitalizationForStandAlone 18302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 18312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller private void initCapitalizationContextInfo(ULocale theLocale) { 1832f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert ICUResourceBundle rb = (ICUResourceBundle) UResourceBundle.getBundleInstance(ICUData.ICU_BASE_NAME, theLocale); 18332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller try { 18342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller ICUResourceBundle rdb = rb.getWithFallback("contextTransforms/number-spellout"); 18352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller int[] intVector = rdb.getIntVector(); 18362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (intVector.length >= 2) { 18372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller capitalizationForListOrMenu = (intVector[0] != 0); 18382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller capitalizationForStandAlone = (intVector[1] != 0); 18392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 18402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } catch (MissingResourceException e) { 18412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // use default 18422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 18432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 18442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 18452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 18462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * This function is used by init() to strip whitespace between rules (i.e., 18472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * after semicolons). 18482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param description The formatter description 18492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @return The description with all the whitespace that follows semicolons 18502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * taken out. 18512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 18522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller private StringBuilder stripWhitespace(String description) { 18532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // since we don't have a method that deletes characters (why?!!) 18542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // create a new StringBuffer to copy the text into 18552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller StringBuilder result = new StringBuilder(); 18562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller int descriptionLength = description.length(); 18572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 18582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // iterate through the characters... 18592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller int start = 0; 18602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller while (start < descriptionLength) { 18612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // seek to the first non-whitespace character... 18622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller while (start < descriptionLength 18632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller && PatternProps.isWhiteSpace(description.charAt(start))) 18642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller { 18652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller ++start; 18662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 18672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 18682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller //if the first non-whitespace character is semicolon, skip it and continue 18692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (start < descriptionLength && description.charAt(start) == ';') { 18702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller start += 1; 18712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller continue; 18722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 18732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 18742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // locate the next semicolon in the text and copy the text from 18752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // our current position up to that semicolon into the result 18762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller int p = description.indexOf(';', start); 18772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (p == -1) { 18782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // or if we don't find a semicolon, just copy the rest of 18792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // the string into the result 18802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller result.append(description.substring(start)); 18812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller break; 18822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 18832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller else if (p < descriptionLength) { 18842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller result.append(description.substring(start, p + 1)); 18852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller start = p + 1; 18862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 18872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller else { 18882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // when we get here, we've seeked off the end of the string, and 18892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // we terminate the loop (we continue until *start* is -1 rather 18902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // than until *p* is -1, because otherwise we'd miss the last 18912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // rule in the description) 18922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller break; 18932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 18942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 18952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return result; 18962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 18972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 18982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller //----------------------------------------------------------------------- 18992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // formatting implementation 19002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller //----------------------------------------------------------------------- 19012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 19022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 19032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Bottleneck through which all the public format() methods 19042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * that take a double pass. By the time we get here, we know 19052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * which rule set we're using to do the formatting. 19062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param number The number to format 19072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param ruleSet The rule set to use to format the number 19082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @return The text that resulted from formatting the number 19092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 19102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller private String format(double number, NFRuleSet ruleSet) { 19112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // all API format() routines that take a double vector through 19122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // here. Create an empty string buffer where the result will 19132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // be built, and pass it to the rule set (along with an insertion 19142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // position of 0 and the number being formatted) to the rule set 19152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // for formatting 1916f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert StringBuilder result = new StringBuilder(); 191705fa7802d0874812c234a29745586677ee5837eaFredrik Roubert if (getRoundingMode() != BigDecimal.ROUND_UNNECESSARY && !Double.isNaN(number) && !Double.isInfinite(number)) { 19182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // We convert to a string because BigDecimal insists on excessive precision. 19192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller number = new BigDecimal(Double.toString(number)).setScale(getMaximumFractionDigits(), roundingMode).doubleValue(); 19202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 19212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller ruleSet.format(number, result, 0, 0); 19222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller postProcess(result, ruleSet); 19232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return result.toString(); 19242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 19252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 19262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 19272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Bottleneck through which all the public format() methods 19282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * that take a long pass. By the time we get here, we know 19292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * which rule set we're using to do the formatting. 19302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param number The number to format 19312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param ruleSet The rule set to use to format the number 19322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @return The text that resulted from formatting the number 19332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 19342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller private String format(long number, NFRuleSet ruleSet) { 19352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // all API format() routines that take a double vector through 19362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // here. We have these two identical functions-- one taking a 19372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // double and one taking a long-- the couple digits of precision 19382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // that long has but double doesn't (both types are 8 bytes long, 19392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // but double has to borrow some of the mantissa bits to hold 19402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // the exponent). 19412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // Create an empty string buffer where the result will 19422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // be built, and pass it to the rule set (along with an insertion 19432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // position of 0 and the number being formatted) to the rule set 19442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // for formatting 1945f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert StringBuilder result = new StringBuilder(); 1946f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert if (number == Long.MIN_VALUE) { 1947f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert // We can't handle this value right now. Provide an accurate default value. 1948f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert result.append(getDecimalFormat().format(Long.MIN_VALUE)); 1949f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert } 1950f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert else { 1951f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert ruleSet.format(number, result, 0, 0); 1952f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert } 19532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller postProcess(result, ruleSet); 19542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return result.toString(); 19552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 19562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 19572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 19582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Post-process the rules if we have a post-processor. 19592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 1960f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert private void postProcess(StringBuilder result, NFRuleSet ruleSet) { 19612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (postProcessRules != null) { 19622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (postProcessor == null) { 19632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller int ix = postProcessRules.indexOf(";"); 19642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (ix == -1) { 19652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller ix = postProcessRules.length(); 19662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 19672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller String ppClassName = postProcessRules.substring(0, ix).trim(); 19682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller try { 19692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller Class<?> cls = Class.forName(ppClassName); 19702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller postProcessor = (RBNFPostProcessor)cls.newInstance(); 19712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller postProcessor.init(this, postProcessRules); 19722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 19732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller catch (Exception e) { 19742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // if debug, print it out 19752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (DEBUG) System.out.println("could not locate " + ppClassName + ", error " + 19762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller e.getClass().getName() + ", " + e.getMessage()); 19772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller postProcessor = null; 19782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller postProcessRules = null; // don't try again 19792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return; 19802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 19812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 19822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 19832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller postProcessor.process(result, ruleSet); 19842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 19852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 19862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 19872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 19882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Adjust capitalization of formatted result for display context 19892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 19902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller private String adjustForContext(String result) { 1991495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert DisplayContext capitalization = getContext(DisplayContext.Type.CAPITALIZATION); 1992495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert if (capitalization != DisplayContext.CAPITALIZATION_NONE && result != null && result.length() > 0 1993495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert && UCharacter.isLowerCase(result.codePointAt(0))) 1994495cb271e305cfb399d463f32210a371198f0abfFredrik Roubert { 19952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if ( capitalization==DisplayContext.CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE || 19962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller (capitalization == DisplayContext.CAPITALIZATION_FOR_UI_LIST_OR_MENU && capitalizationForListOrMenu) || 19972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller (capitalization == DisplayContext.CAPITALIZATION_FOR_STANDALONE && capitalizationForStandAlone) ) { 19982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (capitalizationBrkIter == null) { 19992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // should only happen when deserializing, etc. 20002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller capitalizationBrkIter = BreakIterator.getSentenceInstance(locale); 20012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 20022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return UCharacter.toTitleCase(locale, result, capitalizationBrkIter, 20032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller UCharacter.TITLECASE_NO_LOWERCASE | UCharacter.TITLECASE_NO_BREAK_ADJUSTMENT); 20042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 20052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 20062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return result; 20072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 20082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 20092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /** 20102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Returns the named rule set. Throws an IllegalArgumentException 20112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * if this formatter doesn't have a rule set with that name. 20122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @param name The name of the desired rule set 20132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @return The rule set with that name 20142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 20152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller NFRuleSet findRuleSet(String name) throws IllegalArgumentException { 20162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller NFRuleSet result = ruleSetsMap.get(name); 20172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (result == null) { 20182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller throw new IllegalArgumentException("No rule set named " + name); 20192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 20202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return result; 20212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 20222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller} 2023