Home | History | Annotate | Download | only in text
      1 /* GENERATED SOURCE. DO NOT MODIFY. */
      2 //  2017 and later: Unicode, Inc. and others.
      3 // License & terms of use: http://www.unicode.org/copyright.html#License
      4 package android.icu.text;
      5 
      6 import java.io.IOException;
      7 import java.io.ObjectInputStream;
      8 import java.io.ObjectOutputStream;
      9 import java.io.ObjectStreamField;
     10 import java.math.BigInteger;
     11 import java.math.RoundingMode;
     12 import java.text.AttributedCharacterIterator;
     13 import java.text.FieldPosition;
     14 import java.text.ParseException;
     15 import java.text.ParsePosition;
     16 
     17 import android.icu.impl.number.AffixUtils;
     18 import android.icu.impl.number.DecimalFormatProperties;
     19 import android.icu.impl.number.Padder.PadPosition;
     20 import android.icu.impl.number.Parse;
     21 import android.icu.impl.number.PatternStringParser;
     22 import android.icu.impl.number.PatternStringUtils;
     23 import android.icu.lang.UCharacter;
     24 import android.icu.math.BigDecimal;
     25 import android.icu.math.MathContext;
     26 import android.icu.number.FormattedNumber;
     27 import android.icu.number.LocalizedNumberFormatter;
     28 import android.icu.number.NumberFormatter;
     29 import android.icu.text.PluralRules.IFixedDecimal;
     30 import android.icu.util.Currency;
     31 import android.icu.util.Currency.CurrencyUsage;
     32 import android.icu.util.CurrencyAmount;
     33 import android.icu.util.ULocale;
     34 import android.icu.util.ULocale.Category;
     35 
     36 /**
     37  * <strong>[icu enhancement]</strong> ICU's replacement for {@link java.text.DecimalFormat}.&nbsp;Methods, fields, and other functionality specific to ICU are labeled '<strong>[icu]</strong>'. <code>DecimalFormat</code> is the primary
     38  * concrete subclass of {@link NumberFormat}. It has a variety of features designed to make it
     39  * possible to parse and format numbers in any locale, including support for Western, Arabic, or
     40  * Indic digits. It supports different flavors of numbers, including integers ("123"), fixed-point
     41  * numbers ("123.4"), scientific notation ("1.23E4"), percentages ("12%"), and currency amounts
     42  * ("$123.00", "USD123.00", "123.00 US dollars"). All of these flavors can be easily localized.
     43  *
     44  * <p>To obtain a number formatter for a specific locale (including the default locale), call one of
     45  * NumberFormat's factory methods such as {@link NumberFormat#getInstance}. Do not call
     46  * DecimalFormat constructors directly unless you know what you are doing.
     47  *
     48  * <p>DecimalFormat aims to comply with the specification <a
     49  * href="http://unicode.org/reports/tr35/tr35-numbers.html#Number_Format_Patterns">UTS #35</a>. Read
     50  * the specification for more information on how all the properties in DecimalFormat fit together.
     51  *
     52  * <p><strong>NOTE:</strong> Starting in ICU 60, there is a new set of APIs for localized number
     53  * formatting that are designed to be an improvement over DecimalFormat.  New users are discouraged
     54  * from using DecimalFormat.  For more information, see the package android.icu.number.
     55  *
     56  * <h3>Example Usage</h3>
     57  *
     58  * <p>Customize settings on a DecimalFormat instance from the NumberFormat factory:
     59  *
     60  * <blockquote>
     61  *
     62  * <pre>
     63  * NumberFormat f = NumberFormat.getInstance(loc);
     64  * if (f instanceof DecimalFormat) {
     65  *     ((DecimalFormat) f).setDecimalSeparatorAlwaysShown(true);
     66  *     ((DecimalFormat) f).setMinimumGroupingDigits(2);
     67  * }
     68  * </pre>
     69  *
     70  * </blockquote>
     71  *
     72  * <p>Quick and dirty print out a number using the localized number, currency, and percent format
     73  * for each locale:
     74  *
     75  * <blockquote>
     76  *
     77  * <pre>
     78  * for (ULocale uloc : ULocale.getAvailableLocales()) {
     79  *     System.out.print(uloc + ":\t");
     80  *     System.out.print(NumberFormat.getInstance(uloc).format(1.23));
     81  *     System.out.print("\t");
     82  *     System.out.print(NumberFormat.getCurrencyInstance(uloc).format(1.23));
     83  *     System.out.print("\t");
     84  *     System.out.print(NumberFormat.getPercentInstance(uloc).format(1.23));
     85  *     System.out.println();
     86  * }
     87  * </pre>
     88  *
     89  * </blockquote>
     90  *
     91  * <h3>Properties and Symbols</h3>
     92  *
     93  * <p>A DecimalFormat object encapsulates a set of <em>properties</em> and a set of
     94  * <em>symbols</em>. Grouping size, rounding mode, and affixes are examples of properties. Locale
     95  * digits and the characters used for grouping and decimal separators are examples of symbols.
     96  *
     97  * <p>To set a custom set of symbols, use {@link #setDecimalFormatSymbols}. Use the various other
     98  * setters in this class to set custom values for the properties.
     99  *
    100  * <h3>Rounding</h3>
    101  *
    102  * <p>DecimalFormat provides three main strategies to specify the position at which numbers should
    103  * be rounded:
    104  *
    105  * <ol>
    106  *   <li><strong>Magnitude:</strong> Display a fixed number of fraction digits; this is the most
    107  *       common form.
    108  *   <li><strong>Increment:</strong> Round numbers to the closest multiple of a certain increment,
    109  *       such as 0.05. This is common in currencies.
    110  *   <li><strong>Significant Digits:</strong> Round numbers such that a fixed number of nonzero
    111  *       digits are shown. This is most common in scientific notation.
    112  * </ol>
    113  *
    114  * <p>It is not possible to specify more than one rounding strategy. For example, setting a rounding
    115  * increment in conjunction with significant digits results in undefined behavior.
    116  *
    117  * <p>It is also possible to specify the <em>rounding mode</em> to use. The default rounding mode is
    118  * "half even", which rounds numbers to their closest increment, with ties broken in favor of
    119  * trailing numbers being even. For more information, see {@link #setRoundingMode} and <a
    120  * href="http://userguide.icu-project.org/formatparse/numbers/rounding-modes">the ICU User
    121  * Guide</a>.
    122  *
    123  * <h3>Pattern Strings</h3>
    124  *
    125  * <p>A <em>pattern string</em> is a way to serialize some of the available properties for decimal
    126  * formatting. However, not all properties are capable of being serialized into a pattern string;
    127  * see {@link #applyPattern} for more information.
    128  *
    129  * <p>Most users should not need to interface with pattern strings directly.
    130  *
    131  * <p>ICU DecimalFormat aims to follow the specification for pattern strings in <a
    132  * href="http://unicode.org/reports/tr35/tr35-numbers.html#Number_Format_Patterns">UTS #35</a>.
    133  * Refer to that specification for more information on pattern string syntax.
    134  *
    135  * <h4>Pattern String BNF</h4>
    136  *
    137  * The following BNF is used when parsing the pattern string into property values:
    138  *
    139  * <pre>
    140  * pattern    := subpattern (';' subpattern)?
    141  * subpattern := prefix? number exponent? suffix?
    142  * number     := (integer ('.' fraction)?) | sigDigits
    143  * prefix     := '&#92;u0000'..'&#92;uFFFD' - specialCharacters
    144  * suffix     := '&#92;u0000'..'&#92;uFFFD' - specialCharacters
    145  * integer    := '#'* '0'* '0'
    146  * fraction   := '0'* '#'*
    147  * sigDigits  := '#'* '@' '@'* '#'*
    148  * exponent   := 'E' '+'? '0'* '0'
    149  * padSpec    := '*' padChar
    150  * padChar    := '&#92;u0000'..'&#92;uFFFD' - quote
    151  * &#32;
    152  * Notation:
    153  *   X*       0 or more instances of X
    154  *   X?       0 or 1 instances of X
    155  *   X|Y      either X or Y
    156  *   C..D     any character from C up to D, inclusive
    157  *   S-T      characters in S, except those in T
    158  * </pre>
    159  *
    160  * <p>The first subpattern is for positive numbers. The second (optional) subpattern is for negative
    161  * numbers.
    162  *
    163  * <p>Not indicated in the BNF syntax above:
    164  *
    165  * <ul>
    166  *   <li>The grouping separator ',' can occur inside the integer and sigDigits elements, between any
    167  *       two pattern characters of that element, as long as the integer or sigDigits element is not
    168  *       followed by the exponent element.
    169  *   <li>Two grouping intervals are recognized: That between the decimal point and the first
    170  *       grouping symbol, and that between the first and second grouping symbols. These intervals
    171  *       are identical in most locales, but in some locales they differ. For example, the pattern
    172  *       &quot;#,##,###&quot; formats the number 123456789 as &quot;12,34,56,789&quot;.
    173  *   <li>The pad specifier <code>padSpec</code> may appear before the prefix, after the prefix,
    174  *       before the suffix, after the suffix, or not at all.
    175  *   <li>In place of '0', the digits '1' through '9' may be used to indicate a rounding increment.
    176  * </ul>
    177  *
    178  * <h3>Parsing</h3>
    179  *
    180  * <p>DecimalFormat aims to be able to parse anything that it can output as a formatted string.
    181  *
    182  * <p>There are two primary parse modes: <em>lenient</em> and <em>strict</em>. Lenient mode should
    183  * be used if the goal is to parse user input to a number; strict mode should be used if the goal is
    184  * validation. The default is lenient mode. For more information, see {@link #setParseStrict}.
    185  *
    186  * <p><code>DecimalFormat</code> parses all Unicode characters that represent decimal digits, as
    187  * defined by {@link UCharacter#digit}. In addition, <code>DecimalFormat</code> also recognizes as
    188  * digits the ten consecutive characters starting with the localized zero digit defined in the
    189  * {@link DecimalFormatSymbols} object. During formatting, the {@link DecimalFormatSymbols}-based
    190  * digits are output.
    191  *
    192  * <p>Grouping separators are ignored in lenient mode (default). In strict mode, grouping separators
    193  * must match the locale-specified grouping sizes.
    194  *
    195  * <p>When using {@link #parseCurrency}, all currencies are accepted, not just the currency
    196  * currently set in the formatter. In addition, the formatter is able to parse every currency style
    197  * format for a particular locale no matter which style the formatter is constructed with. For
    198  * example, a formatter instance gotten from NumberFormat.getInstance(ULocale,
    199  * NumberFormat.CURRENCYSTYLE) can parse both "USD1.00" and "3.00 US dollars".
    200  *
    201  * <p>Whitespace characters (lenient mode) and bidi control characters (lenient and strict mode),
    202  * collectively called "ignorables", do not need to match in identity or quantity between the
    203  * pattern string and the input string. For example, the pattern "# %" matches "35 %" (with a single
    204  * space), "35%" (with no space), "35&nbsp;%" (with a non-breaking space), and "35&nbsp; %" (with
    205  * multiple spaces). Arbitrary ignorables are also allowed at boundaries between the parts of the
    206  * number: prefix, number, exponent separator, and suffix. Ignorable whitespace characters are those
    207  * having the Unicode "blank" property for regular expressions, defined in UTS #18 Annex C, which is
    208  * "horizontal" whitespace, like spaces and tabs, but not "vertical" whitespace, like line breaks.
    209  *
    210  * <p>If {@link #parse(String, ParsePosition)} fails to parse a string, it returns <code>null</code>
    211  * and leaves the parse position unchanged. The convenience method {@link #parse(String)} indicates
    212  * parse failure by throwing a {@link java.text.ParseException}.
    213  *
    214  * <p>Under the hood, a state table parsing engine is used. To debug a parsing failure during
    215  * development, use the following pattern to print details about the state table transitions:
    216  *
    217  * <pre>
    218  * android.icu.impl.number.Parse.DEBUGGING = true;
    219  * df.parse("123.45", ppos);
    220  * android.icu.impl.number.Parse.DEBUGGING = false;
    221  * </pre>
    222  *
    223  * <h3>Thread Safety and Best Practices</h3>
    224  *
    225  * <p>Starting with ICU 59, instances of DecimalFormat are thread-safe.
    226  *
    227  * <p>Under the hood, DecimalFormat maintains an immutable formatter object that is rebuilt whenever
    228  * any of the property setters are called. It is therefore best practice to call property setters
    229  * only during construction and not when formatting numbers online.
    230  *
    231  * @see java.text.Format
    232  * @see NumberFormat
    233  */
    234 public class DecimalFormat extends NumberFormat {
    235 
    236   /** New serialization in ICU 59: declare different version from ICU 58. */
    237   private static final long serialVersionUID = 864413376551465018L;
    238 
    239   /**
    240    * One non-transient field such that deserialization can determine the version of the class. This
    241    * field has existed since the very earliest versions of DecimalFormat.
    242    */
    243   @SuppressWarnings("unused")
    244   private final int serialVersionOnStream = 5;
    245 
    246   //=====================================================================================//
    247   //                                   INSTANCE FIELDS                                   //
    248   //=====================================================================================//
    249 
    250   // Fields are package-private, so that subclasses can use them.
    251   // properties should be final, but clone won't work if we make it final.
    252   // All fields are transient because custom serialization is used.
    253 
    254   /**
    255    * The property bag corresponding to user-specified settings and settings from the pattern string.
    256    * In principle this should be final, but serialize and clone won't work if it is final. Does not
    257    * need to be volatile because the reference never changes.
    258    */
    259   /* final */ transient DecimalFormatProperties properties;
    260 
    261   /**
    262    * The symbols for the current locale. Volatile because threads may read and write at the same
    263    * time.
    264    */
    265   transient volatile DecimalFormatSymbols symbols;
    266 
    267   /**
    268    * The pre-computed formatter object. Setters cause this to be re-computed atomically. The {@link
    269    * #format} method uses the formatter directly without needing to synchronize. Volatile because
    270    * threads may read and write at the same time.
    271    */
    272   transient volatile LocalizedNumberFormatter formatter;
    273 
    274   /**
    275    * The effective properties as exported from the formatter object. Volatile because threads may
    276    * read and write at the same time.
    277    */
    278   transient volatile DecimalFormatProperties exportedProperties;
    279 
    280   //=====================================================================================//
    281   //                                    CONSTRUCTORS                                     //
    282   //=====================================================================================//
    283 
    284   /**
    285    * Creates a DecimalFormat based on the number pattern and symbols for the default locale. This is
    286    * a convenient way to obtain a DecimalFormat instance when internationalization is not the main
    287    * concern.
    288    *
    289    * <p>Most users should call the factory methods on NumberFormat, such as {@link
    290    * NumberFormat#getNumberInstance}, which return localized formatter objects, instead of the
    291    * DecimalFormat constructors.
    292    *
    293    * @see NumberFormat#getInstance
    294    * @see NumberFormat#getNumberInstance
    295    * @see NumberFormat#getCurrencyInstance
    296    * @see NumberFormat#getPercentInstance
    297    * @see Category#FORMAT
    298    */
    299   public DecimalFormat() {
    300     // Use the locale's default pattern
    301     ULocale def = ULocale.getDefault(ULocale.Category.FORMAT);
    302     String pattern = getPattern(def, NumberFormat.NUMBERSTYLE);
    303     symbols = getDefaultSymbols();
    304     properties = new DecimalFormatProperties();
    305     exportedProperties = new DecimalFormatProperties();
    306     // Regression: ignore pattern rounding information if the pattern has currency symbols.
    307     setPropertiesFromPattern(pattern, PatternStringParser.IGNORE_ROUNDING_IF_CURRENCY);
    308     refreshFormatter();
    309   }
    310 
    311   /**
    312    * Creates a DecimalFormat based on the given pattern, using symbols for the default locale. This
    313    * is a convenient way to obtain a DecimalFormat instance when internationalization is not the
    314    * main concern.
    315    *
    316    * <p>Most users should call the factory methods on NumberFormat, such as {@link
    317    * NumberFormat#getNumberInstance}, which return localized formatter objects, instead of the
    318    * DecimalFormat constructors.
    319    *
    320    * @param pattern A pattern string such as "#,##0.00" conforming to <a
    321    *     href="http://unicode.org/reports/tr35/tr35-numbers.html#Number_Format_Patterns">UTS
    322    *     #35</a>.
    323    * @throws IllegalArgumentException if the given pattern is invalid.
    324    * @see NumberFormat#getInstance
    325    * @see NumberFormat#getNumberInstance
    326    * @see NumberFormat#getCurrencyInstance
    327    * @see NumberFormat#getPercentInstance
    328    * @see Category#FORMAT
    329    */
    330   public DecimalFormat(String pattern) {
    331     symbols = getDefaultSymbols();
    332     properties = new DecimalFormatProperties();
    333     exportedProperties = new DecimalFormatProperties();
    334     // Regression: ignore pattern rounding information if the pattern has currency symbols.
    335     setPropertiesFromPattern(pattern, PatternStringParser.IGNORE_ROUNDING_IF_CURRENCY);
    336     refreshFormatter();
    337   }
    338 
    339   /**
    340    * Creates a DecimalFormat based on the given pattern and symbols. Use this constructor if you
    341    * want complete control over the behavior of the formatter.
    342    *
    343    * <p>Most users should call the factory methods on NumberFormat, such as {@link
    344    * NumberFormat#getNumberInstance}, which return localized formatter objects, instead of the
    345    * DecimalFormat constructors.
    346    *
    347    * @param pattern A pattern string such as "#,##0.00" conforming to <a
    348    *     href="http://unicode.org/reports/tr35/tr35-numbers.html#Number_Format_Patterns">UTS
    349    *     #35</a>.
    350    * @param symbols The set of symbols to be used.
    351    * @exception IllegalArgumentException if the given pattern is invalid
    352    * @see NumberFormat#getInstance
    353    * @see NumberFormat#getNumberInstance
    354    * @see NumberFormat#getCurrencyInstance
    355    * @see NumberFormat#getPercentInstance
    356    * @see DecimalFormatSymbols
    357    */
    358   public DecimalFormat(String pattern, DecimalFormatSymbols symbols) {
    359     this.symbols = (DecimalFormatSymbols) symbols.clone();
    360     properties = new DecimalFormatProperties();
    361     exportedProperties = new DecimalFormatProperties();
    362     // Regression: ignore pattern rounding information if the pattern has currency symbols.
    363     setPropertiesFromPattern(pattern, PatternStringParser.IGNORE_ROUNDING_IF_CURRENCY);
    364     refreshFormatter();
    365   }
    366 
    367   /**
    368    * Creates a DecimalFormat based on the given pattern and symbols, with additional control over
    369    * the behavior of currency. The style argument determines whether currency rounding rules should
    370    * override the pattern, and the {@link CurrencyPluralInfo} object is used for customizing the
    371    * plural forms used for currency long names.
    372    *
    373    * <p>Most users should call the factory methods on NumberFormat, such as {@link
    374    * NumberFormat#getNumberInstance}, which return localized formatter objects, instead of the
    375    * DecimalFormat constructors.
    376    *
    377    * @param pattern a non-localized pattern string
    378    * @param symbols the set of symbols to be used
    379    * @param infoInput the information used for currency plural format, including currency plural
    380    *     patterns and plural rules.
    381    * @param style the decimal formatting style, it is one of the following values:
    382    *     NumberFormat.NUMBERSTYLE; NumberFormat.CURRENCYSTYLE; NumberFormat.PERCENTSTYLE;
    383    *     NumberFormat.SCIENTIFICSTYLE; NumberFormat.INTEGERSTYLE; NumberFormat.ISOCURRENCYSTYLE;
    384    *     NumberFormat.PLURALCURRENCYSTYLE;
    385    */
    386   public DecimalFormat(
    387       String pattern, DecimalFormatSymbols symbols, CurrencyPluralInfo infoInput, int style) {
    388     this(pattern, symbols, style);
    389     properties.setCurrencyPluralInfo(infoInput);
    390     refreshFormatter();
    391   }
    392 
    393   /** Package-private constructor used by NumberFormat. */
    394   DecimalFormat(String pattern, DecimalFormatSymbols symbols, int choice) {
    395     this.symbols = (DecimalFormatSymbols) symbols.clone();
    396     properties = new DecimalFormatProperties();
    397     exportedProperties = new DecimalFormatProperties();
    398     // If choice is a currency type, ignore the rounding information.
    399     if (choice == CURRENCYSTYLE
    400         || choice == ISOCURRENCYSTYLE
    401         || choice == ACCOUNTINGCURRENCYSTYLE
    402         || choice == CASHCURRENCYSTYLE
    403         || choice == STANDARDCURRENCYSTYLE
    404         || choice == PLURALCURRENCYSTYLE) {
    405       setPropertiesFromPattern(pattern, PatternStringParser.IGNORE_ROUNDING_ALWAYS);
    406     } else {
    407       setPropertiesFromPattern(pattern, PatternStringParser.IGNORE_ROUNDING_IF_CURRENCY);
    408     }
    409     refreshFormatter();
    410   }
    411 
    412   private static DecimalFormatSymbols getDefaultSymbols() {
    413     return DecimalFormatSymbols.getInstance();
    414   }
    415 
    416   /**
    417    * Parses the given pattern string and overwrites the settings specified in the pattern string.
    418    * The properties corresponding to the following setters are overwritten, either with their
    419    * default values or with the value specified in the pattern string:
    420    *
    421    * <ol>
    422    *   <li>{@link #setDecimalSeparatorAlwaysShown}
    423    *   <li>{@link #setExponentSignAlwaysShown}
    424    *   <li>{@link #setFormatWidth}
    425    *   <li>{@link #setGroupingSize}
    426    *   <li>{@link #setMultiplier} (percent/permille)
    427    *   <li>{@link #setMaximumFractionDigits}
    428    *   <li>{@link #setMaximumIntegerDigits}
    429    *   <li>{@link #setMaximumSignificantDigits}
    430    *   <li>{@link #setMinimumExponentDigits}
    431    *   <li>{@link #setMinimumFractionDigits}
    432    *   <li>{@link #setMinimumIntegerDigits}
    433    *   <li>{@link #setMinimumSignificantDigits}
    434    *   <li>{@link #setPadPosition}
    435    *   <li>{@link #setPadCharacter}
    436    *   <li>{@link #setRoundingIncrement}
    437    *   <li>{@link #setSecondaryGroupingSize}
    438    * </ol>
    439    *
    440    * All other settings remain untouched.
    441    *
    442    * <p>For more information on pattern strings, see <a
    443    * href="http://unicode.org/reports/tr35/tr35-numbers.html#Number_Format_Patterns">UTS #35</a>.
    444    */
    445   public synchronized void applyPattern(String pattern) {
    446     setPropertiesFromPattern(pattern, PatternStringParser.IGNORE_ROUNDING_NEVER);
    447     // Backwards compatibility: clear out user-specified prefix and suffix,
    448     // as well as CurrencyPluralInfo.
    449     properties.setPositivePrefix(null);
    450     properties.setNegativePrefix(null);
    451     properties.setPositiveSuffix(null);
    452     properties.setNegativeSuffix(null);
    453     properties.setCurrencyPluralInfo(null);
    454     refreshFormatter();
    455   }
    456 
    457   /**
    458    * Converts the given string to standard notation and then parses it using {@link #applyPattern}.
    459    * This method is provided for backwards compatibility and should not be used in new projects.
    460    *
    461    * <p>Localized notation means that instead of using generic placeholders in the pattern, you use
    462    * the corresponding locale-specific characters instead. For example, in locale <em>fr-FR</em>,
    463    * the period in the pattern "0.000" means "decimal" in standard notation (as it does in every
    464    * other locale), but it means "grouping" in localized notation.
    465    *
    466    * @param localizedPattern The pattern string in localized notation.
    467    */
    468   public synchronized void applyLocalizedPattern(String localizedPattern) {
    469     String pattern = PatternStringUtils.convertLocalized(localizedPattern, symbols, false);
    470     applyPattern(pattern);
    471   }
    472 
    473   //=====================================================================================//
    474   //                                CLONE AND SERIALIZE                                  //
    475   //=====================================================================================//
    476 
    477   /***/
    478   @Override
    479   public Object clone() {
    480     DecimalFormat other = (DecimalFormat) super.clone();
    481     other.symbols = (DecimalFormatSymbols) symbols.clone();
    482     other.properties = properties.clone();
    483     other.exportedProperties = new DecimalFormatProperties();
    484     other.refreshFormatter();
    485     return other;
    486   }
    487 
    488   /**
    489    * Custom serialization: save property bag and symbols; the formatter object can be re-created
    490    * from just that amount of information.
    491    */
    492   private synchronized void writeObject(ObjectOutputStream oos) throws IOException {
    493     // ICU 59 custom serialization.
    494     // Write class metadata and serialVersionOnStream field:
    495     oos.defaultWriteObject();
    496     // Extra int for possible future use:
    497     oos.writeInt(0);
    498     // 1) Property Bag
    499     oos.writeObject(properties);
    500     // 2) DecimalFormatSymbols
    501     oos.writeObject(symbols);
    502   }
    503 
    504   /**
    505    * Custom serialization: re-create object from serialized property bag and symbols. Also supports
    506    * reading from the legacy (pre-ICU4J 59) format and converting it to the new form.
    507    */
    508   private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
    509     ObjectInputStream.GetField fieldGetter = ois.readFields();
    510     ObjectStreamField[] serializedFields = fieldGetter.getObjectStreamClass().getFields();
    511     int serialVersion = fieldGetter.get("serialVersionOnStream", -1);
    512 
    513     if (serialVersion > 5) {
    514       throw new IOException(
    515           "Cannot deserialize newer android.icu.text.DecimalFormat (v" + serialVersion + ")");
    516     } else if (serialVersion == 5) {
    517       ///// ICU 59+ SERIALIZATION FORMAT /////
    518       // We expect this field and no other fields:
    519       if (serializedFields.length > 1) {
    520         throw new IOException("Too many fields when reading serial version 5");
    521       }
    522       // Extra int for possible future use:
    523       ois.readInt();
    524       // 1) Property Bag
    525       Object serializedProperties = ois.readObject();
    526       if (serializedProperties instanceof DecimalFormatProperties) {
    527         // ICU 60+
    528         properties = (DecimalFormatProperties) serializedProperties;
    529       } else {
    530         // ICU 59
    531         properties = ((android.icu.impl.number.Properties) serializedProperties).getInstance();
    532       }
    533       // 2) DecimalFormatSymbols
    534       symbols = (DecimalFormatSymbols) ois.readObject();
    535       // Re-build transient fields
    536       exportedProperties = new DecimalFormatProperties();
    537       refreshFormatter();
    538     } else {
    539       ///// LEGACY SERIALIZATION FORMAT /////
    540       properties = new DecimalFormatProperties();
    541       // Loop through the fields. Not all fields necessarily exist in the serialization.
    542       String pp = null, ppp = null, ps = null, psp = null;
    543       String np = null, npp = null, ns = null, nsp = null;
    544       for (ObjectStreamField field : serializedFields) {
    545         String name = field.getName();
    546         if (name.equals("decimalSeparatorAlwaysShown")) {
    547           setDecimalSeparatorAlwaysShown(fieldGetter.get("decimalSeparatorAlwaysShown", false));
    548         } else if (name.equals("exponentSignAlwaysShown")) {
    549           setExponentSignAlwaysShown(fieldGetter.get("exponentSignAlwaysShown", false));
    550         } else if (name.equals("formatWidth")) {
    551           setFormatWidth(fieldGetter.get("formatWidth", 0));
    552         } else if (name.equals("groupingSize")) {
    553           setGroupingSize(fieldGetter.get("groupingSize", (byte) 3));
    554         } else if (name.equals("groupingSize2")) {
    555           setSecondaryGroupingSize(fieldGetter.get("groupingSize2", (byte) 0));
    556         } else if (name.equals("maxSignificantDigits")) {
    557           setMaximumSignificantDigits(fieldGetter.get("maxSignificantDigits", 6));
    558         } else if (name.equals("minExponentDigits")) {
    559           setMinimumExponentDigits(fieldGetter.get("minExponentDigits", (byte) 0));
    560         } else if (name.equals("minSignificantDigits")) {
    561           setMinimumSignificantDigits(fieldGetter.get("minSignificantDigits", 1));
    562         } else if (name.equals("multiplier")) {
    563           setMultiplier(fieldGetter.get("multiplier", 1));
    564         } else if (name.equals("pad")) {
    565           setPadCharacter(fieldGetter.get("pad", '\u0020'));
    566         } else if (name.equals("padPosition")) {
    567           setPadPosition(fieldGetter.get("padPosition", 0));
    568         } else if (name.equals("parseBigDecimal")) {
    569           setParseBigDecimal(fieldGetter.get("parseBigDecimal", false));
    570         } else if (name.equals("parseRequireDecimalPoint")) {
    571           setDecimalPatternMatchRequired(fieldGetter.get("parseRequireDecimalPoint", false));
    572         } else if (name.equals("roundingMode")) {
    573           setRoundingMode(fieldGetter.get("roundingMode", 0));
    574         } else if (name.equals("useExponentialNotation")) {
    575           setScientificNotation(fieldGetter.get("useExponentialNotation", false));
    576         } else if (name.equals("useSignificantDigits")) {
    577           setSignificantDigitsUsed(fieldGetter.get("useSignificantDigits", false));
    578         } else if (name.equals("currencyPluralInfo")) {
    579           setCurrencyPluralInfo((CurrencyPluralInfo) fieldGetter.get("currencyPluralInfo", null));
    580         } else if (name.equals("mathContext")) {
    581           setMathContextICU((MathContext) fieldGetter.get("mathContext", null));
    582         } else if (name.equals("negPrefixPattern")) {
    583           npp = (String) fieldGetter.get("negPrefixPattern", null);
    584         } else if (name.equals("negSuffixPattern")) {
    585           nsp = (String) fieldGetter.get("negSuffixPattern", null);
    586         } else if (name.equals("negativePrefix")) {
    587           np = (String) fieldGetter.get("negativePrefix", null);
    588         } else if (name.equals("negativeSuffix")) {
    589           ns = (String) fieldGetter.get("negativeSuffix", null);
    590         } else if (name.equals("posPrefixPattern")) {
    591           ppp = (String) fieldGetter.get("posPrefixPattern", null);
    592         } else if (name.equals("posSuffixPattern")) {
    593           psp = (String) fieldGetter.get("posSuffixPattern", null);
    594         } else if (name.equals("positivePrefix")) {
    595           pp = (String) fieldGetter.get("positivePrefix", null);
    596         } else if (name.equals("positiveSuffix")) {
    597           ps = (String) fieldGetter.get("positiveSuffix", null);
    598         } else if (name.equals("roundingIncrement")) {
    599           setRoundingIncrement((java.math.BigDecimal) fieldGetter.get("roundingIncrement", null));
    600         } else if (name.equals("symbols")) {
    601           setDecimalFormatSymbols((DecimalFormatSymbols) fieldGetter.get("symbols", null));
    602         } else {
    603           // The following fields are ignored:
    604           // "PARSE_MAX_EXPONENT"
    605           // "currencySignCount"
    606           // "style"
    607           // "attributes"
    608           // "currencyChoice"
    609           // "formatPattern"
    610           // "currencyUsage" => ignore this because the old code puts currencyUsage directly into min/max fraction.
    611         }
    612       }
    613       // Resolve affixes
    614       if (npp == null) {
    615         properties.setNegativePrefix(np);
    616       } else {
    617         properties.setNegativePrefixPattern(npp);
    618       }
    619       if (nsp == null) {
    620         properties.setNegativeSuffix(ns);
    621       } else {
    622         properties.setNegativeSuffixPattern(nsp);
    623       }
    624       if (ppp == null) {
    625         properties.setPositivePrefix(pp);
    626       } else {
    627         properties.setPositivePrefixPattern(ppp);
    628       }
    629       if (psp == null) {
    630         properties.setPositiveSuffix(ps);
    631       } else {
    632         properties.setPositiveSuffixPattern(psp);
    633       }
    634       // Extract values from parent NumberFormat class.  Have to use reflection here.
    635       java.lang.reflect.Field getter;
    636       try {
    637         getter = NumberFormat.class.getDeclaredField("groupingUsed");
    638         getter.setAccessible(true);
    639         setGroupingUsed((Boolean) getter.get(this));
    640         getter = NumberFormat.class.getDeclaredField("parseIntegerOnly");
    641         getter.setAccessible(true);
    642         setParseIntegerOnly((Boolean) getter.get(this));
    643         getter = NumberFormat.class.getDeclaredField("maximumIntegerDigits");
    644         getter.setAccessible(true);
    645         setMaximumIntegerDigits((Integer) getter.get(this));
    646         getter = NumberFormat.class.getDeclaredField("minimumIntegerDigits");
    647         getter.setAccessible(true);
    648         setMinimumIntegerDigits((Integer) getter.get(this));
    649         getter = NumberFormat.class.getDeclaredField("maximumFractionDigits");
    650         getter.setAccessible(true);
    651         setMaximumFractionDigits((Integer) getter.get(this));
    652         getter = NumberFormat.class.getDeclaredField("minimumFractionDigits");
    653         getter.setAccessible(true);
    654         setMinimumFractionDigits((Integer) getter.get(this));
    655         getter = NumberFormat.class.getDeclaredField("currency");
    656         getter.setAccessible(true);
    657         setCurrency((Currency) getter.get(this));
    658         getter = NumberFormat.class.getDeclaredField("parseStrict");
    659         getter.setAccessible(true);
    660         setParseStrict((Boolean) getter.get(this));
    661       } catch (IllegalArgumentException e) {
    662         throw new IOException(e);
    663       } catch (IllegalAccessException e) {
    664         throw new IOException(e);
    665       } catch (NoSuchFieldException e) {
    666         throw new IOException(e);
    667       } catch (SecurityException e) {
    668         throw new IOException(e);
    669       }
    670       // Finish initialization
    671       if (symbols == null) {
    672         symbols = getDefaultSymbols();
    673       }
    674       exportedProperties = new DecimalFormatProperties();
    675       refreshFormatter();
    676     }
    677   }
    678 
    679   //=====================================================================================//
    680   //                               FORMAT AND PARSE APIS                                 //
    681   //=====================================================================================//
    682 
    683   /**
    684    * {@inheritDoc}
    685    */
    686   @Override
    687   public StringBuffer format(double number, StringBuffer result, FieldPosition fieldPosition) {
    688     FormattedNumber output = formatter.format(number);
    689     output.populateFieldPosition(fieldPosition, result.length());
    690     output.appendTo(result);
    691     return result;
    692   }
    693 
    694   /**
    695    * {@inheritDoc}
    696    */
    697   @Override
    698   public StringBuffer format(long number, StringBuffer result, FieldPosition fieldPosition) {
    699     FormattedNumber output = formatter.format(number);
    700     output.populateFieldPosition(fieldPosition, result.length());
    701     output.appendTo(result);
    702     return result;
    703   }
    704 
    705   /**
    706    * {@inheritDoc}
    707    */
    708   @Override
    709   public StringBuffer format(BigInteger number, StringBuffer result, FieldPosition fieldPosition) {
    710     FormattedNumber output = formatter.format(number);
    711     output.populateFieldPosition(fieldPosition, result.length());
    712     output.appendTo(result);
    713     return result;
    714   }
    715 
    716   /**
    717    * {@inheritDoc}
    718    */
    719   @Override
    720   public StringBuffer format(
    721       java.math.BigDecimal number, StringBuffer result, FieldPosition fieldPosition) {
    722     FormattedNumber output = formatter.format(number);
    723     output.populateFieldPosition(fieldPosition, result.length());
    724     output.appendTo(result);
    725     return result;
    726   }
    727 
    728   /**
    729    * {@inheritDoc}
    730    */
    731   @Override
    732   public StringBuffer format(BigDecimal number, StringBuffer result, FieldPosition fieldPosition) {
    733     FormattedNumber output = formatter.format(number);
    734     output.populateFieldPosition(fieldPosition, result.length());
    735     output.appendTo(result);
    736     return result;
    737   }
    738 
    739   /**
    740    * {@inheritDoc}
    741    */
    742   @Override
    743   public AttributedCharacterIterator formatToCharacterIterator(Object obj) {
    744     if (!(obj instanceof Number)) throw new IllegalArgumentException();
    745     Number number = (Number) obj;
    746     FormattedNumber output = formatter.format(number);
    747     return output.getFieldIterator();
    748   }
    749 
    750   /**
    751    * {@inheritDoc}
    752    */
    753   @Override
    754   public StringBuffer format(CurrencyAmount currAmt, StringBuffer toAppendTo, FieldPosition pos) {
    755     FormattedNumber output = formatter.format(currAmt);
    756     output.populateFieldPosition(pos, toAppendTo.length());
    757     output.appendTo(toAppendTo);
    758     return toAppendTo;
    759   }
    760 
    761   /**
    762    * {@inheritDoc}
    763    */
    764   @Override
    765   public Number parse(String text, ParsePosition parsePosition) {
    766     DecimalFormatProperties pprops = threadLocalProperties.get();
    767     synchronized (this) {
    768       pprops.copyFrom(properties);
    769     }
    770     // Backwards compatibility: use currency parse mode if this is a currency instance
    771     Number result = Parse.parse(text, parsePosition, pprops, symbols);
    772     // Backwards compatibility: return android.icu.math.BigDecimal
    773     if (result instanceof java.math.BigDecimal) {
    774       result = safeConvertBigDecimal((java.math.BigDecimal) result);
    775     }
    776     return result;
    777   }
    778 
    779   /**
    780    * {@inheritDoc}
    781    */
    782   @Override
    783   public CurrencyAmount parseCurrency(CharSequence text, ParsePosition parsePosition) {
    784     try {
    785       DecimalFormatProperties pprops = threadLocalProperties.get();
    786       synchronized (this) {
    787         pprops.copyFrom(properties);
    788       }
    789       CurrencyAmount result = Parse.parseCurrency(text, parsePosition, pprops, symbols);
    790       if (result == null) return null;
    791       Number number = result.getNumber();
    792       // Backwards compatibility: return android.icu.math.BigDecimal
    793       if (number instanceof java.math.BigDecimal) {
    794         number = safeConvertBigDecimal((java.math.BigDecimal) number);
    795         result = new CurrencyAmount(number, result.getCurrency());
    796       }
    797       return result;
    798     } catch (ParseException e) {
    799       return null;
    800     }
    801   }
    802 
    803   //=====================================================================================//
    804   //                                GETTERS AND SETTERS                                  //
    805   //=====================================================================================//
    806 
    807   /**
    808    * Returns a copy of the decimal format symbols used by this formatter.
    809    *
    810    * @return desired DecimalFormatSymbols
    811    * @see DecimalFormatSymbols
    812    */
    813   public synchronized DecimalFormatSymbols getDecimalFormatSymbols() {
    814     return (DecimalFormatSymbols) symbols.clone();
    815   }
    816 
    817   /**
    818    * Sets the decimal format symbols used by this formatter. The formatter uses a copy of the
    819    * provided symbols.
    820    *
    821    * @param newSymbols desired DecimalFormatSymbols
    822    * @see DecimalFormatSymbols
    823    */
    824   public synchronized void setDecimalFormatSymbols(DecimalFormatSymbols newSymbols) {
    825     symbols = (DecimalFormatSymbols) newSymbols.clone();
    826     refreshFormatter();
    827   }
    828 
    829   /**
    830    * <strong>Affixes:</strong> Gets the positive prefix string currently being used to format
    831    * numbers.
    832    *
    833    * <p>If the affix was specified via the pattern, the string returned by this method will have
    834    * locale symbols substituted in place of special characters according to the LDML specification.
    835    * If the affix was specified via {@link #setPositivePrefix}, the string will be returned
    836    * literally.
    837    *
    838    * @return The string being prepended to positive numbers.
    839    */
    840   public synchronized String getPositivePrefix() {
    841     return formatter.format(1).getPrefix();
    842   }
    843 
    844   /**
    845    * <strong>Affixes:</strong> Sets the string to prepend to positive numbers. For example, if you
    846    * set the value "#", then the number 123 will be formatted as "#123" in the locale
    847    * <em>en-US</em>.
    848    *
    849    * <p>Using this method overrides the affix specified via the pattern, and unlike the pattern, the
    850    * string given to this method will be interpreted literally WITHOUT locale symbol substitutions.
    851    *
    852    * @param prefix The literal string to prepend to positive numbers.
    853    */
    854   public synchronized void setPositivePrefix(String prefix) {
    855     if (prefix == null) {
    856       throw new NullPointerException();
    857     }
    858     properties.setPositivePrefix(prefix);
    859     refreshFormatter();
    860   }
    861 
    862   /**
    863    * <strong>Affixes:</strong> Gets the negative prefix string currently being used to format
    864    * numbers.
    865    *
    866    * <p>If the affix was specified via the pattern, the string returned by this method will have
    867    * locale symbols substituted in place of special characters according to the LDML specification.
    868    * If the affix was specified via {@link #setNegativePrefix}, the string will be returned
    869    * literally.
    870    *
    871    * @return The string being prepended to negative numbers.
    872    */
    873   public synchronized String getNegativePrefix() {
    874     return formatter.format(-1).getPrefix();
    875   }
    876 
    877   /**
    878    * <strong>Affixes:</strong> Sets the string to prepend to negative numbers. For example, if you
    879    * set the value "#", then the number -123 will be formatted as "#123" in the locale
    880    * <em>en-US</em> (overriding the implicit default '-' in the pattern).
    881    *
    882    * <p>Using this method overrides the affix specified via the pattern, and unlike the pattern, the
    883    * string given to this method will be interpreted literally WITHOUT locale symbol substitutions.
    884    *
    885    * @param prefix The literal string to prepend to negative numbers.
    886    */
    887   public synchronized void setNegativePrefix(String prefix) {
    888     if (prefix == null) {
    889       throw new NullPointerException();
    890     }
    891     properties.setNegativePrefix(prefix);
    892     refreshFormatter();
    893   }
    894 
    895   /**
    896    * <strong>Affixes:</strong> Gets the positive suffix string currently being used to format
    897    * numbers.
    898    *
    899    * <p>If the affix was specified via the pattern, the string returned by this method will have
    900    * locale symbols substituted in place of special characters according to the LDML specification.
    901    * If the affix was specified via {@link #setPositiveSuffix}, the string will be returned
    902    * literally.
    903    *
    904    * @return The string being appended to positive numbers.
    905    */
    906   public synchronized String getPositiveSuffix() {
    907     return formatter.format(1).getSuffix();
    908   }
    909 
    910   /**
    911    * <strong>Affixes:</strong> Sets the string to append to positive numbers. For example, if you
    912    * set the value "#", then the number 123 will be formatted as "123#" in the locale
    913    * <em>en-US</em>.
    914    *
    915    * <p>Using this method overrides the affix specified via the pattern, and unlike the pattern, the
    916    * string given to this method will be interpreted literally WITHOUT locale symbol substitutions.
    917    *
    918    * @param suffix The literal string to append to positive numbers.
    919    */
    920   public synchronized void setPositiveSuffix(String suffix) {
    921     if (suffix == null) {
    922       throw new NullPointerException();
    923     }
    924     properties.setPositiveSuffix(suffix);
    925     refreshFormatter();
    926   }
    927 
    928   /**
    929    * <strong>Affixes:</strong> Gets the negative suffix string currently being used to format
    930    * numbers.
    931    *
    932    * <p>If the affix was specified via the pattern, the string returned by this method will have
    933    * locale symbols substituted in place of special characters according to the LDML specification.
    934    * If the affix was specified via {@link #setNegativeSuffix}, the string will be returned
    935    * literally.
    936    *
    937    * @return The string being appended to negative numbers.
    938    */
    939   public synchronized String getNegativeSuffix() {
    940     return formatter.format(-1).getSuffix();
    941   }
    942 
    943   /**
    944    * <strong>Affixes:</strong> Sets the string to append to negative numbers. For example, if you
    945    * set the value "#", then the number 123 will be formatted as "123#" in the locale
    946    * <em>en-US</em>.
    947    *
    948    * <p>Using this method overrides the affix specified via the pattern, and unlike the pattern, the
    949    * string given to this method will be interpreted literally WITHOUT locale symbol substitutions.
    950    *
    951    * @param suffix The literal string to append to negative numbers.
    952    */
    953   public synchronized void setNegativeSuffix(String suffix) {
    954     if (suffix == null) {
    955       throw new NullPointerException();
    956     }
    957     properties.setNegativeSuffix(suffix);
    958     refreshFormatter();
    959   }
    960 
    961   /**
    962    * <strong>[icu]</strong> Returns whether the sign is being shown on positive numbers.
    963    *
    964    * @see #setSignAlwaysShown
    965    * @deprecated ICU 59: This API is a technical preview. It may change in an upcoming release.
    966  * @hide draft / provisional / internal are hidden on Android
    967    */
    968   @Deprecated
    969   public synchronized boolean getSignAlwaysShown() {
    970     // This is not in the exported properties
    971     return properties.getSignAlwaysShown();
    972   }
    973 
    974   /**
    975    * Sets whether to always shown the plus sign ('+' in <em>en</em>) on positive numbers. The rules
    976    * in UTS #35 section 3.2.1 will be followed to ensure a locale-aware placement of the sign.
    977    *
    978    * <p>More specifically, the following strategy will be used to place the plus sign:
    979    *
    980    * <ol>
    981    *   <li><em>Patterns without a negative subpattern:</em> The locale's plus sign will be prepended
    982    *       to the positive prefix.
    983    *   <li><em>Patterns with a negative subpattern without a '-' sign (e.g., accounting):</em> The
    984    *       locale's plus sign will be prepended to the positive prefix, as in case 1.
    985    *   <li><em>Patterns with a negative subpattern that has a '-' sign:</em> The locale's plus sign
    986    *       will substitute the '-' in the negative subpattern. The positive subpattern will be
    987    *       unused.
    988    * </ol>
    989    *
    990    * This method is designed to be used <em>instead of</em> applying a pattern containing an
    991    * explicit plus sign, such as "+0;-0". The behavior when combining this method with explicit plus
    992    * signs in the pattern is undefined.
    993    *
    994    * @param value true to always show a sign; false to hide the sign on positive numbers.
    995    * @deprecated ICU 59: This API is technical preview. It may change in an upcoming release.
    996  * @hide draft / provisional / internal are hidden on Android
    997    */
    998   @Deprecated
    999   public synchronized void setSignAlwaysShown(boolean value) {
   1000     properties.setSignAlwaysShown(value);
   1001     refreshFormatter();
   1002   }
   1003 
   1004   /**
   1005    * Returns the multiplier being applied to numbers before they are formatted.
   1006    *
   1007    * @see #setMultiplier
   1008    */
   1009   public synchronized int getMultiplier() {
   1010     if (properties.getMultiplier() != null) {
   1011       return properties.getMultiplier().intValue();
   1012     } else {
   1013       return (int) Math.pow(10, properties.getMagnitudeMultiplier());
   1014     }
   1015   }
   1016 
   1017   /**
   1018    * Sets a number that will be used to multiply all numbers prior to formatting. For example, when
   1019    * formatting percents, a multiplier of 100 can be used.
   1020    *
   1021    * <p>If a percent or permille sign is specified in the pattern, the multiplier is automatically
   1022    * set to 100 or 1000, respectively.
   1023    *
   1024    * <p>If the number specified here is a power of 10, a more efficient code path will be used.
   1025    *
   1026    * @param multiplier The number by which all numbers passed to {@link #format} will be multiplied.
   1027    * @throws IllegalArgumentException If the given multiplier is zero.
   1028    */
   1029   public synchronized void setMultiplier(int multiplier) {
   1030     if (multiplier == 0) {
   1031       throw new IllegalArgumentException("Multiplier must be nonzero.");
   1032     }
   1033 
   1034     // Try to convert to a magnitude multiplier first
   1035     int delta = 0;
   1036     int value = multiplier;
   1037     while (multiplier != 1) {
   1038       delta++;
   1039       int temp = value / 10;
   1040       if (temp * 10 != value) {
   1041         delta = -1;
   1042         break;
   1043       }
   1044       value = temp;
   1045     }
   1046     if (delta != -1) {
   1047       properties.setMagnitudeMultiplier(delta);
   1048     } else {
   1049       properties.setMultiplier(java.math.BigDecimal.valueOf(multiplier));
   1050     }
   1051     refreshFormatter();
   1052   }
   1053 
   1054   /**
   1055    * <strong>[icu]</strong> Returns the increment to which numbers are being rounded.
   1056    *
   1057    * @see #setRoundingIncrement
   1058    */
   1059   public synchronized java.math.BigDecimal getRoundingIncrement() {
   1060     return exportedProperties.getRoundingIncrement();
   1061   }
   1062 
   1063   /**
   1064    * <strong>[icu]</strong> <strong>Rounding and Digit Limits:</strong> Sets an increment, or interval, to which
   1065    * numbers are rounded. For example, a rounding increment of 0.05 will cause the number 1.23 to be
   1066    * rounded to 1.25 in the default rounding mode.
   1067    *
   1068    * <p>The rounding increment can be specified via the pattern string: for example, the pattern
   1069    * "#,##0.05" encodes a rounding increment of 0.05.
   1070    *
   1071    * <p>The rounding increment is applied <em>after</em> any multipliers might take effect; for
   1072    * example, in scientific notation or when {@link #setMultiplier} is used.
   1073    *
   1074    * <p>See {@link #setMaximumFractionDigits} and {@link #setMaximumSignificantDigits} for two other
   1075    * ways of specifying rounding strategies.
   1076    *
   1077    * @param increment The increment to which numbers are to be rounded.
   1078    * @see #setRoundingMode
   1079    * @see #setMaximumFractionDigits
   1080    * @see #setMaximumSignificantDigits
   1081    */
   1082   public synchronized void setRoundingIncrement(java.math.BigDecimal increment) {
   1083     // Backwards compatibility: ignore rounding increment if zero,
   1084     // and instead set maximum fraction digits.
   1085     if (increment != null && increment.compareTo(java.math.BigDecimal.ZERO) == 0) {
   1086       properties.setMaximumFractionDigits(Integer.MAX_VALUE);
   1087       return;
   1088     }
   1089 
   1090     properties.setRoundingIncrement(increment);
   1091     refreshFormatter();
   1092   }
   1093 
   1094   /**
   1095    * <strong>[icu]</strong> <strong>Rounding and Digit Limits:</strong> Overload of {@link
   1096    * #setRoundingIncrement(java.math.BigDecimal)}.
   1097    *
   1098    * @param increment The increment to which numbers are to be rounded.
   1099    * @see #setRoundingIncrement
   1100    */
   1101   public synchronized void setRoundingIncrement(BigDecimal increment) {
   1102     java.math.BigDecimal javaBigDecimal = (increment == null) ? null : increment.toBigDecimal();
   1103     setRoundingIncrement(javaBigDecimal);
   1104   }
   1105 
   1106   /**
   1107    * <strong>[icu]</strong> <strong>Rounding and Digit Limits:</strong> Overload of {@link
   1108    * #setRoundingIncrement(java.math.BigDecimal)}.
   1109    *
   1110    * @param increment The increment to which numbers are to be rounded.
   1111    * @see #setRoundingIncrement
   1112    */
   1113   public synchronized void setRoundingIncrement(double increment) {
   1114     if (increment == 0) {
   1115       setRoundingIncrement((java.math.BigDecimal) null);
   1116     } else {
   1117       java.math.BigDecimal javaBigDecimal = java.math.BigDecimal.valueOf(increment);
   1118       setRoundingIncrement(javaBigDecimal);
   1119     }
   1120   }
   1121 
   1122   /**
   1123    * Returns the rounding mode being used to round numbers.
   1124    *
   1125    * @see #setRoundingMode
   1126    */
   1127   @Override
   1128   public synchronized int getRoundingMode() {
   1129     RoundingMode mode = exportedProperties.getRoundingMode();
   1130     return (mode == null) ? 0 : mode.ordinal();
   1131   }
   1132 
   1133   /**
   1134    * <strong>Rounding and Digit Limits:</strong> Sets the {@link RoundingMode} used to round
   1135    * numbers. The default rounding mode is HALF_EVEN, which rounds decimals to their closest whole
   1136    * number, and rounds to the closest even number if at the midpoint.
   1137    *
   1138    * <p>For more detail on rounding modes, see <a
   1139    * href="http://userguide.icu-project.org/formatparse/numbers/rounding-modes">the ICU User
   1140    * Guide</a>.
   1141    *
   1142    * <p>For backwards compatibility, the rounding mode is specified as an int argument, which can be
   1143    * from either the constants in {@link BigDecimal} or the ordinal value of {@link RoundingMode}.
   1144    * The following two calls are functionally equivalent.
   1145    *
   1146    * <pre>
   1147    * df.setRoundingMode(BigDecimal.ROUND_CEILING);
   1148    * df.setRoundingMode(RoundingMode.CEILING.ordinal());
   1149    * </pre>
   1150    *
   1151    * @param roundingMode The integer constant rounding mode to use when formatting numbers.
   1152    */
   1153   @Override
   1154   public synchronized void setRoundingMode(int roundingMode) {
   1155     properties.setRoundingMode(RoundingMode.valueOf(roundingMode));
   1156     refreshFormatter();
   1157   }
   1158 
   1159   /**
   1160    * <strong>[icu]</strong> Returns the {@link java.math.MathContext} being used to round numbers.
   1161    *
   1162    * @see #setMathContext
   1163    */
   1164   public synchronized java.math.MathContext getMathContext() {
   1165     java.math.MathContext mathContext = exportedProperties.getMathContext();
   1166     assert mathContext != null;
   1167     return mathContext;
   1168   }
   1169 
   1170   /**
   1171    * <strong>[icu]</strong> <strong>Rounding and Digit Limits:</strong> Sets the {@link java.math.MathContext} used
   1172    * to round numbers. A "math context" encodes both a rounding mode and a number of significant
   1173    * digits. Most users should call {@link #setRoundingMode} and/or {@link
   1174    * #setMaximumSignificantDigits} instead of this method.
   1175    *
   1176    * <p>When formatting, since no division is ever performed, the default MathContext is unlimited
   1177    * significant digits. However, when division occurs during parsing to correct for percentages and
   1178    * multipliers, a MathContext of 34 digits, the IEEE 754R Decimal128 standard, is used by default.
   1179    * If you require more than 34 digits when parsing, you can set a custom MathContext using this
   1180    * method.
   1181    *
   1182    * @param mathContext The MathContext to use when rounding numbers.
   1183    * @see java.math.MathContext
   1184    */
   1185   public synchronized void setMathContext(java.math.MathContext mathContext) {
   1186     properties.setMathContext(mathContext);
   1187     refreshFormatter();
   1188   }
   1189 
   1190   // Remember the ICU math context form in order to be able to return it from the API.
   1191   // NOTE: This value is not serialized. (should it be?)
   1192   private transient int icuMathContextForm = MathContext.PLAIN;
   1193 
   1194   /**
   1195    * <strong>[icu]</strong> Returns the {@link android.icu.math.MathContext} being used to round numbers.
   1196    *
   1197    * @see #setMathContext
   1198    */
   1199   public synchronized MathContext getMathContextICU() {
   1200     java.math.MathContext mathContext = getMathContext();
   1201     return new MathContext(
   1202         mathContext.getPrecision(),
   1203         icuMathContextForm,
   1204         false,
   1205         mathContext.getRoundingMode().ordinal());
   1206   }
   1207 
   1208   /**
   1209    * <strong>[icu]</strong> <strong>Rounding and Digit Limits:</strong> Overload of {@link #setMathContext} for
   1210    * {@link android.icu.math.MathContext}.
   1211    *
   1212    * @param mathContextICU The MathContext to use when rounding numbers.
   1213    * @see #setMathContext(java.math.MathContext)
   1214    */
   1215   public synchronized void setMathContextICU(MathContext mathContextICU) {
   1216     icuMathContextForm = mathContextICU.getForm();
   1217     java.math.MathContext mathContext;
   1218     if (mathContextICU.getLostDigits()) {
   1219       // The getLostDigits() feature in ICU MathContext means "throw an ArithmeticException if
   1220       // rounding causes digits to be lost". That feature is called RoundingMode.UNNECESSARY in
   1221       // Java MathContext.
   1222       mathContext = new java.math.MathContext(mathContextICU.getDigits(), RoundingMode.UNNECESSARY);
   1223     } else {
   1224       mathContext =
   1225           new java.math.MathContext(
   1226               mathContextICU.getDigits(), RoundingMode.valueOf(mathContextICU.getRoundingMode()));
   1227     }
   1228     setMathContext(mathContext);
   1229   }
   1230 
   1231   /**
   1232    * Returns the effective minimum number of digits before the decimal separator.
   1233    *
   1234    * @see #setMinimumIntegerDigits
   1235    */
   1236   @Override
   1237   public synchronized int getMinimumIntegerDigits() {
   1238     return exportedProperties.getMinimumIntegerDigits();
   1239   }
   1240 
   1241   /**
   1242    * <strong>Rounding and Digit Limits:</strong> Sets the minimum number of digits to display before
   1243    * the decimal separator. If the number has fewer than this many digits, the number is padded with
   1244    * zeros.
   1245    *
   1246    * <p>For example, if minimum integer digits is 3, the number 12.3 will be printed as "001.23".
   1247    *
   1248    * <p>Minimum integer and minimum and maximum fraction digits can be specified via the pattern
   1249    * string. For example, "#,#00.00#" has 2 minimum integer digits, 2 minimum fraction digits, and 3
   1250    * maximum fraction digits. Note that it is not possible to specify maximium integer digits in the
   1251    * pattern except in scientific notation.
   1252    *
   1253    * <p>If minimum and maximum integer, fraction, or significant digits conflict with each other,
   1254    * the most recently specified value is used. For example, if there is a formatter with minInt=5,
   1255    * and then you set maxInt=3, then minInt will be changed to 3.
   1256    *
   1257    * @param value The minimum number of digits before the decimal separator.
   1258    */
   1259   @Override
   1260   public synchronized void setMinimumIntegerDigits(int value) {
   1261     // For backwards compatibility, conflicting min/max need to keep the most recent setting.
   1262     int max = properties.getMaximumIntegerDigits();
   1263     if (max >= 0 && max < value) {
   1264       properties.setMaximumIntegerDigits(value);
   1265     }
   1266     properties.setMinimumIntegerDigits(value);
   1267     refreshFormatter();
   1268   }
   1269 
   1270   /**
   1271    * Returns the effective maximum number of digits before the decimal separator.
   1272    *
   1273    * @see #setMaximumIntegerDigits
   1274    */
   1275   @Override
   1276   public synchronized int getMaximumIntegerDigits() {
   1277     return exportedProperties.getMaximumIntegerDigits();
   1278   }
   1279 
   1280   /**
   1281    * <strong>Rounding and Digit Limits:</strong> Sets the maximum number of digits to display before
   1282    * the decimal separator. If the number has more than this many digits, the number is truncated.
   1283    *
   1284    * <p>For example, if maximum integer digits is 3, the number 12345 will be printed as "345".
   1285    *
   1286    * <p>Minimum integer and minimum and maximum fraction digits can be specified via the pattern
   1287    * string. For example, "#,#00.00#" has 2 minimum integer digits, 2 minimum fraction digits, and 3
   1288    * maximum fraction digits. Note that it is not possible to specify maximium integer digits in the
   1289    * pattern except in scientific notation.
   1290    *
   1291    * <p>If minimum and maximum integer, fraction, or significant digits conflict with each other,
   1292    * the most recently specified value is used. For example, if there is a formatter with minInt=5,
   1293    * and then you set maxInt=3, then minInt will be changed to 3.
   1294    *
   1295    * @param value The maximum number of digits before the decimal separator.
   1296    */
   1297   @Override
   1298   public synchronized void setMaximumIntegerDigits(int value) {
   1299     int min = properties.getMinimumIntegerDigits();
   1300     if (min >= 0 && min > value) {
   1301       properties.setMinimumIntegerDigits(value);
   1302     }
   1303     properties.setMaximumIntegerDigits(value);
   1304     refreshFormatter();
   1305   }
   1306 
   1307   /**
   1308    * Returns the effective minimum number of integer digits after the decimal separator.
   1309    *
   1310    * @see #setMaximumIntegerDigits
   1311    */
   1312   @Override
   1313   public synchronized int getMinimumFractionDigits() {
   1314     return exportedProperties.getMinimumFractionDigits();
   1315   }
   1316 
   1317   /**
   1318    * <strong>Rounding and Digit Limits:</strong> Sets the minimum number of digits to display after
   1319    * the decimal separator. If the number has fewer than this many digits, the number is padded with
   1320    * zeros.
   1321    *
   1322    * <p>For example, if minimum fraction digits is 2, the number 123.4 will be printed as "123.40".
   1323    *
   1324    * <p>Minimum integer and minimum and maximum fraction digits can be specified via the pattern
   1325    * string. For example, "#,#00.00#" has 2 minimum integer digits, 2 minimum fraction digits, and 3
   1326    * maximum fraction digits. Note that it is not possible to specify maximium integer digits in the
   1327    * pattern except in scientific notation.
   1328    *
   1329    * <p>If minimum and maximum integer, fraction, or significant digits conflict with each other,
   1330    * the most recently specified value is used. For example, if there is a formatter with minInt=5,
   1331    * and then you set maxInt=3, then minInt will be changed to 3.
   1332    *
   1333    * <p>See {@link #setRoundingIncrement} and {@link #setMaximumSignificantDigits} for two other
   1334    * ways of specifying rounding strategies.
   1335    *
   1336    * @param value The minimum number of integer digits after the decimal separator.
   1337    * @see #setRoundingMode
   1338    * @see #setRoundingIncrement
   1339    * @see #setMaximumSignificantDigits
   1340    */
   1341   @Override
   1342   public synchronized void setMinimumFractionDigits(int value) {
   1343     int max = properties.getMaximumFractionDigits();
   1344     if (max >= 0 && max < value) {
   1345       properties.setMaximumFractionDigits(value);
   1346     }
   1347     properties.setMinimumFractionDigits(value);
   1348     refreshFormatter();
   1349   }
   1350 
   1351   /**
   1352    * Returns the effective maximum number of integer digits after the decimal separator.
   1353    *
   1354    * @see #setMaximumIntegerDigits
   1355    */
   1356   @Override
   1357   public synchronized int getMaximumFractionDigits() {
   1358     return exportedProperties.getMaximumFractionDigits();
   1359   }
   1360 
   1361   /**
   1362    * <strong>Rounding and Digit Limits:</strong> Sets the maximum number of digits to display after
   1363    * the decimal separator. If the number has more than this many digits, the number is rounded
   1364    * according to the rounding mode.
   1365    *
   1366    * <p>For example, if maximum fraction digits is 2, the number 123.456 will be printed as
   1367    * "123.46".
   1368    *
   1369    * <p>Minimum integer and minimum and maximum fraction digits can be specified via the pattern
   1370    * string. For example, "#,#00.00#" has 2 minimum integer digits, 2 minimum fraction digits, and 3
   1371    * maximum fraction digits. Note that it is not possible to specify maximium integer digits in the
   1372    * pattern except in scientific notation.
   1373    *
   1374    * <p>If minimum and maximum integer, fraction, or significant digits conflict with each other,
   1375    * the most recently specified value is used. For example, if there is a formatter with minInt=5,
   1376    * and then you set maxInt=3, then minInt will be changed to 3.
   1377    *
   1378    * @param value The maximum number of integer digits after the decimal separator.
   1379    * @see #setRoundingMode
   1380    */
   1381   @Override
   1382   public synchronized void setMaximumFractionDigits(int value) {
   1383     int min = properties.getMinimumFractionDigits();
   1384     if (min >= 0 && min > value) {
   1385       properties.setMinimumFractionDigits(value);
   1386     }
   1387     properties.setMaximumFractionDigits(value);
   1388     refreshFormatter();
   1389   }
   1390 
   1391   /**
   1392    * <strong>[icu]</strong> Returns whether significant digits are being used in rounding.
   1393    *
   1394    * @see #setSignificantDigitsUsed
   1395    */
   1396   public synchronized boolean areSignificantDigitsUsed() {
   1397     return properties.getMinimumSignificantDigits() != -1
   1398         || properties.getMaximumSignificantDigits() != -1;
   1399   }
   1400 
   1401   /**
   1402    * <strong>[icu]</strong> <strong>Rounding and Digit Limits:</strong> Sets whether significant digits are to be
   1403    * used in rounding.
   1404    *
   1405    * <p>Calling <code>df.setSignificantDigitsUsed(true)</code> is functionally equivalent to:
   1406    *
   1407    * <pre>
   1408    * df.setMinimumSignificantDigits(1);
   1409    * df.setMaximumSignificantDigits(6);
   1410    * </pre>
   1411    *
   1412    * @param useSignificantDigits true to enable significant digit rounding; false to disable it.
   1413    */
   1414   public synchronized void setSignificantDigitsUsed(boolean useSignificantDigits) {
   1415     if (useSignificantDigits) {
   1416       // These are the default values from the old implementation.
   1417       properties.setMinimumSignificantDigits(1);
   1418       properties.setMaximumSignificantDigits(6);
   1419     } else {
   1420       properties.setMinimumSignificantDigits(-1);
   1421       properties.setMaximumSignificantDigits(-1);
   1422     }
   1423     refreshFormatter();
   1424   }
   1425 
   1426   /**
   1427    * <strong>[icu]</strong> Returns the effective minimum number of significant digits displayed.
   1428    *
   1429    * @see #setMinimumSignificantDigits
   1430    */
   1431   public synchronized int getMinimumSignificantDigits() {
   1432     return exportedProperties.getMinimumSignificantDigits();
   1433   }
   1434 
   1435   /**
   1436    * <strong>[icu]</strong> <strong>Rounding and Digit Limits:</strong> Sets the minimum number of significant
   1437    * digits to be displayed. If the number of significant digits is less than this value, the number
   1438    * will be padded with zeros as necessary.
   1439    *
   1440    * <p>For example, if minimum significant digits is 3 and the number is 1.2, the number will be
   1441    * printed as "1.20".
   1442    *
   1443    * <p>If minimum and maximum integer, fraction, or significant digits conflict with each other,
   1444    * the most recently specified value is used. For example, if there is a formatter with minInt=5,
   1445    * and then you set maxInt=3, then minInt will be changed to 3.
   1446    *
   1447    * @param value The minimum number of significant digits to display.
   1448    */
   1449   public synchronized void setMinimumSignificantDigits(int value) {
   1450     int max = properties.getMaximumSignificantDigits();
   1451     if (max >= 0 && max < value) {
   1452       properties.setMaximumSignificantDigits(value);
   1453     }
   1454     properties.setMinimumSignificantDigits(value);
   1455     refreshFormatter();
   1456   }
   1457 
   1458   /**
   1459    * <strong>[icu]</strong> Returns the effective maximum number of significant digits displayed.
   1460    *
   1461    * @see #setMaximumSignificantDigits
   1462    */
   1463   public synchronized int getMaximumSignificantDigits() {
   1464     return exportedProperties.getMaximumSignificantDigits();
   1465   }
   1466 
   1467   /**
   1468    * <strong>[icu]</strong> <strong>Rounding and Digit Limits:</strong> Sets the maximum number of significant
   1469    * digits to be displayed. If the number of significant digits in the number exceeds this value,
   1470    * the number will be rounded according to the current rounding mode.
   1471    *
   1472    * <p>For example, if maximum significant digits is 3 and the number is 12345, the number will be
   1473    * printed as "12300".
   1474    *
   1475    * <p>If minimum and maximum integer, fraction, or significant digits conflict with each other,
   1476    * the most recently specified value is used. For example, if there is a formatter with minInt=5,
   1477    * and then you set maxInt=3, then minInt will be changed to 3.
   1478    *
   1479    * <p>See {@link #setRoundingIncrement} and {@link #setMaximumFractionDigits} for two other ways
   1480    * of specifying rounding strategies.
   1481    *
   1482    * @param value The maximum number of significant digits to display.
   1483    * @see #setRoundingMode
   1484    * @see #setRoundingIncrement
   1485    * @see #setMaximumFractionDigits
   1486    */
   1487   public synchronized void setMaximumSignificantDigits(int value) {
   1488     int min = properties.getMinimumSignificantDigits();
   1489     if (min >= 0 && min > value) {
   1490       properties.setMinimumSignificantDigits(value);
   1491     }
   1492     properties.setMaximumSignificantDigits(value);
   1493     refreshFormatter();
   1494   }
   1495 
   1496   /**
   1497    * Returns the minimum number of characters in formatted output.
   1498    *
   1499    * @see #setFormatWidth
   1500    */
   1501   public synchronized int getFormatWidth() {
   1502     return properties.getFormatWidth();
   1503   }
   1504 
   1505   /**
   1506    * <strong>Padding:</strong> Sets the minimum width of the string output by the formatting
   1507    * pipeline. For example, if padding is enabled and paddingWidth is set to 6, formatting the
   1508    * number "3.14159" with the pattern "0.00" will result in "3.14" if '' is your padding string.
   1509    *
   1510    * <p>If the number is longer than your padding width, the number will display as if no padding
   1511    * width had been specified, which may result in strings longer than the padding width.
   1512    *
   1513    * <p>Padding can be specified in the pattern string using the '*' symbol. For example, the format
   1514    * "*x######0" has a format width of 7 and a pad character of 'x'.
   1515    *
   1516    * <p>Padding is currently counted in UTF-16 code units; see <a
   1517    * href="http://bugs.icu-project.org/trac/ticket/13034">ticket #13034</a> for more information.
   1518    *
   1519    * @param width The minimum number of characters in the output.
   1520    * @see #setPadCharacter
   1521    * @see #setPadPosition
   1522    */
   1523   public synchronized void setFormatWidth(int width) {
   1524     properties.setFormatWidth(width);
   1525     refreshFormatter();
   1526   }
   1527 
   1528   /**
   1529    * <strong>[icu]</strong> Returns the character used for padding.
   1530    *
   1531    * @see #setPadCharacter
   1532    */
   1533   public synchronized char getPadCharacter() {
   1534     CharSequence paddingString = properties.getPadString();
   1535     if (paddingString == null) {
   1536       return '.'; // TODO: Is this the correct behavior?
   1537     } else {
   1538       return paddingString.charAt(0);
   1539     }
   1540   }
   1541 
   1542   /**
   1543    * <strong>[icu]</strong> <strong>Padding:</strong> Sets the character used to pad numbers that are narrower than
   1544    * the width specified in {@link #setFormatWidth}.
   1545    *
   1546    * <p>In the pattern string, the padding character is the token that follows '*' before or after
   1547    * the prefix or suffix.
   1548    *
   1549    * @param padChar The character used for padding.
   1550    * @see #setFormatWidth
   1551    */
   1552   public synchronized void setPadCharacter(char padChar) {
   1553     properties.setPadString(Character.toString(padChar));
   1554     refreshFormatter();
   1555   }
   1556 
   1557   /**
   1558    * <strong>[icu]</strong> Returns the position used for padding.
   1559    *
   1560    * @see #setPadPosition
   1561    */
   1562   public synchronized int getPadPosition() {
   1563     PadPosition loc = properties.getPadPosition();
   1564     return (loc == null) ? PAD_BEFORE_PREFIX : loc.toOld();
   1565   }
   1566 
   1567   /**
   1568    * <strong>[icu]</strong> <strong>Padding:</strong> Sets the position where to insert the pad character when
   1569    * narrower than the width specified in {@link #setFormatWidth}. For example, consider the pattern
   1570    * "P123S" with padding width 8 and padding char "*". The four positions are:
   1571    *
   1572    * <ul>
   1573    *   <li>{@link DecimalFormat#PAD_BEFORE_PREFIX}  "***P123S"
   1574    *   <li>{@link DecimalFormat#PAD_AFTER_PREFIX}  "P***123S"
   1575    *   <li>{@link DecimalFormat#PAD_BEFORE_SUFFIX}  "P123***S"
   1576    *   <li>{@link DecimalFormat#PAD_AFTER_SUFFIX}  "P123S***"
   1577    * </ul>
   1578    *
   1579    * @param padPos The position used for padding.
   1580    * @see #setFormatWidth
   1581    */
   1582   public synchronized void setPadPosition(int padPos) {
   1583     properties.setPadPosition(PadPosition.fromOld(padPos));
   1584     refreshFormatter();
   1585   }
   1586 
   1587   /**
   1588    * <strong>[icu]</strong> Returns whether scientific (exponential) notation is enabled on this formatter.
   1589    *
   1590    * @see #setScientificNotation
   1591    */
   1592   public synchronized boolean isScientificNotation() {
   1593     return properties.getMinimumExponentDigits() != -1;
   1594   }
   1595 
   1596   /**
   1597    * <strong>[icu]</strong> <strong>Scientific Notation:</strong> Sets whether this formatter should print in
   1598    * scientific (exponential) notation. For example, if scientific notation is enabled, the number
   1599    * 123000 will be printed as "1.23E5" in locale <em>en-US</em>. A locale-specific symbol is used
   1600    * as the exponent separator.
   1601    *
   1602    * <p>Calling <code>df.setScientificNotation(true)</code> is functionally equivalent to calling
   1603    * <code>df.setMinimumExponentDigits(1)</code>.
   1604    *
   1605    * @param useScientific true to enable scientific notation; false to disable it.
   1606    * @see #setMinimumExponentDigits
   1607    */
   1608   public synchronized void setScientificNotation(boolean useScientific) {
   1609     if (useScientific) {
   1610       properties.setMinimumExponentDigits(1);
   1611     } else {
   1612       properties.setMinimumExponentDigits(-1);
   1613     }
   1614     refreshFormatter();
   1615   }
   1616 
   1617   /**
   1618    * <strong>[icu]</strong> Returns the minimum number of digits printed in the exponent in scientific notation.
   1619    *
   1620    * @see #setMinimumExponentDigits
   1621    */
   1622   public synchronized byte getMinimumExponentDigits() {
   1623     return (byte) properties.getMinimumExponentDigits();
   1624   }
   1625 
   1626   /**
   1627    * <strong>[icu]</strong> <strong>Scientific Notation:</strong> Sets the minimum number of digits to be printed in
   1628    * the exponent. For example, if minimum exponent digits is 3, the number 123000 will be printed
   1629    * as "1.23E005".
   1630    *
   1631    * <p>This setting corresponds to the number of zeros after the 'E' in a pattern string such as
   1632    * "0.00E000".
   1633    *
   1634    * @param minExpDig The minimum number of digits in the exponent.
   1635    */
   1636   public synchronized void setMinimumExponentDigits(byte minExpDig) {
   1637     properties.setMinimumExponentDigits(minExpDig);
   1638     refreshFormatter();
   1639   }
   1640 
   1641   /**
   1642    * <strong>[icu]</strong> Returns whether the sign (plus or minus) is always printed in scientific notation.
   1643    *
   1644    * @see #setExponentSignAlwaysShown
   1645    */
   1646   public synchronized boolean isExponentSignAlwaysShown() {
   1647     return properties.getExponentSignAlwaysShown();
   1648   }
   1649 
   1650   /**
   1651    * <strong>[icu]</strong> <strong>Scientific Notation:</strong> Sets whether the sign (plus or minus) is always to
   1652    * be shown in the exponent in scientific notation. For example, if this setting is enabled, the
   1653    * number 123000 will be printed as "1.23E+5" in locale <em>en-US</em>. The number 0.0000123 will
   1654    * always be printed as "1.23E-5" in locale <em>en-US</em> whether or not this setting is enabled.
   1655    *
   1656    * <p>This setting corresponds to the '+' in a pattern such as "0.00E+0".
   1657    *
   1658    * @param expSignAlways true to always shown the sign in the exponent; false to show it for
   1659    *     negatives but not positives.
   1660    */
   1661   public synchronized void setExponentSignAlwaysShown(boolean expSignAlways) {
   1662     properties.setExponentSignAlwaysShown(expSignAlways);
   1663     refreshFormatter();
   1664   }
   1665 
   1666   /**
   1667    * Returns whether or not grouping separators are being printed in the output.
   1668    *
   1669    * @see #setGroupingUsed
   1670    */
   1671   @Override
   1672   public synchronized boolean isGroupingUsed() {
   1673     return properties.getGroupingSize() > 0 || properties.getSecondaryGroupingSize() > 0;
   1674   }
   1675 
   1676   /**
   1677    * <strong>Grouping:</strong> Sets whether grouping is to be used when formatting numbers.
   1678    * Grouping means whether the thousands, millions, billions, and larger powers of ten should be
   1679    * separated by a grouping separator (a comma in <em>en-US</em>).
   1680    *
   1681    * <p>For example, if grouping is enabled, 12345 will be printed as "12,345" in <em>en-US</em>. If
   1682    * grouping were disabled, it would instead be printed as simply "12345".
   1683    *
   1684    * <p>Calling <code>df.setGroupingUsed(true)</code> is functionally equivalent to setting grouping
   1685    * size to 3, as in <code>df.setGroupingSize(3)</code>.
   1686    *
   1687    * @param enabled true to enable grouping separators; false to disable them.
   1688    * @see #setGroupingSize
   1689    * @see #setSecondaryGroupingSize
   1690    */
   1691   @Override
   1692   public synchronized void setGroupingUsed(boolean enabled) {
   1693     if (enabled) {
   1694       // Set to a reasonable default value
   1695       properties.setGroupingSize(3);
   1696     } else {
   1697       properties.setGroupingSize(0);
   1698       properties.setSecondaryGroupingSize(0);
   1699     }
   1700     refreshFormatter();
   1701   }
   1702 
   1703   /**
   1704    * Returns the primary grouping size in use.
   1705    *
   1706    * @see #setGroupingSize
   1707    */
   1708   public synchronized int getGroupingSize() {
   1709     return properties.getGroupingSize();
   1710   }
   1711 
   1712   /**
   1713    * <strong>Grouping:</strong> Sets the primary grouping size (distance between grouping
   1714    * separators) used when formatting large numbers. For most locales, this defaults to 3: the
   1715    * number of digits between the ones and thousands place, between thousands and millions, and so
   1716    * forth.
   1717    *
   1718    * <p>For example, with a grouping size of 3, the number 1234567 will be formatted as "1,234,567".
   1719    *
   1720    * <p>Grouping size can also be specified in the pattern: for example, "#,##0" corresponds to a
   1721    * grouping size of 3.
   1722    *
   1723    * @param width The grouping size to use.
   1724    * @see #setSecondaryGroupingSize
   1725    */
   1726   public synchronized void setGroupingSize(int width) {
   1727     properties.setGroupingSize(width);
   1728     refreshFormatter();
   1729   }
   1730 
   1731   /**
   1732    * <strong>[icu]</strong> Returns the secondary grouping size in use.
   1733    *
   1734    * @see #setSecondaryGroupingSize
   1735    */
   1736   public synchronized int getSecondaryGroupingSize() {
   1737     int grouping1 = properties.getGroupingSize();
   1738     int grouping2 = properties.getSecondaryGroupingSize();
   1739     if (grouping1 == grouping2 || grouping2 < 0) {
   1740       return 0;
   1741     }
   1742     return properties.getSecondaryGroupingSize();
   1743   }
   1744 
   1745   /**
   1746    * <strong>[icu]</strong> <strong>Grouping:</strong> Sets the secondary grouping size (distance between grouping
   1747    * separators after the first separator) used when formatting large numbers. In many south Asian
   1748    * locales, this is set to 2.
   1749    *
   1750    * <p>For example, with primary grouping size 3 and secondary grouping size 2, the number 1234567
   1751    * will be formatted as "12,34,567".
   1752    *
   1753    * <p>Grouping size can also be specified in the pattern: for example, "#,##,##0" corresponds to a
   1754    * primary grouping size of 3 and a secondary grouping size of 2.
   1755    *
   1756    * @param width The secondary grouping size to use.
   1757    * @see #setGroupingSize
   1758    */
   1759   public synchronized void setSecondaryGroupingSize(int width) {
   1760     properties.setSecondaryGroupingSize(width);
   1761     refreshFormatter();
   1762   }
   1763 
   1764   /**
   1765    * <strong>[icu]</strong> Returns the minimum number of digits before grouping is triggered.
   1766    *
   1767    * @see #setMinimumGroupingDigits
   1768    * @deprecated ICU 59: This API is a technical preview. It may change in an upcoming release.
   1769  * @hide draft / provisional / internal are hidden on Android
   1770    */
   1771   @Deprecated
   1772   public synchronized int getMinimumGroupingDigits() {
   1773     // Only 1 and 2 are supported right now.
   1774     if (properties.getMinimumGroupingDigits() == 2) {
   1775       return 2;
   1776     } else {
   1777       return 1;
   1778     }
   1779   }
   1780 
   1781   /**
   1782    * <strong>[icu]</strong> Sets the minimum number of digits that must be before the first grouping separator in
   1783    * order for the grouping separator to be printed. For example, if minimum grouping digits is set
   1784    * to 2, in <em>en-US</em>, 1234 will be printed as "1234" and 12345 will be printed as "12,345".
   1785    *
   1786    * @param number The minimum number of digits before grouping is triggered.
   1787    * @deprecated ICU 59: This API is a technical preview. It may change in an upcoming release.
   1788  * @hide draft / provisional / internal are hidden on Android
   1789    */
   1790   @Deprecated
   1791   public synchronized void setMinimumGroupingDigits(int number) {
   1792     properties.setMinimumGroupingDigits(number);
   1793     refreshFormatter();
   1794   }
   1795 
   1796   /**
   1797    * Returns whether the decimal separator is shown on integers.
   1798    *
   1799    * @see #setDecimalSeparatorAlwaysShown
   1800    */
   1801   public synchronized boolean isDecimalSeparatorAlwaysShown() {
   1802     return properties.getDecimalSeparatorAlwaysShown();
   1803   }
   1804 
   1805   /**
   1806    * <strong>Separators:</strong> Sets whether the decimal separator (a period in <em>en-US</em>) is
   1807    * shown on integers. For example, if this setting is turned on, formatting 123 will result in
   1808    * "123." with the decimal separator.
   1809    *
   1810    * <p>This setting can be specified in the pattern for integer formats: "#,##0." is an example.
   1811    *
   1812    * @param value true to always show the decimal separator; false to show it only when there is a
   1813    *     fraction part of the number.
   1814    */
   1815   public synchronized void setDecimalSeparatorAlwaysShown(boolean value) {
   1816     properties.setDecimalSeparatorAlwaysShown(value);
   1817     refreshFormatter();
   1818   }
   1819 
   1820   /**
   1821    * Returns the user-specified currency. May be null.
   1822    *
   1823    * @see #setCurrency
   1824    * @see DecimalFormatSymbols#getCurrency
   1825    */
   1826   @Override
   1827   public synchronized Currency getCurrency() {
   1828     return properties.getCurrency();
   1829   }
   1830 
   1831   /**
   1832    * Sets the currency to be used when formatting numbers. The effect is twofold:
   1833    *
   1834    * <ol>
   1835    *   <li>Substitutions for currency symbols in the pattern string will use this currency
   1836    *   <li>The rounding mode will obey the rules for this currency (see {@link #setCurrencyUsage})
   1837    * </ol>
   1838    *
   1839    * <strong>Important:</strong> Displaying the currency in the output requires that the patter
   1840    * associated with this formatter contains a currency symbol ''. This will be the case if the
   1841    * instance was created via {@link #getCurrencyInstance} or one of its friends.
   1842    *
   1843    * @param currency The currency to use.
   1844    */
   1845   @Override
   1846   public synchronized void setCurrency(Currency currency) {
   1847     properties.setCurrency(currency);
   1848     // Backwards compatibility: also set the currency in the DecimalFormatSymbols
   1849     if (currency != null) {
   1850       symbols.setCurrency(currency);
   1851       String symbol = currency.getName(symbols.getULocale(), Currency.SYMBOL_NAME, null);
   1852       symbols.setCurrencySymbol(symbol);
   1853     }
   1854     refreshFormatter();
   1855   }
   1856 
   1857   /**
   1858    * <strong>[icu]</strong> Returns the strategy for rounding currency amounts.
   1859    *
   1860    * @see #setCurrencyUsage
   1861    */
   1862   public synchronized CurrencyUsage getCurrencyUsage() {
   1863     // CurrencyUsage is not exported, so we have to get it from the input property bag.
   1864     // TODO: Should we export CurrencyUsage instead?
   1865     CurrencyUsage usage = properties.getCurrencyUsage();
   1866     if (usage == null) {
   1867       usage = CurrencyUsage.STANDARD;
   1868     }
   1869     return usage;
   1870   }
   1871 
   1872   /**
   1873    * <strong>[icu]</strong> Sets the currency-dependent strategy to use when rounding numbers. There are two
   1874    * strategies:
   1875    *
   1876    * <ul>
   1877    *   <li>STANDARD: When the amount displayed is intended for banking statements or electronic
   1878    *       transfer.
   1879    *   <li>CASH: When the amount displayed is intended to be representable in physical currency,
   1880    *       like at a cash register.
   1881    * </ul>
   1882    *
   1883    * CASH mode is relevant in currencies that do not have tender down to the penny. For more
   1884    * information on the two rounding strategies, see <a
   1885    * href="http://unicode.org/reports/tr35/tr35-numbers.html#Supplemental_Currency_Data">UTS
   1886    * #35</a>. If omitted, the strategy defaults to STANDARD. To override currency rounding
   1887    * altogether, use {@link #setMinimumFractionDigits} and {@link #setMaximumFractionDigits} or
   1888    * {@link #setRoundingIncrement}.
   1889    *
   1890    * @param usage The strategy to use when rounding in the current currency.
   1891    */
   1892   public synchronized void setCurrencyUsage(CurrencyUsage usage) {
   1893     properties.setCurrencyUsage(usage);
   1894     refreshFormatter();
   1895   }
   1896 
   1897   /**
   1898    * <strong>[icu]</strong> Returns the current instance of CurrencyPluralInfo.
   1899    *
   1900    * @see #setCurrencyPluralInfo
   1901    */
   1902   public synchronized CurrencyPluralInfo getCurrencyPluralInfo() {
   1903     // CurrencyPluralInfo also is not exported.
   1904     return properties.getCurrencyPluralInfo();
   1905   }
   1906 
   1907   /**
   1908    * <strong>[icu]</strong> Sets a custom instance of CurrencyPluralInfo. CurrencyPluralInfo generates pattern
   1909    * strings for printing currency long names.
   1910    *
   1911    * <p><strong>Most users should not call this method directly.</strong> You should instead create
   1912    * your formatter via <code>NumberFormat.getInstance(NumberFormat.PLURALCURRENCYSTYLE)</code>.
   1913    *
   1914    * @param newInfo The CurrencyPluralInfo to use when printing currency long names.
   1915    */
   1916   public synchronized void setCurrencyPluralInfo(CurrencyPluralInfo newInfo) {
   1917     properties.setCurrencyPluralInfo(newInfo);
   1918     refreshFormatter();
   1919   }
   1920 
   1921   /**
   1922    * Returns whether {@link #parse} will always return a BigDecimal.
   1923    *
   1924    * @see #setParseBigDecimal
   1925    */
   1926   public synchronized boolean isParseBigDecimal() {
   1927     return properties.getParseToBigDecimal();
   1928   }
   1929 
   1930   /**
   1931    * Whether to make {@link #parse} prefer returning a {@link android.icu.math.BigDecimal} when
   1932    * possible. For strings corresponding to return values of Infinity, -Infinity, NaN, and -0.0, a
   1933    * Double will be returned even if ParseBigDecimal is enabled.
   1934    *
   1935    * @param value true to cause {@link #parse} to prefer BigDecimal; false to let {@link #parse}
   1936    *     return additional data types like Long or BigInteger.
   1937    */
   1938   public synchronized void setParseBigDecimal(boolean value) {
   1939     properties.setParseToBigDecimal(value);
   1940     // refreshFormatter() not needed
   1941   }
   1942 
   1943   /**
   1944    * Always returns 1000, the default prior to ICU 59.
   1945    *
   1946    * @deprecated Setting max parse digits has no effect since ICU4J 59.
   1947    */
   1948   @Deprecated
   1949   public int getParseMaxDigits() {
   1950     return 1000;
   1951   }
   1952 
   1953   /**
   1954    * @param maxDigits Prior to ICU 59, the maximum number of digits in the output number after
   1955    *     exponential notation is applied.
   1956    * @deprecated Setting max parse digits has no effect since ICU4J 59.
   1957    */
   1958   @Deprecated
   1959   public void setParseMaxDigits(int maxDigits) {}
   1960 
   1961   /**
   1962    * {@inheritDoc}
   1963    */
   1964   @Override
   1965   public synchronized boolean isParseStrict() {
   1966     return properties.getParseMode() == Parse.ParseMode.STRICT;
   1967   }
   1968 
   1969   /**
   1970    * {@inheritDoc}
   1971    */
   1972   @Override
   1973   public synchronized void setParseStrict(boolean parseStrict) {
   1974     Parse.ParseMode mode = parseStrict ? Parse.ParseMode.STRICT : Parse.ParseMode.LENIENT;
   1975     properties.setParseMode(mode);
   1976     // refreshFormatter() not needed
   1977   }
   1978 
   1979   /**
   1980    * {@inheritDoc}
   1981    *
   1982    * @see #setParseIntegerOnly
   1983    */
   1984   @Override
   1985   public synchronized boolean isParseIntegerOnly() {
   1986     return properties.getParseIntegerOnly();
   1987   }
   1988 
   1989   /**
   1990    * <strong>Parsing:</strong> {@inheritDoc}
   1991    *
   1992    * <p>This is functionally equivalent to calling {@link #setDecimalPatternMatchRequired} and a
   1993    * pattern without a decimal point.
   1994    *
   1995    * @param parseIntegerOnly true to ignore fractional parts of numbers when parsing; false to
   1996    *     consume fractional parts.
   1997    */
   1998   @Override
   1999   public synchronized void setParseIntegerOnly(boolean parseIntegerOnly) {
   2000     properties.setParseIntegerOnly(parseIntegerOnly);
   2001     // refreshFormatter() not needed
   2002   }
   2003 
   2004   /**
   2005    * <strong>[icu]</strong> Returns whether the presence of a decimal point must match the pattern.
   2006    *
   2007    * @see #setDecimalPatternMatchRequired
   2008    */
   2009   public synchronized boolean isDecimalPatternMatchRequired() {
   2010     return properties.getDecimalPatternMatchRequired();
   2011   }
   2012 
   2013   /**
   2014    * <strong>[icu]</strong> <strong>Parsing:</strong> This method is used to either <em>require</em> or
   2015    * <em>forbid</em> the presence of a decimal point in the string being parsed (disabled by
   2016    * default). This feature was designed to be an extra layer of strictness on top of strict
   2017    * parsing, although it can be used in either lenient mode or strict mode.
   2018    *
   2019    * <p>To <em>require</em> a decimal point, call this method in combination with either a pattern
   2020    * containing a decimal point or with {@link #setDecimalSeparatorAlwaysShown}.
   2021    *
   2022    * <pre>
   2023    * // Require a decimal point in the string being parsed:
   2024    * df.applyPattern("#.");
   2025    * df.setDecimalPatternMatchRequired(true);
   2026    *
   2027    * // Alternatively:
   2028    * df.setDecimalSeparatorAlwaysShown(true);
   2029    * df.setDecimalPatternMatchRequired(true);
   2030    * </pre>
   2031    *
   2032    * To <em>forbid</em> a decimal point, call this method in combination with a pattern containing
   2033    * no decimal point. Alternatively, use {@link #setParseIntegerOnly} for the same behavior without
   2034    * depending on the contents of the pattern string.
   2035    *
   2036    * <pre>
   2037    * // Forbid a decimal point in the string being parsed:
   2038    * df.applyPattern("#");
   2039    * df.setDecimalPatternMatchRequired(true);
   2040    * </pre>
   2041    *
   2042    * @param value true to either require or forbid the decimal point according to the pattern; false
   2043    *     to disable this feature.
   2044    * @see #setParseIntegerOnly
   2045    */
   2046   public synchronized void setDecimalPatternMatchRequired(boolean value) {
   2047     properties.setDecimalPatternMatchRequired(value);
   2048     refreshFormatter();
   2049   }
   2050 
   2051   /**
   2052    * <strong>[icu]</strong> Returns whether to ignore exponents when parsing.
   2053    *
   2054    * @see #setParseNoExponent
   2055    * @deprecated ICU 59: This API is a technical preview. It may change in an upcoming release.
   2056  * @hide draft / provisional / internal are hidden on Android
   2057    */
   2058   @Deprecated
   2059   public synchronized boolean getParseNoExponent() {
   2060     return properties.getParseNoExponent();
   2061   }
   2062 
   2063   /**
   2064    * <strong>[icu]</strong> Specifies whether to stop parsing when an exponent separator is encountered. For
   2065    * example, parses "123E4" to 123 (with parse position 3) instead of 1230000 (with parse position
   2066    * 5).
   2067    *
   2068    * @param value true to prevent exponents from being parsed; false to allow them to be parsed.
   2069    * @deprecated ICU 59: This API is a technical preview. It may change in an upcoming release.
   2070  * @hide draft / provisional / internal are hidden on Android
   2071    */
   2072   @Deprecated
   2073   public synchronized void setParseNoExponent(boolean value) {
   2074     properties.setParseNoExponent(value);
   2075     refreshFormatter();
   2076   }
   2077 
   2078   /**
   2079    * <strong>[icu]</strong> Returns whether to force case (uppercase/lowercase) to match when parsing.
   2080    *
   2081    * @see #setParseNoExponent
   2082    * @deprecated ICU 59: This API is a technical preview. It may change in an upcoming release.
   2083  * @hide draft / provisional / internal are hidden on Android
   2084    */
   2085   @Deprecated
   2086   public synchronized boolean getParseCaseSensitive() {
   2087     return properties.getParseCaseSensitive();
   2088   }
   2089 
   2090   /**
   2091    * <strong>[icu]</strong> Specifies whether parsing should require cases to match in affixes, exponent separators,
   2092    * and currency codes. Case mapping is performed for each code point using {@link
   2093    * UCharacter#foldCase}.
   2094    *
   2095    * @param value true to force case (uppercase/lowercase) to match when parsing; false to ignore
   2096    *     case and perform case folding.
   2097    * @deprecated ICU 59: This API is a technical preview. It may change in an upcoming release.
   2098  * @hide draft / provisional / internal are hidden on Android
   2099    */
   2100   @Deprecated
   2101   public synchronized void setParseCaseSensitive(boolean value) {
   2102     properties.setParseCaseSensitive(value);
   2103     refreshFormatter();
   2104   }
   2105 
   2106   // TODO(sffc): Uncomment for ICU 60 API proposal.
   2107   //
   2108   //  /**
   2109   //   * {@icu} Returns the strategy used for choosing between grouping and decimal separators when
   2110   //   * parsing.
   2111   //   *
   2112   //   * @see #setParseGroupingMode
   2113   //   * @category Parsing
   2114   //   */
   2115   //  public synchronized GroupingMode getParseGroupingMode() {
   2116   //    return properties.getParseGroupingMode();
   2117   //  }
   2118   //
   2119   //  /**
   2120   //   * {@icu} Sets the strategy used during parsing when a code point needs to be interpreted as
   2121   //   * either a decimal separator or a grouping separator.
   2122   //   *
   2123   //   * <p>The comma, period, space, and apostrophe have different meanings in different locales. For
   2124   //   * example, in <em>en-US</em> and most American locales, the period is used as a decimal
   2125   //   * separator, but in <em>es-PY</em> and most European locales, it is used as a grouping separator.
   2126   //   *
   2127   //   * Suppose you are in <em>fr-FR</em> the parser encounters the string "1.234".  In <em>fr-FR</em>,
   2128   //   * the grouping is a space and the decimal is a comma.  The <em>grouping mode</em> is a mechanism
   2129   //   * to let you specify whether to accept the string as 1234 (GroupingMode.DEFAULT) or whether to reject it since the separators
   2130   //   * don't match (GroupingMode.RESTRICTED).
   2131   //   *
   2132   //   * When resolving grouping separators, it is the <em>equivalence class</em> of separators that is considered.
   2133   //   * For example, a period is seen as equal to a fixed set of other period-like characters.
   2134   //   *
   2135   //   * @param groupingMode The strategy to use; either DEFAULT or RESTRICTED.
   2136   //   * @category Parsing
   2137   //   */
   2138   //  public synchronized void setParseGroupingMode(GroupingMode groupingMode) {
   2139   //    properties.setParseGroupingMode(groupingMode);
   2140   //    refreshFormatter();
   2141   //  }
   2142 
   2143   //=====================================================================================//
   2144   //                                     UTILITIES                                       //
   2145   //=====================================================================================//
   2146 
   2147   /**
   2148    * Tests for equality between this formatter and another formatter.
   2149    *
   2150    * <p>If two DecimalFormat instances are equal, then they will always produce the same output.
   2151    * However, the reverse is not necessarily true: if two DecimalFormat instances always produce the
   2152    * same output, they are not necessarily equal.
   2153    */
   2154   @Override
   2155   public synchronized boolean equals(Object obj) {
   2156     if (obj == null) return false;
   2157     if (obj == this) return true;
   2158     if (!(obj instanceof DecimalFormat)) return false;
   2159     DecimalFormat other = (DecimalFormat) obj;
   2160     return properties.equals(other.properties) && symbols.equals(other.symbols);
   2161   }
   2162 
   2163   /**
   2164    * {@inheritDoc}
   2165    */
   2166   @Override
   2167   public synchronized int hashCode() {
   2168     return properties.hashCode() ^ symbols.hashCode();
   2169   }
   2170 
   2171   /**
   2172    * Returns the default value of toString() with extra DecimalFormat-specific information appended
   2173    * to the end of the string. This extra information is intended for debugging purposes, and the
   2174    * format is not guaranteed to be stable.
   2175    */
   2176   @Override
   2177   public String toString() {
   2178     StringBuilder result = new StringBuilder();
   2179     result.append(getClass().getName());
   2180     result.append("@");
   2181     result.append(Integer.toHexString(hashCode()));
   2182     result.append(" { symbols@");
   2183     result.append(Integer.toHexString(symbols.hashCode()));
   2184     synchronized (this) {
   2185       properties.toStringBare(result);
   2186     }
   2187     result.append(" }");
   2188     return result.toString();
   2189   }
   2190 
   2191   /**
   2192    * Serializes this formatter object to a decimal format pattern string. The result of this method
   2193    * is guaranteed to be <em>functionally</em> equivalent to the pattern string used to create this
   2194    * instance after incorporating values from the setter methods.
   2195    *
   2196    * <p>For more information on decimal format pattern strings, see <a
   2197    * href="http://unicode.org/reports/tr35/tr35-numbers.html#Number_Format_Patterns">UTS #35</a>.
   2198    *
   2199    * <p><strong>Important:</strong> Not all properties are capable of being encoded in a pattern
   2200    * string. See a list of properties in {@link #applyPattern}.
   2201    *
   2202    * @return A decimal format pattern string.
   2203    */
   2204   public synchronized String toPattern() {
   2205     // Pull some properties from exportedProperties and others from properties
   2206     // to keep affix patterns intact.  In particular, pull rounding properties
   2207     // so that CurrencyUsage is reflected properly.
   2208     // TODO: Consider putting this logic in PatternString.java instead.
   2209     DecimalFormatProperties tprops = threadLocalProperties.get().copyFrom(properties);
   2210     if (useCurrency(properties)) {
   2211       tprops.setMinimumFractionDigits(exportedProperties.getMinimumFractionDigits());
   2212       tprops.setMaximumFractionDigits(exportedProperties.getMaximumFractionDigits());
   2213       tprops.setRoundingIncrement(exportedProperties.getRoundingIncrement());
   2214     }
   2215     return PatternStringUtils.propertiesToPatternString(tprops);
   2216   }
   2217 
   2218   /**
   2219    * Calls {@link #toPattern} and converts the string to localized notation. For more information on
   2220    * localized notation, see {@link #applyLocalizedPattern}. This method is provided for backwards
   2221    * compatibility and should not be used in new projects.
   2222    *
   2223    * @return A decimal format pattern string in localized notation.
   2224    */
   2225   public synchronized String toLocalizedPattern() {
   2226     String pattern = toPattern();
   2227     return PatternStringUtils.convertLocalized(pattern, symbols, true);
   2228   }
   2229 
   2230   /**
   2231    * Converts this DecimalFormat to a NumberFormatter.  Starting in ICU 60,
   2232    * NumberFormatter is the recommended way to format numbers.
   2233    *
   2234    * @return An instance of {@link LocalizedNumberFormatter} with the same behavior as this instance of
   2235    * DecimalFormat.
   2236    * @see NumberFormatter
   2237    * @hide draft / provisional / internal are hidden on Android
   2238    */
   2239   public LocalizedNumberFormatter toNumberFormatter() {
   2240       return formatter;
   2241   }
   2242 
   2243   /**
   2244    * @deprecated This API is ICU internal only.
   2245  * @hide draft / provisional / internal are hidden on Android
   2246    */
   2247   @Deprecated
   2248   public IFixedDecimal getFixedDecimal(double number) {
   2249     return formatter.format(number).getFixedDecimal();
   2250   }
   2251 
   2252   private static final ThreadLocal<DecimalFormatProperties> threadLocalProperties =
   2253       new ThreadLocal<DecimalFormatProperties>() {
   2254         @Override
   2255         protected DecimalFormatProperties initialValue() {
   2256           return new DecimalFormatProperties();
   2257         }
   2258       };
   2259 
   2260   /** Rebuilds the formatter object from the property bag. */
   2261   void refreshFormatter() {
   2262     if (exportedProperties == null) {
   2263       // exportedProperties is null only when the formatter is not ready yet.
   2264       // The only time when this happens is during legacy deserialization.
   2265       return;
   2266     }
   2267     ULocale locale = this.getLocale(ULocale.ACTUAL_LOCALE);
   2268     if (locale == null) {
   2269       // Constructor
   2270       locale = symbols.getLocale(ULocale.ACTUAL_LOCALE);
   2271     }
   2272     if (locale == null) {
   2273       // Deserialization
   2274       locale = symbols.getULocale();
   2275     }
   2276     assert locale != null;
   2277     formatter = NumberFormatter.fromDecimalFormat(properties, symbols, exportedProperties).locale(locale);
   2278   }
   2279 
   2280   /**
   2281    * Converts a java.math.BigDecimal to a android.icu.math.BigDecimal with fallback for numbers
   2282    * outside of the range supported by android.icu.math.BigDecimal.
   2283    *
   2284    * @param number
   2285    * @return
   2286    */
   2287   private Number safeConvertBigDecimal(java.math.BigDecimal number) {
   2288     try {
   2289       return new android.icu.math.BigDecimal(number);
   2290     } catch (NumberFormatException e) {
   2291       if (number.signum() > 0 && number.scale() < 0) {
   2292         return Double.POSITIVE_INFINITY;
   2293       } else if (number.scale() < 0) {
   2294         return Double.NEGATIVE_INFINITY;
   2295       } else if (number.signum() < 0) {
   2296         return -0.0;
   2297       } else {
   2298         return 0.0;
   2299       }
   2300     }
   2301   }
   2302 
   2303   /**
   2304    * Returns true if the currency is set in The property bag or if currency symbols are present in
   2305    * the prefix/suffix pattern.
   2306    */
   2307   private static boolean useCurrency(DecimalFormatProperties properties) {
   2308     return ((properties.getCurrency() != null)
   2309         || properties.getCurrencyPluralInfo() != null
   2310         || properties.getCurrencyUsage() != null
   2311         || AffixUtils.hasCurrencySymbols(properties.getPositivePrefixPattern())
   2312         || AffixUtils.hasCurrencySymbols(properties.getPositiveSuffixPattern())
   2313         || AffixUtils.hasCurrencySymbols(properties.getNegativePrefixPattern())
   2314         || AffixUtils.hasCurrencySymbols(properties.getNegativeSuffixPattern()));
   2315   }
   2316 
   2317   /**
   2318    * Updates the property bag with settings from the given pattern.
   2319    *
   2320    * @param pattern The pattern string to parse.
   2321    * @param ignoreRounding Whether to leave out rounding information (minFrac, maxFrac, and rounding
   2322    *     increment) when parsing the pattern. This may be desirable if a custom rounding mode, such
   2323    *     as CurrencyUsage, is to be used instead. One of {@link
   2324    *     PatternStringParser#IGNORE_ROUNDING_ALWAYS}, {@link PatternStringParser#IGNORE_ROUNDING_IF_CURRENCY},
   2325    *     or {@link PatternStringParser#IGNORE_ROUNDING_NEVER}.
   2326    * @see PatternAndPropertyUtils#parseToExistingProperties
   2327    */
   2328   void setPropertiesFromPattern(String pattern, int ignoreRounding) {
   2329     if (pattern == null) {
   2330       throw new NullPointerException();
   2331     }
   2332     PatternStringParser.parseToExistingProperties(pattern, properties, ignoreRounding);
   2333   }
   2334 
   2335   /**
   2336    * @deprecated This API is ICU internal only.
   2337  * @hide draft / provisional / internal are hidden on Android
   2338    */
   2339   @Deprecated
   2340   public synchronized void setProperties(PropertySetter func) {
   2341     func.set(properties);
   2342     refreshFormatter();
   2343   }
   2344 
   2345   /**
   2346    * @deprecated This API is ICU internal only.
   2347  * @hide draft / provisional / internal are hidden on Android
   2348    */
   2349   @Deprecated
   2350   public static interface PropertySetter {
   2351     /**
   2352      * @deprecated This API is ICU internal only.
   2353      * @hide draft / provisional / internal are hidden on Android
   2354      */
   2355     @Deprecated
   2356     public void set(DecimalFormatProperties props);
   2357   }
   2358 
   2359   /**
   2360    * <strong>[icu]</strong> Constant for {@link #getPadPosition()} and {@link #setPadPosition(int)} to specify pad
   2361    * characters inserted before the prefix.
   2362    *
   2363    * @see #setPadPosition
   2364    * @see #getPadPosition
   2365    * @see #PAD_AFTER_PREFIX
   2366    * @see #PAD_BEFORE_SUFFIX
   2367    * @see #PAD_AFTER_SUFFIX
   2368    */
   2369   public static final int PAD_BEFORE_PREFIX = 0;
   2370 
   2371   /**
   2372    * <strong>[icu]</strong> Constant for {@link #getPadPosition()} and {@link #setPadPosition(int)} to specify pad
   2373    * characters inserted after the prefix.
   2374    *
   2375    * @see #setPadPosition
   2376    * @see #getPadPosition
   2377    * @see #PAD_BEFORE_PREFIX
   2378    * @see #PAD_BEFORE_SUFFIX
   2379    * @see #PAD_AFTER_SUFFIX
   2380    */
   2381   public static final int PAD_AFTER_PREFIX = 1;
   2382 
   2383   /**
   2384    * <strong>[icu]</strong> Constant for {@link #getPadPosition()} and {@link #setPadPosition(int)} to specify pad
   2385    * characters inserted before the suffix.
   2386    *
   2387    * @see #setPadPosition
   2388    * @see #getPadPosition
   2389    * @see #PAD_BEFORE_PREFIX
   2390    * @see #PAD_AFTER_PREFIX
   2391    * @see #PAD_AFTER_SUFFIX
   2392    */
   2393   public static final int PAD_BEFORE_SUFFIX = 2;
   2394 
   2395   /**
   2396    * <strong>[icu]</strong> Constant for {@link #getPadPosition()} and {@link #setPadPosition(int)} to specify pad
   2397    * characters inserted after the suffix.
   2398    *
   2399    * @see #setPadPosition
   2400    * @see #getPadPosition
   2401    * @see #PAD_BEFORE_PREFIX
   2402    * @see #PAD_AFTER_PREFIX
   2403    * @see #PAD_BEFORE_SUFFIX
   2404    */
   2405   public static final int PAD_AFTER_SUFFIX = 3;
   2406 }
   2407