/*
 *******************************************************************************
 * Copyright (C) 1996-2015, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 */

package com.ibm.icu.text;

import java.math.BigInteger;
import java.text.FieldPosition;
import java.text.ParsePosition;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.Set;

import com.ibm.icu.impl.ICUDebug;
import com.ibm.icu.impl.ICUResourceBundle;
import com.ibm.icu.impl.PatternProps;
import com.ibm.icu.lang.UCharacter;
import com.ibm.icu.math.BigDecimal;
import com.ibm.icu.util.ULocale;
import com.ibm.icu.util.ULocale.Category;
import com.ibm.icu.util.UResourceBundle;
import com.ibm.icu.util.UResourceBundleIterator;


/**
 * <p>A class that formats numbers according to a set of rules. This number formatter is
 * typically used for spelling out numeric values in words (e.g., 25,3476 as
 * &quot;twenty-five thousand three hundred seventy-six&quot; or &quot;vingt-cinq mille trois
 * cents soixante-seize&quot; or
 * &quot;funfundzwanzigtausenddreihundertsechsundsiebzig&quot;), but can also be used for
 * other complicated formatting tasks, such as formatting a number of seconds as hours,
 * minutes and seconds (e.g., 3,730 as &quot;1:02:10&quot;).</p>
 *
 * <p>The resources contain three predefined formatters for each locale: spellout, which
 * spells out a value in words (123 is &quot;one hundred twenty-three&quot;); ordinal, which
 * appends an ordinal suffix to the end of a numeral (123 is &quot;123rd&quot;); and
 * duration, which shows a duration in seconds as hours, minutes, and seconds (123 is
 * &quot;2:03&quot;).&nbsp; The client can also define more specialized <tt>RuleBasedNumberFormat</tt>s
 * by supplying programmer-defined rule sets.</p>
 *
 * <p>The behavior of a <tt>RuleBasedNumberFormat</tt> is specified by a textual description
 * that is either passed to the constructor as a <tt>String</tt> or loaded from a resource
 * bundle. In its simplest form, the description consists of a semicolon-delimited list of <em>rules.</em>
 * Each rule has a string of output text and a value or range of values it is applicable to.
 * In a typical spellout rule set, the first twenty rules are the words for the numbers from
 * 0 to 19:</p>
 *
 * <pre>zero; one; two; three; four; five; six; seven; eight; nine;
 * ten; eleven; twelve; thirteen; fourteen; fifteen; sixteen; seventeen; eighteen; nineteen;</pre>
 *
 * <p>For larger numbers, we can use the preceding set of rules to format the ones place, and
 * we only have to supply the words for the multiples of 10:</p>
 *
 * <pre>20: twenty[-&gt;&gt;];
 * 30: thirty{-&gt;&gt;];
 * 40: forty[-&gt;&gt;];
 * 50: fifty[-&gt;&gt;];
 * 60: sixty[-&gt;&gt;];
 * 70: seventy[-&gt;&gt;];
 * 80: eighty[-&gt;&gt;];
 * 90: ninety[-&gt;&gt;];</pre>
 *
 * <p>In these rules, the <em>base value</em> is spelled out explicitly and set off from the
 * rule's output text with a colon. The rules are in a sorted list, and a rule is applicable
 * to all numbers from its own base value to one less than the next rule's base value. The
 * &quot;&gt;&gt;&quot; token is called a <em>substitution</em> and tells the formatter to
 * isolate the number's ones digit, format it using this same set of rules, and place the
 * result at the position of the &quot;&gt;&gt;&quot; token. Text in brackets is omitted if
 * the number being formatted is an even multiple of 10 (the hyphen is a literal hyphen; 24
 * is &quot;twenty-four,&quot; not &quot;twenty four&quot;).</p>
 *
 * <p>For even larger numbers, we can actually look up several parts of the number in the
 * list:</p>
 *
 * <pre>100: &lt;&lt; hundred[ &gt;&gt;];</pre>
 *
 * <p>The &quot;&lt;&lt;&quot; represents a new kind of substitution. The &lt;&lt; isolates
 * the hundreds digit (and any digits to its left), formats it using this same rule set, and
 * places the result where the &quot;&lt;&lt;&quot; was. Notice also that the meaning of
 * &gt;&gt; has changed: it now refers to both the tens and the ones digits. The meaning of
 * both substitutions depends on the rule's base value. The base value determines the rule's <em>divisor,</em>
 * which is the highest power of 10 that is less than or equal to the base value (the user
 * can change this). To fill in the substitutions, the formatter divides the number being
 * formatted by the divisor. The integral quotient is used to fill in the &lt;&lt;
 * substitution, and the remainder is used to fill in the &gt;&gt; substitution. The meaning
 * of the brackets changes similarly: text in brackets is omitted if the value being
 * formatted is an even multiple of the rule's divisor. The rules are applied recursively, so
 * if a substitution is filled in with text that includes another substitution, that
 * substitution is also filled in.</p>
 *
 * <p>This rule covers values up to 999, at which point we add another rule:</p>
 *
 * <pre>1000: &lt;&lt; thousand[ &gt;&gt;];</pre>
 *
 * <p>Again, the meanings of the brackets and substitution tokens shift because the rule's
 * base value is a higher power of 10, changing the rule's divisor. This rule can actually be
 * used all the way up to 999,999. This allows us to finish out the rules as follows:</p>
 *
 * <pre>1,000,000: &lt;&lt; million[ &gt;&gt;];
 * 1,000,000,000: &lt;&lt; billion[ &gt;&gt;];
 * 1,000,000,000,000: &lt;&lt; trillion[ &gt;&gt;];
 * 1,000,000,000,000,000: OUT OF RANGE!;</pre>
 *
 * <p>Commas, periods, and spaces can be used in the base values to improve legibility and
 * are ignored by the rule parser. The last rule in the list is customarily treated as an
 * &quot;overflow rule,&quot; applying to everything from its base value on up, and often (as
 * in this example) being used to print out an error message or default representation.
 * Notice also that the size of the major groupings in large numbers is controlled by the
 * spacing of the rules: because in English we group numbers by thousand, the higher rules
 * are separated from each other by a factor of 1,000.</p>
 *
 * <p>To see how these rules actually work in practice, consider the following example:
 * Formatting 25,430 with this rule set would work like this:</p>
 *
 * <table border="0" width="630">
 *   <tr>
 *     <td width="21"></td>
 *     <td width="257" valign="top"><strong>&lt;&lt; thousand &gt;&gt;</strong></td>
 *     <td width="340" valign="top">[the rule whose base value is 1,000 is applicable to 25,340]</td>
 *   </tr>
 *   <tr>
 *     <td width="21"></td>
 *     <td width="257" valign="top"><strong>twenty-&gt;&gt;</strong> thousand &gt;&gt;</td>
 *     <td width="340" valign="top">[25,340 over 1,000 is 25. The rule for 20 applies.]</td>
 *   </tr>
 *   <tr>
 *     <td width="21"></td>
 *     <td width="257" valign="top">twenty-<strong>five</strong> thousand &gt;&gt;</td>
 *     <td width="340" valign="top">[25 mod 10 is 5. The rule for 5 is &quot;five.&quot;</td>
 *   </tr>
 *   <tr>
 *     <td width="21"></td>
 *     <td width="257" valign="top">twenty-five thousand <strong>&lt;&lt; hundred &gt;&gt;</strong></td>
 *     <td width="340" valign="top">[25,340 mod 1,000 is 340. The rule for 100 applies.]</td>
 *   </tr>
 *   <tr>
 *     <td width="21"></td>
 *     <td width="257" valign="top">twenty-five thousand <strong>three</strong> hundred &gt;&gt;</td>
 *     <td width="340" valign="top">[340 over 100 is 3. The rule for 3 is &quot;three.&quot;]</td>
 *   </tr>
 *   <tr>
 *     <td width="21"></td>
 *     <td width="257" valign="top">twenty-five thousand three hundred <strong>forty</strong></td>
 *     <td width="340" valign="top">[340 mod 100 is 40. The rule for 40 applies. Since 40 divides
 *     evenly by 10, the hyphen and substitution in the brackets are omitted.]</td>
 *   </tr>
 * </table>
 *
 * <p>The above syntax suffices only to format positive integers. To format negative numbers,
 * we add a special rule:</p>
 *
 * <pre>-x: minus &gt;&gt;;</pre>
 *
 * <p>This is called a <em>negative-number rule,</em> and is identified by &quot;-x&quot;
 * where the base value would be. This rule is used to format all negative numbers. the
 * &gt;&gt; token here means &quot;find the number's absolute value, format it with these
 * rules, and put the result here.&quot;</p>
 *
 * <p>We also add a special rule called a <em>fraction rule </em>for numbers with fractional
 * parts:</p>
 *
 * <pre>x.x: &lt;&lt; point &gt;&gt;;</pre>
 *
 * <p>This rule is used for all positive non-integers (negative non-integers pass through the
 * negative-number rule first and then through this rule). Here, the &lt;&lt; token refers to
 * the number's integral part, and the &gt;&gt; to the number's fractional part. The
 * fractional part is formatted as a series of single-digit numbers (e.g., 123.456 would be
 * formatted as &quot;one hundred twenty-three point four five six&quot;).</p>
 *
 * <p>To see how this rule syntax is applied to various languages, examine the resource data.</p>
 *
 * <p>There is actually much more flexibility built into the rule language than the
 * description above shows. A formatter may own multiple rule sets, which can be selected by
 * the caller, and which can use each other to fill in their substitutions. Substitutions can
 * also be filled in with digits, using a DecimalFormat object. There is syntax that can be
 * used to alter a rule's divisor in various ways. And there is provision for much more
 * flexible fraction handling. A complete description of the rule syntax follows:</p>
 *
 * <hr>
 *
 * <p>The description of a <tt>RuleBasedNumberFormat</tt>'s behavior consists of one or more <em>rule
 * sets.</em> Each rule set consists of a name, a colon, and a list of <em>rules.</em> A rule
 * set name must begin with a % sign. Rule sets with names that begin with a single % sign
 * are <em>public:</em> the caller can specify that they be used to format and parse numbers.
 * Rule sets with names that begin with %% are <em>private:</em> they exist only for the use
 * of other rule sets. If a formatter only has one rule set, the name may be omitted.</p>
 *
 * <p>The user can also specify a special &quot;rule set&quot; named <tt>%%lenient-parse</tt>.
 * The body of <tt>%%lenient-parse</tt> isn't a set of number-formatting rules, but a <tt>RuleBasedCollator</tt>
 * description which is used to define equivalences for lenient parsing. For more information
 * on the syntax, see <tt>RuleBasedCollator</tt>. For more information on lenient parsing,
 * see <tt>setLenientParse()</tt>. <em>Note:</em> symbols that have syntactic meaning
 * in collation rules, such as '&amp;', have no particular meaning when appearing outside
 * of the <tt>lenient-parse</tt> rule set.</p>
 *
 * <p>The body of a rule set consists of an ordered, semicolon-delimited list of <em>rules.</em>
 * Internally, every rule has a base value, a divisor, rule text, and zero, one, or two <em>substitutions.</em>
 * These parameters are controlled by the description syntax, which consists of a <em>rule
 * descriptor,</em> a colon, and a <em>rule body.</em></p>
 *
 * <p>A rule descriptor can take one of the following forms (text in <em>italics</em> is the
 * name of a token):</p>
 *
 * <table border="0" width="100%">
 *   <tr>
 *     <td width="5%" valign="top"></td>
 *     <td width="8%" valign="top"><em>bv</em>:</td>
 *     <td valign="top"><em>bv</em> specifies the rule's base value. <em>bv</em> is a decimal
 *     number expressed using ASCII digits. <em>bv</em> may contain spaces, period, and commas,
 *     which are ignored. The rule's divisor is the highest power of 10 less than or equal to
 *     the base value.</td>
 *   </tr>
 *   <tr>
 *     <td width="5%" valign="top"></td>
 *     <td width="8%" valign="top"><em>bv</em>/<em>rad</em>:</td>
 *     <td valign="top"><em>bv</em> specifies the rule's base value. The rule's divisor is the
 *     highest power of <em>rad</em> less than or equal to the base value.</td>
 *   </tr>
 *   <tr>
 *     <td width="5%" valign="top"></td>
 *     <td width="8%" valign="top"><em>bv</em>&gt;:</td>
 *     <td valign="top"><em>bv</em> specifies the rule's base value. To calculate the divisor,
 *     let the radix be 10, and the exponent be the highest exponent of the radix that yields a
 *     result less than or equal to the base value. Every &gt; character after the base value
 *     decreases the exponent by 1. If the exponent is positive or 0, the divisor is the radix
 *     raised to the power of the exponent; otherwise, the divisor is 1.</td>
 *   </tr>
 *   <tr>
 *     <td width="5%" valign="top"></td>
 *     <td width="8%" valign="top"><em>bv</em>/<em>rad</em>&gt;:</td>
 *     <td valign="top"><em>bv</em> specifies the rule's base value. To calculate the divisor,
 *     let the radix be <em>rad</em>, and the exponent be the highest exponent of the radix that
 *     yields a result less than or equal to the base value. Every &gt; character after the radix
 *     decreases the exponent by 1. If the exponent is positive or 0, the divisor is the radix
 *     raised to the power of the exponent; otherwise, the divisor is 1.</td>
 *   </tr>
 *   <tr>
 *     <td width="5%" valign="top"></td>
 *     <td width="8%" valign="top">-x:</td>
 *     <td valign="top">The rule is a negative-number rule.</td>
 *   </tr>
 *   <tr>
 *     <td width="5%" valign="top"></td>
 *     <td width="8%" valign="top">x.x:</td>
 *     <td valign="top">The rule is an <em>improper fraction rule</em>. If the full stop in
 *     the middle of the rule name is replaced with the decimal point
 *     that is used in the language or DecimalFormatSymbols, then that rule will
 *     have precedence when formatting and parsing this rule. For example, some
 *     languages use the comma, and can thus be written as x,x instead. For example,
 *     you can use "x.x: &lt;&lt; point &gt;&gt;;x,x: &lt;&lt; comma &gt;&gt;;" to
 *     handle the decimal point that matches the language's natural spelling of
 *     the punctuation of either the full stop or comma.</td>
 *   </tr>
 *   <tr>
 *     <td width="5%" valign="top"></td>
 *     <td width="8%" valign="top">0.x:</td>
 *     <td valign="top">The rule is a <em>proper fraction rule</em>. If the full stop in
 *     the middle of the rule name is replaced with the decimal point
 *     that is used in the language or DecimalFormatSymbols, then that rule will
 *     have precedence when formatting and parsing this rule. For example, some
 *     languages use the comma, and can thus be written as 0,x instead. For example,
 *     you can use "0.x: point &gt;&gt;;0,x: comma &gt;&gt;;" to
 *     handle the decimal point that matches the language's natural spelling of
 *     the punctuation of either the full stop or comma</td>
 *   </tr>
 *   <tr>
 *     <td width="5%" valign="top"></td>
 *     <td width="8%" valign="top">x.0:</td>
 *     <td valign="top">The rule is a <em>master rule</em>. If the full stop in
 *     the middle of the rule name is replaced with the decimal point
 *     that is used in the language or DecimalFormatSymbols, then that rule will
 *     have precedence when formatting and parsing this rule. For example, some
 *     languages use the comma, and can thus be written as x,0 instead. For example,
 *     you can use "x.0: &lt;&lt; point;x,0: &lt;&lt; comma;" to
 *     handle the decimal point that matches the language's natural spelling of
 *     the punctuation of either the full stop or comma</td>
 *   </tr>
 *   <tr>
 *     <td width="5%" valign="top"></td>
 *     <td width="8%" valign="top">Inf:</td>
 *     <td valign="top">The rule for infinity.</td>
 *   </tr>
 *   <tr>
 *     <td width="5%" valign="top"></td>
 *     <td width="8%" valign="top">NaN:</td>
 *     <td valign="top">The rule for an IEEE 754 NaN (not a number).</td>
 *   </tr>
 *   <tr>
 *     <td width="5%" valign="top"></td>
 *     <td width="8%" valign="top"><em>nothing</em></td>
 *     <td valign="top">If the rule's rule descriptor is left out, the base value is one plus the
 *     preceding rule's base value (or zero if this is the first rule in the list) in a normal
 *     rule set.&nbsp; In a fraction rule set, the base value is the same as the preceding rule's
 *     base value.</td>
 *   </tr>
 * </table>
 *
 * <p>A rule set may be either a regular rule set or a <em>fraction rule set,</em> depending
 * on whether it is used to format a number's integral part (or the whole number) or a
 * number's fractional part. Using a rule set to format a rule's fractional part makes it a
 * fraction rule set.</p>
 *
 * <p>Which rule is used to format a number is defined according to one of the following
 * algorithms: If the rule set is a regular rule set, do the following:
 *
 * <ul>
 *   <li>If the rule set includes a master rule (and the number was passed in as a <tt>double</tt>),
 *     use the master rule.&nbsp; (If the number being formatted was passed in as a <tt>long</tt>,
 *     the master rule is ignored.)</li>
 *   <li>If the number is negative, use the negative-number rule.</li>
 *   <li>If the number has a fractional part and is greater than 1, use the improper fraction
 *     rule.</li>
 *   <li>If the number has a fractional part and is between 0 and 1, use the proper fraction
 *     rule.</li>
 *   <li>Binary-search the rule list for the rule with the highest base value less than or equal
 *     to the number. If that rule has two substitutions, its base value is not an even multiple
 *     of its divisor, and the number <em>is</em> an even multiple of the rule's divisor, use the
 *     rule that precedes it in the rule list. Otherwise, use the rule itself.</li>
 * </ul>
 *
 * <p>If the rule set is a fraction rule set, do the following:
 *
 * <ul>
 *   <li>Ignore negative-number and fraction rules.</li>
 *   <li>For each rule in the list, multiply the number being formatted (which will always be
 *     between 0 and 1) by the rule's base value. Keep track of the distance between the result
 *     the nearest integer.</li>
 *   <li>Use the rule that produced the result closest to zero in the above calculation. In the
 *     event of a tie or a direct hit, use the first matching rule encountered. (The idea here is
 *     to try each rule's base value as a possible denominator of a fraction. Whichever
 *     denominator produces the fraction closest in value to the number being formatted wins.) If
 *     the rule following the matching rule has the same base value, use it if the numerator of
 *     the fraction is anything other than 1; if the numerator is 1, use the original matching
 *     rule. (This is to allow singular and plural forms of the rule text without a lot of extra
 *     hassle.)</li>
 * </ul>
 *
 * <p>A rule's body consists of a string of characters terminated by a semicolon. The rule
 * may include zero, one, or two <em>substitution tokens,</em> and a range of text in
 * brackets. The brackets denote optional text (and may also include one or both
 * substitutions). The exact meanings of the substitution tokens, and under what conditions
 * optional text is omitted, depend on the syntax of the substitution token and the context.
 * The rest of the text in a rule body is literal text that is output when the rule matches
 * the number being formatted.</p>
 *
 * <p>A substitution token begins and ends with a <em>token character.</em> The token
 * character and the context together specify a mathematical operation to be performed on the
 * number being formatted. An optional <em>substitution descriptor </em>specifies how the
 * value resulting from that operation is used to fill in the substitution. The position of
 * the substitution token in the rule body specifies the location of the resultant text in
 * the original rule text.</p>
 *
 * <p>The meanings of the substitution token characters are as follows:</p>
 *
 * <table border="0" width="100%">
 *   <tr>
 *     <td width="37"></td>
 *     <td width="23">&gt;&gt;</td>
 *     <td width="165" valign="top">in normal rule</td>
 *     <td>Divide the number by the rule's divisor and format the remainder</td>
 *   </tr>
 *   <tr>
 *     <td width="37"></td>
 *     <td width="23"></td>
 *     <td width="165" valign="top">in negative-number rule</td>
 *     <td>Find the absolute value of the number and format the result</td>
 *   </tr>
 *   <tr>
 *     <td width="37"></td>
 *     <td width="23"></td>
 *     <td width="165" valign="top">in fraction or master rule</td>
 *     <td>Isolate the number's fractional part and format it.</td>
 *   </tr>
 *   <tr>
 *     <td width="37"></td>
 *     <td width="23"></td>
 *     <td width="165" valign="top">in rule in fraction rule set</td>
 *     <td>Not allowed.</td>
 *   </tr>
 *   <tr>
 *     <td width="37"></td>
 *     <td width="23">&gt;&gt;&gt;</td>
 *     <td width="165" valign="top">in normal rule</td>
 *     <td>Divide the number by the rule's divisor and format the remainder,
 *       but bypass the normal rule-selection process and just use the
 *       rule that precedes this one in this rule list.</td>
 *   </tr>
 *   <tr>
 *     <td width="37"></td>
 *     <td width="23"></td>
 *     <td width="165" valign="top">in all other rules</td>
 *     <td>Not allowed.</td>
 *   </tr>
 *   <tr>
 *     <td width="37"></td>
 *     <td width="23">&lt;&lt;</td>
 *     <td width="165" valign="top">in normal rule</td>
 *     <td>Divide the number by the rule's divisor and format the quotient</td>
 *   </tr>
 *   <tr>
 *     <td width="37"></td>
 *     <td width="23"></td>
 *     <td width="165" valign="top">in negative-number rule</td>
 *     <td>Not allowed.</td>
 *   </tr>
 *   <tr>
 *     <td width="37"></td>
 *     <td width="23"></td>
 *     <td width="165" valign="top">in fraction or master rule</td>
 *     <td>Isolate the number's integral part and format it.</td>
 *   </tr>
 *   <tr>
 *     <td width="37"></td>
 *     <td width="23"></td>
 *     <td width="165" valign="top">in rule in fraction rule set</td>
 *     <td>Multiply the number by the rule's base value and format the result.</td>
 *   </tr>
 *   <tr>
 *     <td width="37"></td>
 *     <td width="23">==</td>
 *     <td width="165" valign="top">in all rule sets</td>
 *     <td>Format the number unchanged</td>
 *   </tr>
 *   <tr>
 *     <td width="37"></td>
 *     <td width="23">[]</td>
 *     <td width="165" valign="top">in normal rule</td>
 *     <td>Omit the optional text if the number is an even multiple of the rule's divisor</td>
 *   </tr>
 *   <tr>
 *     <td width="37"></td>
 *     <td width="23"></td>
 *     <td width="165" valign="top">in negative-number rule</td>
 *     <td>Not allowed.</td>
 *   </tr>
 *   <tr>
 *     <td width="37"></td>
 *     <td width="23"></td>
 *     <td width="165" valign="top">in improper-fraction rule</td>
 *     <td>Omit the optional text if the number is between 0 and 1 (same as specifying both an
 *     x.x rule and a 0.x rule)</td>
 *   </tr>
 *   <tr>
 *     <td width="37"></td>
 *     <td width="23"></td>
 *     <td width="165" valign="top">in master rule</td>
 *     <td>Omit the optional text if the number is an integer (same as specifying both an x.x
 *     rule and an x.0 rule)</td>
 *   </tr>
 *   <tr>
 *     <td width="37"></td>
 *     <td width="23"></td>
 *     <td width="165" valign="top">in proper-fraction rule</td>
 *     <td>Not allowed.</td>
 *   </tr>
 *   <tr>
 *     <td width="37"></td>
 *     <td width="23"></td>
 *     <td width="165" valign="top">in rule in fraction rule set</td>
 *     <td>Omit the optional text if multiplying the number by the rule's base value yields 1.</td>
 *   </tr>
 *   <tr>
 *     <td width="37">$(cardinal,<i>plural syntax</i>)$</td>
 *     <td width="23"></td>
 *     <td width="165" valign="top">in all rule sets</td>
 *     <td>This provides the ability to choose a word based on the number divided by the radix to the power of the
 *     exponent of the base value for the specified locale, which is normally equivalent to the &lt;&lt; value.
 *     This uses the cardinal plural rules from PluralFormat. All strings used in the plural format are treated
 *     as the same base value for parsing.</td>
 *   </tr>
 *   <tr>
 *     <td width="37">$(ordinal,<i>plural syntax</i>)$</td>
 *     <td width="23"></td>
 *     <td width="165" valign="top">in all rule sets</td>
 *     <td>This provides the ability to choose a word based on the number divided by the radix to the power of the
 *     exponent of the base value for the specified locale, which is normally equivalent to the &lt;&lt; value.
 *     This uses the ordinal plural rules from PluralFormat. All strings used in the plural format are treated
 *     as the same base value for parsing.</td>
 *   </tr>
 * </table>
 *
 * <p>The substitution descriptor (i.e., the text between the token characters) may take one
 * of three forms:</p>
 *
 * <table border="0" width="100%">
 *   <tr>
 *     <td width="42"></td>
 *     <td width="166" valign="top">a rule set name</td>
 *     <td>Perform the mathematical operation on the number, and format the result using the
 *     named rule set.</td>
 *   </tr>
 *   <tr>
 *     <td width="42"></td>
 *     <td width="166" valign="top">a DecimalFormat pattern</td>
 *     <td>Perform the mathematical operation on the number, and format the result using a
 *     DecimalFormat with the specified pattern.&nbsp; The pattern must begin with 0 or #.</td>
 *   </tr>
 *   <tr>
 *     <td width="42"></td>
 *     <td width="166" valign="top">nothing</td>
 *     <td>Perform the mathematical operation on the number, and format the result using the rule
 *     set containing the current rule, except:<ul>
 *       <li>You can't have an empty substitution descriptor with a == substitution.</li>
 *       <li>If you omit the substitution descriptor in a &gt;&gt; substitution in a fraction rule,
 *         format the result one digit at a time using the rule set containing the current rule.</li>
 *       <li>If you omit the substitution descriptor in a &lt;&lt; substitution in a rule in a
 *         fraction rule set, format the result using the default rule set for this formatter.</li>
 *     </ul>
 *     </td>
 *   </tr>
 * </table>
 *
 * <p>Whitespace is ignored between a rule set name and a rule set body, between a rule
 * descriptor and a rule body, or between rules. If a rule body begins with an apostrophe,
 * the apostrophe is ignored, but all text after it becomes significant (this is how you can
 * have a rule's rule text begin with whitespace). There is no escape function: the semicolon
 * is not allowed in rule set names or in rule text, and the colon is not allowed in rule set
 * names. The characters beginning a substitution token are always treated as the beginning
 * of a substitution token.</p>
 *
 * <p>See the resource data and the demo program for annotated examples of real rule sets
 * using these features.</p>
 *
 * @author Richard Gillam
 * @see NumberFormat
 * @see DecimalFormat
 * @see PluralFormat
 * @see PluralRules
 * @stable ICU 2.0
 */
public class RuleBasedNumberFormat extends NumberFormat {

    //-----------------------------------------------------------------------
    // constants
    //-----------------------------------------------------------------------

    // Generated by serialver from JDK 1.4.1_01
    static final long serialVersionUID = -7664252765575395068L;

    /**
     * Selector code that tells the constructor to create a spellout formatter
     * @stable ICU 2.0
     */
    public static final int SPELLOUT = 1;

    /**
     * Selector code that tells the constructor to create an ordinal formatter
     * @stable ICU 2.0
     */
    public static final int ORDINAL = 2;

    /**
     * Selector code that tells the constructor to create a duration formatter
     * @stable ICU 2.0
     */
    public static final int DURATION = 3;

    /**
     * Selector code that tells the constructor to create a numbering system formatter
     * @stable ICU 4.2
     */
    public static final int NUMBERING_SYSTEM = 4;

    //-----------------------------------------------------------------------
    // data members
    //-----------------------------------------------------------------------

    /**
     * The formatter's rule sets.
     */
    private transient NFRuleSet[] ruleSets = null;

    /**
     * The formatter's rule names mapped to rule sets.
     */
    private transient Map<String, NFRuleSet> ruleSetsMap = null;

    /**
     * A pointer to the formatter's default rule set.  This is always included
     * in ruleSets.
     */
    private transient NFRuleSet defaultRuleSet = null;

    /**
     * The formatter's locale.  This is used to create DecimalFormatSymbols and
     * Collator objects.
     * @serial
     */
    private ULocale locale = null;

    /**
     * The formatter's rounding mode.
     * @serial
     */
    private int roundingMode = BigDecimal.ROUND_UNNECESSARY;

    /**
     * Collator to be used in lenient parsing.  This variable is lazy-evaluated:
     * the collator is actually created the first time the client does a parse
     * with lenient-parse mode turned on.
     */
    private transient RbnfLenientScannerProvider scannerProvider = null;

    // flag to mark whether we've previously looked for a scanner and failed
    private transient boolean lookedForScanner;

    /**
     * The DecimalFormatSymbols object that any DecimalFormat objects this
     * formatter uses should use.  This variable is lazy-evaluated: it isn't
     * filled in if the rule set never uses a DecimalFormat pattern.
     */
    private transient DecimalFormatSymbols decimalFormatSymbols = null;

    /**
     * The NumberFormat used when lenient parsing numbers.  This needs to reflect
     * the locale.  This is lazy-evaluated, like decimalFormatSymbols.  It is
     * here so it can be shared by different NFSubstitutions.
     */
    private transient DecimalFormat decimalFormat = null;

    /**
     * The rule used when dealing with infinity. This is lazy-evaluated, and derived from decimalFormat.
     * It is here so it can be shared by different NFRuleSets.
     */
    private transient NFRule defaultInfinityRule = null;

    /**
     * The rule used when dealing with IEEE 754 NaN. This is lazy-evaluated, and derived from decimalFormat.
     * It is here so it can be shared by different NFRuleSets.
     */
    private transient NFRule defaultNaNRule = null;

    /**
     * Flag specifying whether lenient parse mode is on or off.  Off by default.
     * @serial
     */
    private boolean lenientParse = false;

    /**
     * If the description specifies lenient-parse rules, they're stored here until
     * the collator is created.
     */
    private transient String lenientParseRules;

    /**
     * If the description specifies post-process rules, they're stored here until
     * post-processing is required.
     */
    private transient String postProcessRules;

    /**
     * Post processor lazily constructed from the postProcessRules.
     */
    private transient RBNFPostProcessor postProcessor;

    /**
     * Localizations for rule set names.
     * @serial
     */
    private Map<String, String[]> ruleSetDisplayNames;

    /**
     * The public rule set names;
     * @serial
     */
    private String[] publicRuleSetNames;

    /**
     * Data for handling context-based capitalization
     */
    private boolean capitalizationInfoIsSet = false;
    private boolean capitalizationForListOrMenu = false;
    private boolean capitalizationForStandAlone = false;
    private transient BreakIterator capitalizationBrkIter = null;


    private static final boolean DEBUG  =  ICUDebug.enabled("rbnf");

    //-----------------------------------------------------------------------
    // constructors
    //-----------------------------------------------------------------------

    /**
     * Creates a RuleBasedNumberFormat that behaves according to the description
     * passed in.  The formatter uses the default <code>FORMAT</code> locale.
     * @param description A description of the formatter's desired behavior.
     * See the class documentation for a complete explanation of the description
     * syntax.
     * @see Category#FORMAT
     * @stable ICU 2.0
     */
    public RuleBasedNumberFormat(String description) {
        locale = ULocale.getDefault(Category.FORMAT);
        init(description, null);
    }

    /**
     * Creates a RuleBasedNumberFormat that behaves according to the description
     * passed in.  The formatter uses the default <code>FORMAT</code> locale.
     * <p>
     * The localizations data provides information about the public
     * rule sets and their localized display names for different
     * locales. The first element in the list is an array of the names
     * of the public rule sets.  The first element in this array is
     * the initial default ruleset.  The remaining elements in the
     * list are arrays of localizations of the names of the public
     * rule sets.  Each of these is one longer than the initial array,
     * with the first String being the ULocale ID, and the remaining
     * Strings being the localizations of the rule set names, in the
     * same order as the initial array.
     * @param description A description of the formatter's desired behavior.
     * See the class documentation for a complete explanation of the description
     * syntax.
     * @param localizations a list of localizations for the rule set
     * names in the description.
     * @see Category#FORMAT
     * @stable ICU 3.2
     */
    public RuleBasedNumberFormat(String description, String[][] localizations) {
        locale = ULocale.getDefault(Category.FORMAT);
        init(description, localizations);
    }

    /**
     * Creates a RuleBasedNumberFormat that behaves according to the description
     * passed in.  The formatter uses the specified locale to determine the
     * characters to use when formatting in numerals, and to define equivalences
     * for lenient parsing.
     * @param description A description of the formatter's desired behavior.
     * See the class documentation for a complete explanation of the description
     * syntax.
     * @param locale A locale, which governs which characters are used for
     * formatting values in numerals, and which characters are equivalent in
     * lenient parsing.
     * @stable ICU 2.0
     */
    public RuleBasedNumberFormat(String description, Locale locale) {
        this(description, ULocale.forLocale(locale));
    }

    /**
     * Creates a RuleBasedNumberFormat that behaves according to the description
     * passed in.  The formatter uses the specified locale to determine the
     * characters to use when formatting in numerals, and to define equivalences
     * for lenient parsing.
     * @param description A description of the formatter's desired behavior.
     * See the class documentation for a complete explanation of the description
     * syntax.
     * @param locale A locale, which governs which characters are used for
     * formatting values in numerals, and which characters are equivalent in
     * lenient parsing.
     * @stable ICU 3.2
     */
    public RuleBasedNumberFormat(String description, ULocale locale) {
        this.locale = locale;
        init(description, null);
    }

    /**
     * Creates a RuleBasedNumberFormat that behaves according to the description
     * passed in.  The formatter uses the specified locale to determine the
     * characters to use when formatting in numerals, and to define equivalences
     * for lenient parsing.
     * <p>
     * The localizations data provides information about the public
     * rule sets and their localized display names for different
     * locales. The first element in the list is an array of the names
     * of the public rule sets.  The first element in this array is
     * the initial default ruleset.  The remaining elements in the
     * list are arrays of localizations of the names of the public
     * rule sets.  Each of these is one longer than the initial array,
     * with the first String being the ULocale ID, and the remaining
     * Strings being the localizations of the rule set names, in the
     * same order as the initial array.
     * @param description A description of the formatter's desired behavior.
     * See the class documentation for a complete explanation of the description
     * syntax.
     * @param localizations a list of localizations for the rule set names in the description.
     * @param locale A ULocale that governs which characters are used for
     * formatting values in numerals, and determines which characters are equivalent in
     * lenient parsing.
     * @stable ICU 3.2
     */
    public RuleBasedNumberFormat(String description, String[][] localizations, ULocale locale) {
        this.locale = locale;
        init(description, localizations);
    }

    /**
     * Creates a RuleBasedNumberFormat from a predefined description.  The selector
     * code chooses among three possible predefined formats: spellout, ordinal,
     * and duration.
     * @param locale The locale for the formatter.
     * @param format A selector code specifying which kind of formatter to create for that
     * locale.  There are three legal values: SPELLOUT, which creates a formatter that
     * spells out a value in words in the desired language, ORDINAL, which attaches
     * an ordinal suffix from the desired language to the end of a number (e.g. "123rd"),
     * and DURATION, which formats a duration in seconds as hours, minutes, and seconds.
     * @stable ICU 2.0
     */
    public RuleBasedNumberFormat(Locale locale, int format) {
        this(ULocale.forLocale(locale), format);
    }

    /**
     * Creates a RuleBasedNumberFormat from a predefined description.  The selector
     * code chooses among three possible predefined formats: spellout, ordinal,
     * and duration.
     * @param locale The locale for the formatter.
     * @param format A selector code specifying which kind of formatter to create for that
     * locale.  There are four legal values: SPELLOUT, which creates a formatter that
     * spells out a value in words in the desired language, ORDINAL, which attaches
     * an ordinal suffix from the desired language to the end of a number (e.g. "123rd"),
     * DURATION, which formats a duration in seconds as hours, minutes, and seconds, and
     * NUMBERING_SYSTEM, which is used to invoke rules for alternate numbering
     * systems such as the Hebrew numbering system, or for Roman numerals, etc..
     * @stable ICU 3.2
     */
    public RuleBasedNumberFormat(ULocale locale, int format) {
        this.locale = locale;

        ICUResourceBundle bundle = (ICUResourceBundle)UResourceBundle.
            getBundleInstance(ICUResourceBundle.ICU_RBNF_BASE_NAME, locale);

        // TODO: determine correct actual/valid locale.  Note ambiguity
        // here -- do actual/valid refer to pattern, DecimalFormatSymbols,
        // or Collator?
        ULocale uloc = bundle.getULocale();
        setLocale(uloc, uloc);

        StringBuilder description = new StringBuilder();
        String[][] localizations = null;

        try {
            ICUResourceBundle rules = bundle.getWithFallback("RBNFRules/"+rulenames[format-1]);
            UResourceBundleIterator it = rules.getIterator();
            while (it.hasNext()) {
               description.append(it.nextString());
            }
        }
        catch (MissingResourceException e1) {
        }

        // We use findTopLevel() instead of get() because
        // it's faster when we know that it's usually going to fail.
        UResourceBundle locNamesBundle = bundle.findTopLevel(locnames[format - 1]);
        if (locNamesBundle != null) {
            localizations = new String[locNamesBundle.getSize()][];
            for (int i = 0; i < localizations.length; ++i) {
                localizations[i] = locNamesBundle.get(i).getStringArray();
            }
        }
        // else there are no localized names. It's not that important.

        init(description.toString(), localizations);
    }

    private static final String[] rulenames = {
        "SpelloutRules", "OrdinalRules", "DurationRules", "NumberingSystemRules",
    };
    private static final String[] locnames = {
        "SpelloutLocalizations", "OrdinalLocalizations", "DurationLocalizations", "NumberingSystemLocalizations",
    };

    /**
     * Creates a RuleBasedNumberFormat from a predefined description.  Uses the
     * default <code>FORMAT</code> locale.
     * @param format A selector code specifying which kind of formatter to create.
     * There are three legal values: SPELLOUT, which creates a formatter that spells
     * out a value in words in the default locale's language, ORDINAL, which attaches
     * an ordinal suffix from the default locale's language to a numeral, and
     * DURATION, which formats a duration in seconds as hours, minutes, and seconds always rounding down.
     * or NUMBERING_SYSTEM, which is used for alternate numbering systems such as Hebrew.
     * @see Category#FORMAT
     * @stable ICU 2.0
     */
    public RuleBasedNumberFormat(int format) {
        this(ULocale.getDefault(Category.FORMAT), format);
    }

    //-----------------------------------------------------------------------
    // boilerplate
    //-----------------------------------------------------------------------

    /**
     * Duplicates this formatter.
     * @return A RuleBasedNumberFormat that is equal to this one.
     * @stable ICU 2.0
     */
    public Object clone() {
        return super.clone();
    }

    /**
     * Tests two RuleBasedNumberFormats for equality.
     * @param that The formatter to compare against this one.
     * @return true if the two formatters have identical behavior.
     * @stable ICU 2.0
     */
    public boolean equals(Object that) {
        // if the other object isn't a RuleBasedNumberFormat, that's
        // all we need to know
        // Test for capitalization info equality is adequately handled
        // by the NumberFormat test for capitalizationSetting equality;
        // the info here is just derived from that.
        if (!(that instanceof RuleBasedNumberFormat)) {
            return false;
        } else {
            // cast the other object's pointer to a pointer to a
            // RuleBasedNumberFormat
            RuleBasedNumberFormat that2 = (RuleBasedNumberFormat)that;

            // compare their locales and lenient-parse modes
            if (!locale.equals(that2.locale) || lenientParse != that2.lenientParse) {
                return false;
            }

            // if that succeeds, then compare their rule set lists
            if (ruleSets.length != that2.ruleSets.length) {
                return false;
            }
            for (int i = 0; i < ruleSets.length; i++) {
                if (!ruleSets[i].equals(that2.ruleSets[i])) {
                    return false;
                }
            }

            return true;
        }
    }
    
    /**
     * Mock implementation of hashCode(). This implementation always returns a constant
     * value. When Java assertion is enabled, this method triggers an assertion failure.
     * @internal
     * @deprecated This API is ICU internal only.
     */
    @Deprecated
    public int hashCode() {
        return super.hashCode();
    }

    /**
     * Generates a textual description of this formatter.
     * @return a String containing a rule set that will produce a RuleBasedNumberFormat
     * with identical behavior to this one.  This won't necessarily be identical
     * to the rule set description that was originally passed in, but will produce
     * the same result.
     * @stable ICU 2.0
     */
    public String toString() {

        // accumulate the descriptions of all the rule sets in a
        // StringBuffer, then cast it to a String and return it
        StringBuilder result = new StringBuilder();
        for (NFRuleSet ruleSet : ruleSets) {
            result.append(ruleSet.toString());
        }
        return result.toString();
    }

    /**
     * Writes this object to a stream.
     * @param out The stream to write to.
     */
    private void writeObject(java.io.ObjectOutputStream out)
        throws java.io.IOException {
        // we just write the textual description to the stream, so we
        // have an implementation-independent streaming format
        out.writeUTF(this.toString());
        out.writeObject(this.locale);
        out.writeInt(this.roundingMode);
    }

    /**
     * Reads this object in from a stream.
     * @param in The stream to read from.
     */
    private void readObject(java.io.ObjectInputStream in)
        throws java.io.IOException {

        // read the description in from the stream
        String description = in.readUTF();
        ULocale loc;

        try {
            loc = (ULocale) in.readObject();
        } catch (Exception e) {
            loc = ULocale.getDefault(Category.FORMAT);
        }
        try {
            roundingMode = in.readInt();
        } catch (Exception ignored) {
        }

        // build a brand-new RuleBasedNumberFormat from the description,
        // then steal its substructure.  This object's substructure and
        // the temporary RuleBasedNumberFormat drop on the floor and
        // get swept up by the garbage collector
        RuleBasedNumberFormat temp = new RuleBasedNumberFormat(description, loc);
        ruleSets = temp.ruleSets;
        ruleSetsMap = temp.ruleSetsMap;
        defaultRuleSet = temp.defaultRuleSet;
        publicRuleSetNames = temp.publicRuleSetNames;
        decimalFormatSymbols = temp.decimalFormatSymbols;
        decimalFormat = temp.decimalFormat;
        locale = temp.locale;
        defaultInfinityRule = temp.defaultInfinityRule;
        defaultNaNRule = temp.defaultNaNRule;
    }


    //-----------------------------------------------------------------------
    // public API functions
    //-----------------------------------------------------------------------

    /**
     * Returns a list of the names of all of this formatter's public rule sets.
     * @return A list of the names of all of this formatter's public rule sets.
     * @stable ICU 2.0
     */
    public String[] getRuleSetNames() {
        return publicRuleSetNames.clone();
    }

    /**
     * Return a list of locales for which there are locale-specific display names
     * for the rule sets in this formatter.  If there are no localized display names, return null.
     * @return an array of the ULocales for which there is rule set display name information
     * @stable ICU 3.2
     */
    public ULocale[] getRuleSetDisplayNameLocales() {
        if (ruleSetDisplayNames != null) {
            Set<String> s = ruleSetDisplayNames.keySet();
            String[] locales = s.toArray(new String[s.size()]);
            Arrays.sort(locales, String.CASE_INSENSITIVE_ORDER);
            ULocale[] result = new ULocale[locales.length];
            for (int i = 0; i < locales.length; ++i) {
                result[i] = new ULocale(locales[i]);
            }
            return result;
        }
        return null;
    }

    private String[] getNameListForLocale(ULocale loc) {
        if (loc != null && ruleSetDisplayNames != null) {
            String[] localeNames = { loc.getBaseName(), ULocale.getDefault(Category.DISPLAY).getBaseName() };
            for (String lname : localeNames) {
                while (lname.length() > 0) {
                    String[] names = ruleSetDisplayNames.get(lname);
                    if (names != null) {
                        return names;
                    }
                    lname = ULocale.getFallback(lname);
                }
            }
        }
        return null;
    }

    /**
     * Return the rule set display names for the provided locale.  These are in the same order
     * as those returned by getRuleSetNames.  The locale is matched against the locales for
     * which there is display name data, using normal fallback rules.  If no locale matches,
     * the default display names are returned.  (These are the internal rule set names minus
     * the leading '%'.)
     * @return an array of the locales that have display name information
     * @see #getRuleSetNames
     * @stable ICU 3.2
     */
    public String[] getRuleSetDisplayNames(ULocale loc) {
        String[] names = getNameListForLocale(loc);
        if (names != null) {
            return names.clone();
        }
        names = getRuleSetNames();
        for (int i = 0; i < names.length; ++i) {
            names[i] = names[i].substring(1);
        }
        return names;
    }

    /**
     * Return the rule set display names for the current default <code>DISPLAY</code> locale.
     * @return an array of the display names
     * @see #getRuleSetDisplayNames(ULocale)
     * @see Category#DISPLAY
     * @stable ICU 3.2
     */
    public String[] getRuleSetDisplayNames() {
        return getRuleSetDisplayNames(ULocale.getDefault(Category.DISPLAY));
    }

    /**
     * Return the rule set display name for the provided rule set and locale.
     * The locale is matched against the locales for which there is display name data, using
     * normal fallback rules.  If no locale matches, the default display name is returned.
     * @return the display name for the rule set
     * @see #getRuleSetDisplayNames
     * @throws IllegalArgumentException if ruleSetName is not a valid rule set name for this format
     * @stable ICU 3.2
     */
    public String getRuleSetDisplayName(String ruleSetName, ULocale loc) {
        String[] rsnames = publicRuleSetNames;
        for (int ix = 0; ix < rsnames.length; ++ix) {
            if (rsnames[ix].equals(ruleSetName)) {
                String[] names = getNameListForLocale(loc);
                if (names != null) {
                    return names[ix];
                }
                return rsnames[ix].substring(1);
            }
        }
        throw new IllegalArgumentException("unrecognized rule set name: " + ruleSetName);
    }

    /**
     * Return the rule set display name for the provided rule set in the current default <code>DISPLAY</code> locale.
     * @return the display name for the rule set
     * @see #getRuleSetDisplayName(String,ULocale)
     * @see Category#DISPLAY
     * @stable ICU 3.2
     */
    public String getRuleSetDisplayName(String ruleSetName) {
        return getRuleSetDisplayName(ruleSetName, ULocale.getDefault(Category.DISPLAY));
    }

    /**
     * Formats the specified number according to the specified rule set.
     * @param number The number to format.
     * @param ruleSet The name of the rule set to format the number with.
     * This must be the name of a valid public rule set for this formatter.
     * @return A textual representation of the number.
     * @stable ICU 2.0
     */
    public String format(double number, String ruleSet) throws IllegalArgumentException {
        if (ruleSet.startsWith("%%")) {
            throw new IllegalArgumentException("Can't use internal rule set");
        }
        return adjustForContext(format(number, findRuleSet(ruleSet)));
    }

    /**
     * Formats the specified number according to the specified rule set.
     * (If the specified rule set specifies a master ["x.0"] rule, this function
     * ignores it.  Convert the number to a double first if you ned it.)  This
     * function preserves all the precision in the long-- it doesn't convert it
     * to a double.
     * @param number The number to format.
     * @param ruleSet The name of the rule set to format the number with.
     * This must be the name of a valid public rule set for this formatter.
     * @return A textual representation of the number.
     * @stable ICU 2.0
     */
    public String format(long number, String ruleSet) throws IllegalArgumentException {
        if (ruleSet.startsWith("%%")) {
            throw new IllegalArgumentException("Can't use internal rule set");
        }
        return adjustForContext(format(number, findRuleSet(ruleSet)));
    }

    /**
     * Formats the specified number using the formatter's default rule set.
     * (The default rule set is the last public rule set defined in the description.)
     * @param number The number to format.
     * @param toAppendTo A StringBuffer that the result should be appended to.
     * @param ignore This function doesn't examine or update the field position.
     * @return toAppendTo
     * @stable ICU 2.0
     */
    public StringBuffer format(double number,
                               StringBuffer toAppendTo,
                               FieldPosition ignore) {
        // this is one of the inherited format() methods.  Since it doesn't
        // have a way to select the rule set to use, it just uses the
        // default one
        // Note, the BigInteger/BigDecimal methods below currently go through this.
        if (toAppendTo.length() == 0) {
            toAppendTo.append(adjustForContext(format(number, defaultRuleSet)));
        } else {
            // appending to other text, don't capitalize
            toAppendTo.append(format(number, defaultRuleSet));
        }
        return toAppendTo;
    }

    /**
     * Formats the specified number using the formatter's default rule set.
     * (The default rule set is the last public rule set defined in the description.)
     * (If the specified rule set specifies a master ["x.0"] rule, this function
     * ignores it.  Convert the number to a double first if you ned it.)  This
     * function preserves all the precision in the long-- it doesn't convert it
     * to a double.
     * @param number The number to format.
     * @param toAppendTo A StringBuffer that the result should be appended to.
     * @param ignore This function doesn't examine or update the field position.
     * @return toAppendTo
     * @stable ICU 2.0
     */
    public StringBuffer format(long number,
                               StringBuffer toAppendTo,
                               FieldPosition ignore) {
        // this is one of the inherited format() methods.  Since it doesn't
        // have a way to select the rule set to use, it just uses the
        // default one
        if (toAppendTo.length() == 0) {
            toAppendTo.append(adjustForContext(format(number, defaultRuleSet)));
        } else {
            // appending to other text, don't capitalize
            toAppendTo.append(format(number, defaultRuleSet));
        }
        return toAppendTo;
    }

    /**
     * <strong><font face=helvetica color=red>NEW</font></strong>
     * Implement com.ibm.icu.text.NumberFormat:
     * Format a BigInteger.
     * @stable ICU 2.0
     */
    public StringBuffer format(BigInteger number,
                               StringBuffer toAppendTo,
                               FieldPosition pos) {
        return format(new com.ibm.icu.math.BigDecimal(number), toAppendTo, pos);
    }

    /**
     * <strong><font face=helvetica color=red>NEW</font></strong>
     * Implement com.ibm.icu.text.NumberFormat:
     * Format a BigDecimal.
     * @stable ICU 2.0
     */
    public StringBuffer format(java.math.BigDecimal number,
                               StringBuffer toAppendTo,
                               FieldPosition pos) {
        return format(new com.ibm.icu.math.BigDecimal(number), toAppendTo, pos);
    }

    /**
     * <strong><font face=helvetica color=red>NEW</font></strong>
     * Implement com.ibm.icu.text.NumberFormat:
     * Format a BigDecimal.
     * @stable ICU 2.0
     */
    public StringBuffer format(com.ibm.icu.math.BigDecimal number,
                               StringBuffer toAppendTo,
                               FieldPosition pos) {
        // TEMPORARY:
        return format(number.doubleValue(), toAppendTo, pos);
    }

    /**
     * Parses the specified string, beginning at the specified position, according
     * to this formatter's rules.  This will match the string against all of the
     * formatter's public rule sets and return the value corresponding to the longest
     * parseable substring.  This function's behavior is affected by the lenient
     * parse mode.
     * @param text The string to parse
     * @param parsePosition On entry, contains the position of the first character
     * in "text" to examine.  On exit, has been updated to contain the position
     * of the first character in "text" that wasn't consumed by the parse.
     * @return The number that corresponds to the parsed text.  This will be an
     * instance of either Long or Double, depending on whether the result has a
     * fractional part.
     * @see #setLenientParseMode
     * @stable ICU 2.0
     */
    public Number parse(String text, ParsePosition parsePosition) {

        // parsePosition tells us where to start parsing.  We copy the
        // text in the string from here to the end inro a new string,
        // and create a new ParsePosition and result variable to use
        // for the duration of the parse operation
        String workingText = text.substring(parsePosition.getIndex());
        ParsePosition workingPos = new ParsePosition(0);
        Number tempResult = null;

        // keep track of the largest number of characters consumed in
        // the various trials, and the result that corresponds to it
        Number result = NFRule.ZERO;
        ParsePosition highWaterMark = new ParsePosition(workingPos.getIndex());

        // iterate over the public rule sets (beginning with the default one)
        // and try parsing the text with each of them.  Keep track of which
        // one consumes the most characters: that's the one that determines
        // the result we return
        for (int i = ruleSets.length - 1; i >= 0; i--) {
            // skip private or unparseable rule sets
            if (!ruleSets[i].isPublic() || !ruleSets[i].isParseable()) {
                continue;
            }

            // try parsing the string with the rule set.  If it gets past the
            // high-water mark, update the high-water mark and the result
            tempResult = ruleSets[i].parse(workingText, workingPos, Double.MAX_VALUE);
            if (workingPos.getIndex() > highWaterMark.getIndex()) {
                result = tempResult;
                highWaterMark.setIndex(workingPos.getIndex());
            }
            // commented out because this API on ParsePosition doesn't exist in 1.1.x
            //            if (workingPos.getErrorIndex() > highWaterMark.getErrorIndex()) {
            //                highWaterMark.setErrorIndex(workingPos.getErrorIndex());
            //            }

            // if we manage to use up all the characters in the string,
            // we don't have to try any more rule sets
            if (highWaterMark.getIndex() == workingText.length()) {
                break;
            }

            // otherwise, reset our internal parse position to the
            // beginning and try again with the next rule set
            workingPos.setIndex(0);
        }

        // add the high water mark to our original parse position and
        // return the result
        parsePosition.setIndex(parsePosition.getIndex() + highWaterMark.getIndex());
        // commented out because this API on ParsePosition doesn't exist in 1.1.x
        //        if (highWaterMark.getIndex() == 0) {
        //            parsePosition.setErrorIndex(parsePosition.getIndex() + highWaterMark.getErrorIndex());
        //        }
        return result;
    }

    /**
     * Turns lenient parse mode on and off.
     *
     * When in lenient parse mode, the formatter uses an RbnfLenientScanner
     * for parsing the text.  Lenient parsing is only in effect if a scanner
     * is set.  If a provider is not set, and this is used for parsing,
     * a default scanner <code>RbnfLenientScannerProviderImpl</code> will be set if
     * it is available on the classpath.  Otherwise this will have no effect.
     *
     * @param enabled If true, turns lenient-parse mode on; if false, turns it off.
     * @see RbnfLenientScanner
     * @see RbnfLenientScannerProvider
     * @stable ICU 2.0
     */
    public void setLenientParseMode(boolean enabled) {
        lenientParse = enabled;
    }

    /**
     * Returns true if lenient-parse mode is turned on.  Lenient parsing is off
     * by default.
     * @return true if lenient-parse mode is turned on.
     * @see #setLenientParseMode
     * @stable ICU 2.0
     */
    public boolean lenientParseEnabled() {
        return lenientParse;
    }

    /**
     * Sets the provider for the lenient scanner.  If this has not been set, 
     * {@link #setLenientParseMode}
     * has no effect.  This is necessary to decouple collation from format code.
     * @param scannerProvider the provider
     * @see #setLenientParseMode
     * @see #getLenientScannerProvider
     * @stable ICU 4.4
     */
    public void setLenientScannerProvider(RbnfLenientScannerProvider scannerProvider) {
        this.scannerProvider = scannerProvider;
    }

    /**
     * Returns the lenient scanner provider.  If none was set, and lenient parse is
     * enabled, this will attempt to instantiate a default scanner, setting it if
     * it was successful.  Otherwise this returns false.
     *
     * @see #setLenientScannerProvider
     * @stable ICU 4.4
     */
    public RbnfLenientScannerProvider getLenientScannerProvider() {
        // there's a potential race condition if two threads try to set/get the scanner at
        // the same time, but you get what you get, and you shouldn't be using this from
        // multiple threads anyway.
        if (scannerProvider == null && lenientParse && !lookedForScanner) {
            try {
                lookedForScanner = true;
                Class<?> cls = Class.forName("com.ibm.icu.impl.text.RbnfScannerProviderImpl");
                RbnfLenientScannerProvider provider = (RbnfLenientScannerProvider)cls.newInstance();
                setLenientScannerProvider(provider);
            }
            catch (Exception e) {
                // any failure, we just ignore and return null
            }
        }

        return scannerProvider;
    }

    /**
     * Override the default rule set to use.  If ruleSetName is null, reset
     * to the initial default rule set.
     * @param ruleSetName the name of the rule set, or null to reset the initial default.
     * @throws IllegalArgumentException if ruleSetName is not the name of a public ruleset.
     * @stable ICU 2.0
     */
    public void setDefaultRuleSet(String ruleSetName) {
        if (ruleSetName == null) {
            if (publicRuleSetNames.length > 0) {
                defaultRuleSet = findRuleSet(publicRuleSetNames[0]);
            } else {
                defaultRuleSet = null;
                int n = ruleSets.length;
                while (--n >= 0) {
                   String currentName = ruleSets[n].getName();
                   if (currentName.equals("%spellout-numbering") ||
                       currentName.equals("%digits-ordinal") ||
                       currentName.equals("%duration")) {

                       defaultRuleSet = ruleSets[n];
                       return;
                   }
                }

                n = ruleSets.length;
                while (--n >= 0) {
                    if (ruleSets[n].isPublic()) {
                        defaultRuleSet = ruleSets[n];
                        break;
                    }
                }
            }
        } else if (ruleSetName.startsWith("%%")) {
            throw new IllegalArgumentException("cannot use private rule set: " + ruleSetName);
        } else {
            defaultRuleSet = findRuleSet(ruleSetName);
        }
    }

    /**
     * Return the name of the current default rule set.
     * @return the name of the current default rule set, if it is public, else the empty string.
     * @stable ICU 3.0
     */
    public String getDefaultRuleSetName() {
        if (defaultRuleSet != null && defaultRuleSet.isPublic()) {
            return defaultRuleSet.getName();
        }
        return "";
    }
    
    /**
     * Sets the decimal format symbols used by this formatter. The formatter uses a copy of the
     * provided symbols.
     * 
     * @param newSymbols desired DecimalFormatSymbols
     * @see DecimalFormatSymbols
     * @stable ICU 49
     */
    public void setDecimalFormatSymbols(DecimalFormatSymbols newSymbols) {
        if (newSymbols != null) {
            decimalFormatSymbols = (DecimalFormatSymbols) newSymbols.clone();
            if (decimalFormat != null) {
                decimalFormat.setDecimalFormatSymbols(decimalFormatSymbols);
            }
            if (defaultInfinityRule != null) {
                defaultInfinityRule = null;
                getDefaultInfinityRule(); // Reset with the new DecimalFormatSymbols
            }
            if (defaultNaNRule != null) {
                defaultNaNRule = null;
                getDefaultNaNRule(); // Reset with the new DecimalFormatSymbols
            }

            // Apply the new decimalFormatSymbols by reparsing the rulesets
            for (NFRuleSet ruleSet : ruleSets) {
                ruleSet.setDecimalFormatSymbols(decimalFormatSymbols);
            }
        }
    }

    /**
     * {@icu} Set a particular DisplayContext value in the formatter,
     * such as CAPITALIZATION_FOR_STANDALONE. Note: For getContext, see 
     * NumberFormat.
     * 
     * @param context The DisplayContext value to set. 
     * @stable ICU 53
     */
    // Here we override the NumberFormat implementation in order to
    // lazily initialize relevant items 
    public void setContext(DisplayContext context) {
        super.setContext(context);
        if (!capitalizationInfoIsSet &&
              (context==DisplayContext.CAPITALIZATION_FOR_UI_LIST_OR_MENU || context==DisplayContext.CAPITALIZATION_FOR_STANDALONE)) {
            initCapitalizationContextInfo(locale);
            capitalizationInfoIsSet = true;
        }
        if (capitalizationBrkIter == null && (context==DisplayContext.CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE ||
              (context==DisplayContext.CAPITALIZATION_FOR_UI_LIST_OR_MENU && capitalizationForListOrMenu) ||
              (context==DisplayContext.CAPITALIZATION_FOR_STANDALONE && capitalizationForStandAlone) )) {
            capitalizationBrkIter = BreakIterator.getSentenceInstance(locale);
        }
    }

    /**
     * Returns the rounding mode.
     *
     * @return A rounding mode, between <code>BigDecimal.ROUND_UP</code> and
     * <code>BigDecimal.ROUND_UNNECESSARY</code>.
     * @see #setRoundingMode
     * @see java.math.BigDecimal
     * @draft ICU 56
     */
    @Override
    public int getRoundingMode() {
        return roundingMode;
    }

    /**
     * Sets the rounding mode. This has no effect unless the rounding increment is greater
     * than zero.
     *
     * @param roundingMode A rounding mode, between <code>BigDecimal.ROUND_UP</code> and
     * <code>BigDecimal.ROUND_UNNECESSARY</code>.
     * @exception IllegalArgumentException if <code>roundingMode</code> is unrecognized.
     * @see #getRoundingMode
     * @see java.math.BigDecimal
     * @draft ICU 56
     */
    @Override
    public void setRoundingMode(int roundingMode) {
        if (roundingMode < BigDecimal.ROUND_UP || roundingMode > BigDecimal.ROUND_UNNECESSARY) {
            throw new IllegalArgumentException("Invalid rounding mode: " + roundingMode);
        }

        this.roundingMode = roundingMode;
    }


    //-----------------------------------------------------------------------
    // package-internal API
    //-----------------------------------------------------------------------

    /**
     * Returns a reference to the formatter's default rule set.  The default
     * rule set is the last public rule set in the description, or the one
     * most recently set by setDefaultRuleSet.
     * @return The formatter's default rule set.
     */
    NFRuleSet getDefaultRuleSet() {
        return defaultRuleSet;
    }

    /**
     * Returns the scanner to use for lenient parsing.  The scanner is
     * provided by the provider.
     * @return The collator to use for lenient parsing, or null if lenient parsing
     * is turned off.
     */
    RbnfLenientScanner getLenientScanner() {
        if (lenientParse) {
            RbnfLenientScannerProvider provider = getLenientScannerProvider();
            if (provider != null) {
                return provider.get(locale, lenientParseRules);
            }
        }
        return null;
    }

    /**
     * Returns the DecimalFormatSymbols object that should be used by all DecimalFormat
     * instances owned by this formatter.  This object is lazily created: this function
     * creates it the first time it's called.
     * @return The DecimalFormatSymbols object that should be used by all DecimalFormat
     * instances owned by this formatter.
     */
    DecimalFormatSymbols getDecimalFormatSymbols() {
        // lazy-evaluate the DecimalFormatSymbols object.  This object
        // is shared by all DecimalFormat instances belonging to this
        // formatter
        if (decimalFormatSymbols == null) {
            decimalFormatSymbols = new DecimalFormatSymbols(locale);
        }
        return decimalFormatSymbols;
    }

    DecimalFormat getDecimalFormat() {
        if (decimalFormat == null) {
            // Don't use NumberFormat.getInstance, which can cause a recursive call
            String pattern = getPattern(locale, NUMBERSTYLE);
            decimalFormat = new DecimalFormat(pattern, getDecimalFormatSymbols());
        }
        return decimalFormat;
    }

    PluralFormat createPluralFormat(PluralRules.PluralType pluralType, String pattern) {
        return new PluralFormat(locale, pluralType, pattern, getDecimalFormat());
    }

    /**
     * Returns the default rule for infinity. This object is lazily created: this function
     * creates it the first time it's called.
     */
    NFRule getDefaultInfinityRule() {
        if (defaultInfinityRule == null) {
            defaultInfinityRule = new NFRule(this, "Inf: " + getDecimalFormatSymbols().getInfinity());
        }
        return defaultInfinityRule;
    }

    /**
     * Returns the default rule for NaN. This object is lazily created: this function
     * creates it the first time it's called.
     */
    NFRule getDefaultNaNRule() {
        if (defaultNaNRule == null) {
            defaultNaNRule = new NFRule(this, "NaN: " + getDecimalFormatSymbols().getNaN());
        }
        return defaultNaNRule;
    }

    //-----------------------------------------------------------------------
    // construction implementation
    //-----------------------------------------------------------------------

    /**
     * This extracts the special information from the rule sets before the
     * main parsing starts.  Extra whitespace must have already been removed
     * from the description.  If found, the special information is removed from the
     * description and returned, otherwise the description is unchanged and null
     * is returned.  Note: the trailing semicolon at the end of the special
     * rules is stripped.
     * @param description the rbnf description with extra whitespace removed
     * @param specialName the name of the special rule text to extract
     * @return the special rule text, or null if the rule was not found
     */
    private String extractSpecial(StringBuilder description, String specialName) {
        String result = null;
        int lp = description.indexOf(specialName);
        if (lp != -1) {
            // we've got to make sure we're not in the middle of a rule
            // (where specialName would actually get treated as
            // rule text)
            if (lp == 0 || description.charAt(lp - 1) == ';') {
                // locate the beginning and end of the actual special
                // rules (there may be whitespace between the name and
                // the first token in the description)
                int lpEnd = description.indexOf(";%", lp);

                if (lpEnd == -1) {
                    lpEnd = description.length() - 1; // later we add 1 back to get the '%'
                }
                int lpStart = lp + specialName.length();
                while (lpStart < lpEnd &&
                       PatternProps.isWhiteSpace(description.charAt(lpStart))) {
                    ++lpStart;
                }

                // copy out the special rules
                result = description.substring(lpStart, lpEnd);

                // remove the special rule from the description
                description.delete(lp, lpEnd+1); // delete the semicolon but not the '%'
            }
        }
        return result;
    }

    /**
     * This function parses the description and uses it to build all of
     * internal data structures that the formatter uses to do formatting
     * @param description The description of the formatter's desired behavior.
     * This is either passed in by the caller or loaded out of a resource
     * by one of the constructors, and is in the description format specified
     * in the class docs.
     */
    private void init(String description, String[][] localizations) {
        initLocalizations(localizations);

        // start by stripping the trailing whitespace from all the rules
        // (this is all the whitespace follwing each semicolon in the
        // description).  This allows us to look for rule-set boundaries
        // by searching for ";%" without having to worry about whitespace
        // between the ; and the %
        StringBuilder descBuf = stripWhitespace(description);

        // check to see if there's a set of lenient-parse rules.  If there
        // is, pull them out into our temporary holding place for them,
        // and delete them from the description before the real description-
        // parsing code sees them

        lenientParseRules = extractSpecial(descBuf, "%%lenient-parse:");
        postProcessRules = extractSpecial(descBuf, "%%post-process:");

        // pre-flight parsing the description and count the number of
        // rule sets (";%" marks the end of one rule set and the beginning
        // of the next)
        int numRuleSets = 1;
        int p = 0;
        while ((p = descBuf.indexOf(";%", p)) != -1) {
            ++numRuleSets;
            p += 2; // Skip the length of ";%"
        }

        // our rule list is an array of the appropriate size
        ruleSets = new NFRuleSet[numRuleSets];
        ruleSetsMap = new HashMap<String, NFRuleSet>(numRuleSets * 2 + 1);
        defaultRuleSet = null;

        // Used to count the number of public rule sets
        // Public rule sets have names that begin with % instead of %%.
        int publicRuleSetCount = 0;

        // divide up the descriptions into individual rule-set descriptions
        // and store them in a temporary array.  At each step, we also
        // new up a rule set, but all this does is initialize its name
        // and remove it from its description.  We can't actually parse
        // the rest of the descriptions and finish initializing everything
        // because we have to know the names and locations of all the rule
        // sets before we can actually set everything up
        String[] ruleSetDescriptions = new String[numRuleSets];

        int curRuleSet = 0;
        int start = 0;

        while (curRuleSet < ruleSets.length) {
            p = descBuf.indexOf(";%", start);
            if (p < 0) {
                p = descBuf.length() - 1;
            }
            ruleSetDescriptions[curRuleSet] = descBuf.substring(start, p + 1);
            NFRuleSet ruleSet = new NFRuleSet(this, ruleSetDescriptions, curRuleSet);
            ruleSets[curRuleSet] = ruleSet;
            String currentName = ruleSet.getName();
            ruleSetsMap.put(currentName, ruleSet);
            if (!currentName.startsWith("%%")) {
                ++publicRuleSetCount;
                if (defaultRuleSet == null
                        && currentName.equals("%spellout-numbering")
                        || currentName.equals("%digits-ordinal")
                        || currentName.equals("%duration"))
                {
                    defaultRuleSet = ruleSet;
                }
            }
            ++curRuleSet;
            start = p + 1;
        }

        // now we can take note of the formatter's default rule set, which
        // is the last public rule set in the description (it's the last
        // rather than the first so that a user can create a new formatter
        // from an existing formatter and change its default behavior just
        // by appending more rule sets to the end)

        // {dlf} Initialization of a fraction rule set requires the default rule
        // set to be known.  For purposes of initialization, this is always the
        // last public rule set, no matter what the localization data says.

        // Set the default ruleset to the last public ruleset, unless one of the predefined
        // ruleset names %spellout-numbering, %digits-ordinal, or %duration is found

        if (defaultRuleSet == null) {
            for (int i = ruleSets.length - 1; i >= 0; --i) {
                if (!ruleSets[i].getName().startsWith("%%")) {
                    defaultRuleSet = ruleSets[i];
                    break;
                }
            }
        }
        if (defaultRuleSet == null) {
            defaultRuleSet = ruleSets[ruleSets.length - 1];
        }

        // finally, we can go back through the temporary descriptions
        // list and finish setting up the substructure
        for (int i = 0; i < ruleSets.length; i++) {
            ruleSets[i].parseRules(ruleSetDescriptions[i]);
        }

        // Now that the rules are initialized, the 'real' default rule
        // set can be adjusted by the localization data.

        // prepare an array of the proper size and copy the names into it
        String[] publicRuleSetTemp = new String[publicRuleSetCount];
        publicRuleSetCount = 0;
        for (int i = ruleSets.length - 1; i >= 0; i--) {
            if (!ruleSets[i].getName().startsWith("%%")) {
                publicRuleSetTemp[publicRuleSetCount++] = ruleSets[i].getName();
            }
        }

        if (publicRuleSetNames != null) {
            // confirm the names, if any aren't in the rules, that's an error
            // it is ok if the rules contain public rule sets that are not in this list
            loop: for (int i = 0; i < publicRuleSetNames.length; ++i) {
                String name = publicRuleSetNames[i];
                for (int j = 0; j < publicRuleSetTemp.length; ++j) {
                    if (name.equals(publicRuleSetTemp[j])) {
                        continue loop;
                    }
                }
                throw new IllegalArgumentException("did not find public rule set: " + name);
            }

            defaultRuleSet = findRuleSet(publicRuleSetNames[0]); // might be different
        } else {
            publicRuleSetNames = publicRuleSetTemp;
        }
    }

    /**
     * Take the localizations array and create a Map from the locale strings to
     * the localization arrays.
     */
    private void initLocalizations(String[][] localizations) {
        if (localizations != null) {
            publicRuleSetNames = localizations[0].clone();

            Map<String, String[]> m = new HashMap<String, String[]>();
            for (int i = 1; i < localizations.length; ++i) {
                String[] data = localizations[i];
                String loc = data[0];
                String[] names = new String[data.length-1];
                if (names.length != publicRuleSetNames.length) {
                    throw new IllegalArgumentException("public name length: " + publicRuleSetNames.length +
                                                       " != localized names[" + i + "] length: " + names.length);
                }
                System.arraycopy(data, 1, names, 0, names.length);
                m.put(loc, names);
            }

            if (!m.isEmpty()) {
                ruleSetDisplayNames = m;
            }
        }
    }

    /**
     * Set capitalizationForListOrMenu, capitalizationForStandAlone 
     */
    private void initCapitalizationContextInfo(ULocale theLocale) {
        ICUResourceBundle rb = (ICUResourceBundle) UResourceBundle.getBundleInstance(ICUResourceBundle.ICU_BASE_NAME, theLocale);
        try {
            ICUResourceBundle rdb = rb.getWithFallback("contextTransforms/number-spellout");
            int[] intVector = rdb.getIntVector();
            if (intVector.length >= 2) {
                capitalizationForListOrMenu = (intVector[0] != 0);
                capitalizationForStandAlone = (intVector[1] != 0);
            }
        } catch (MissingResourceException e) {
            // use default
        }
    }

    /**
     * This function is used by init() to strip whitespace between rules (i.e.,
     * after semicolons).
     * @param description The formatter description
     * @return The description with all the whitespace that follows semicolons
     * taken out.
     */
    private StringBuilder stripWhitespace(String description) {
        // since we don't have a method that deletes characters (why?!!)
        // create a new StringBuffer to copy the text into
        StringBuilder result = new StringBuilder();
        int descriptionLength = description.length();

        // iterate through the characters...
        int start = 0;
        while (start < descriptionLength) {
            // seek to the first non-whitespace character...
            while (start < descriptionLength
                   && PatternProps.isWhiteSpace(description.charAt(start)))
            {
                ++start;
            }

            //if the first non-whitespace character is semicolon, skip it and continue
            if (start < descriptionLength && description.charAt(start) == ';') {
                start += 1;
                continue;
            }

            // locate the next semicolon in the text and copy the text from
            // our current position up to that semicolon into the result
            int p = description.indexOf(';', start);
            if (p == -1) {
                // or if we don't find a semicolon, just copy the rest of
                // the string into the result
                result.append(description.substring(start));
                break;
            }
            else if (p < descriptionLength) {
                result.append(description.substring(start, p + 1));
                start = p + 1;
            }
            else {
                // when we get here, we've seeked off the end of the string, and
                // we terminate the loop (we continue until *start* is -1 rather
                // than until *p* is -1, because otherwise we'd miss the last
                // rule in the description)
                break;
            }
        }
        return result;
    }

    //-----------------------------------------------------------------------
    // formatting implementation
    //-----------------------------------------------------------------------

    /**
     * Bottleneck through which all the public format() methods
     * that take a double pass. By the time we get here, we know
     * which rule set we're using to do the formatting.
     * @param number The number to format
     * @param ruleSet The rule set to use to format the number
     * @return The text that resulted from formatting the number
     */
    private String format(double number, NFRuleSet ruleSet) {
        // all API format() routines that take a double vector through
        // here.  Create an empty string buffer where the result will
        // be built, and pass it to the rule set (along with an insertion
        // position of 0 and the number being formatted) to the rule set
        // for formatting
        StringBuffer result = new StringBuffer();
        if (getRoundingMode() != BigDecimal.ROUND_UNNECESSARY) {
            // We convert to a string because BigDecimal insists on excessive precision.
            number = new BigDecimal(Double.toString(number)).setScale(getMaximumFractionDigits(), roundingMode).doubleValue();
        }
        ruleSet.format(number, result, 0, 0);
        postProcess(result, ruleSet);
        return result.toString();
    }

    /**
     * Bottleneck through which all the public format() methods
     * that take a long pass. By the time we get here, we know
     * which rule set we're using to do the formatting.
     * @param number The number to format
     * @param ruleSet The rule set to use to format the number
     * @return The text that resulted from formatting the number
     */
    private String format(long number, NFRuleSet ruleSet) {
        // all API format() routines that take a double vector through
        // here.  We have these two identical functions-- one taking a
        // double and one taking a long-- the couple digits of precision
        // that long has but double doesn't (both types are 8 bytes long,
        // but double has to borrow some of the mantissa bits to hold
        // the exponent).
        // Create an empty string buffer where the result will
        // be built, and pass it to the rule set (along with an insertion
        // position of 0 and the number being formatted) to the rule set
        // for formatting
        StringBuffer result = new StringBuffer();
        ruleSet.format(number, result, 0, 0);
        postProcess(result, ruleSet);
        return result.toString();
    }

    /**
     * Post-process the rules if we have a post-processor.
     */
    private void postProcess(StringBuffer result, NFRuleSet ruleSet) {
        if (postProcessRules != null) {
            if (postProcessor == null) {
                int ix = postProcessRules.indexOf(";");
                if (ix == -1) {
                    ix = postProcessRules.length();
                }
                String ppClassName = postProcessRules.substring(0, ix).trim();
                try {
                    Class<?> cls = Class.forName(ppClassName);
                    postProcessor = (RBNFPostProcessor)cls.newInstance();
                    postProcessor.init(this, postProcessRules);
                }
                catch (Exception e) {
                    // if debug, print it out
                    if (DEBUG) System.out.println("could not locate " + ppClassName + ", error " +
                                       e.getClass().getName() + ", " + e.getMessage());
                    postProcessor = null;
                    postProcessRules = null; // don't try again
                    return;
                }
            }

            postProcessor.process(result, ruleSet);
        }
    }

    /**
     * Adjust capitalization of formatted result for display context
     */
    private String adjustForContext(String result) {
        if (result != null && result.length() > 0 && UCharacter.isLowerCase(result.codePointAt(0))) {
            DisplayContext capitalization = getContext(DisplayContext.Type.CAPITALIZATION);
            if (  capitalization==DisplayContext.CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE ||
                  (capitalization == DisplayContext.CAPITALIZATION_FOR_UI_LIST_OR_MENU && capitalizationForListOrMenu) ||
                  (capitalization == DisplayContext.CAPITALIZATION_FOR_STANDALONE && capitalizationForStandAlone) ) {
                if (capitalizationBrkIter == null) {
                    // should only happen when deserializing, etc.
                    capitalizationBrkIter = BreakIterator.getSentenceInstance(locale);
                }
                return UCharacter.toTitleCase(locale, result, capitalizationBrkIter,
                                UCharacter.TITLECASE_NO_LOWERCASE | UCharacter.TITLECASE_NO_BREAK_ADJUSTMENT);
            }
        }
        return result;
    }

    /**
     * Returns the named rule set.  Throws an IllegalArgumentException
     * if this formatter doesn't have a rule set with that name.
     * @param name The name of the desired rule set
     * @return The rule set with that name
     */
    NFRuleSet findRuleSet(String name) throws IllegalArgumentException {
        NFRuleSet result = ruleSetsMap.get(name);
        if (result == null) {
            throw new IllegalArgumentException("No rule set named " + name);
        }
        return result;
    }
}
