// © 2017 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html#License
package com.ibm.icu.text;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamField;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.text.AttributedCharacterIterator;
import java.text.FieldPosition;
import java.text.ParsePosition;

import com.ibm.icu.impl.FormattedStringBuilder;
import com.ibm.icu.impl.FormattedValueStringBuilderImpl;
import com.ibm.icu.impl.Utility;
import com.ibm.icu.impl.number.AffixUtils;
import com.ibm.icu.impl.number.DecimalFormatProperties;
import com.ibm.icu.impl.number.DecimalFormatProperties.ParseMode;
import com.ibm.icu.impl.number.DecimalQuantity;
import com.ibm.icu.impl.number.DecimalQuantity_DualStorageBCD;
import com.ibm.icu.impl.number.Padder;
import com.ibm.icu.impl.number.Padder.PadPosition;
import com.ibm.icu.impl.number.PatternStringParser;
import com.ibm.icu.impl.number.PatternStringUtils;
import com.ibm.icu.impl.number.parse.NumberParserImpl;
import com.ibm.icu.impl.number.parse.ParsedNumber;
import com.ibm.icu.lang.UCharacter;
import com.ibm.icu.math.BigDecimal;
import com.ibm.icu.math.MathContext;
import com.ibm.icu.number.FormattedNumber;
import com.ibm.icu.number.LocalizedNumberFormatter;
import com.ibm.icu.number.NumberFormatter;
import com.ibm.icu.text.PluralRules.IFixedDecimal;
import com.ibm.icu.util.Currency;
import com.ibm.icu.util.Currency.CurrencyUsage;
import com.ibm.icu.util.CurrencyAmount;
import com.ibm.icu.util.ULocale;
import com.ibm.icu.util.ULocale.Category;

/**
 * {@icuenhanced java.text.DecimalFormat}.{@icu _usage_}
 *
 * <p>
 * <strong>IMPORTANT:</strong> New users are strongly encouraged to see if
 * {@link NumberFormatter} fits their use case.  Although not deprecated, this
 * class, DecimalFormat, is only provided for java.text.DecimalFormat compatibility.
 * <hr>
 *
 * <code>DecimalFormat</code> is the primary
 * concrete subclass of {@link NumberFormat}. It has a variety of features designed to make it
 * possible to parse and format numbers in any locale, including support for Western, Arabic, or
 * Indic digits. It supports different flavors of numbers, including integers ("123"), fixed-point
 * numbers ("123.4"), scientific notation ("1.23E4"), percentages ("12%"), and currency amounts
 * ("$123.00", "USD123.00", "123.00 US dollars"). All of these flavors can be easily localized.
 *
 * <p>To obtain a number formatter for a specific locale (including the default locale), call one of
 * NumberFormat's factory methods such as {@link NumberFormat#getInstance}. Do not call
 * DecimalFormat constructors directly unless you know what you are doing.
 *
 * <p>DecimalFormat aims to comply with the specification <a
 * href="http://unicode.org/reports/tr35/tr35-numbers.html#Number_Format_Patterns">UTS #35</a>. Read
 * the specification for more information on how all the properties in DecimalFormat fit together.
 *
 * <p><strong>NOTE:</strong> Starting in ICU 60, there is a new set of APIs for localized number
 * formatting that are designed to be an improvement over DecimalFormat.  New users are discouraged
 * from using DecimalFormat.  For more information, see the package com.ibm.icu.number.
 *
 * <h3>Example Usage</h3>
 *
 * <p>Customize settings on a DecimalFormat instance from the NumberFormat factory:
 *
 * <blockquote>
 *
 * <pre>
 * NumberFormat f = NumberFormat.getInstance(loc);
 * if (f instanceof DecimalFormat) {
 *     ((DecimalFormat) f).setDecimalSeparatorAlwaysShown(true);
 *     ((DecimalFormat) f).setMinimumGroupingDigits(2);
 * }
 * </pre>
 *
 * </blockquote>
 *
 * <p>Quick and dirty print out a number using the localized number, currency, and percent format
 * for each locale:
 *
 * <blockquote>
 *
 * <pre>
 * for (ULocale uloc : ULocale.getAvailableLocales()) {
 *     System.out.print(uloc + ":\t");
 *     System.out.print(NumberFormat.getInstance(uloc).format(1.23));
 *     System.out.print("\t");
 *     System.out.print(NumberFormat.getCurrencyInstance(uloc).format(1.23));
 *     System.out.print("\t");
 *     System.out.print(NumberFormat.getPercentInstance(uloc).format(1.23));
 *     System.out.println();
 * }
 * </pre>
 *
 * </blockquote>
 *
 * <h3>Properties and Symbols</h3>
 *
 * <p>A DecimalFormat object encapsulates a set of <em>properties</em> and a set of
 * <em>symbols</em>. Grouping size, rounding mode, and affixes are examples of properties. Locale
 * digits and the characters used for grouping and decimal separators are examples of symbols.
 *
 * <p>To set a custom set of symbols, use {@link #setDecimalFormatSymbols}. Use the various other
 * setters in this class to set custom values for the properties.
 *
 * <h3>Rounding</h3>
 *
 * <p>DecimalFormat provides three main strategies to specify the position at which numbers should
 * be rounded:
 *
 * <ol>
 *   <li><strong>Magnitude:</strong> Display a fixed number of fraction digits; this is the most
 *       common form.
 *   <li><strong>Increment:</strong> Round numbers to the closest multiple of a certain increment,
 *       such as 0.05. This is common in currencies.
 *   <li><strong>Significant Digits:</strong> Round numbers such that a fixed number of nonzero
 *       digits are shown. This is most common in scientific notation.
 * </ol>
 *
 * <p>It is not possible to specify more than one rounding strategy. For example, setting a rounding
 * increment in conjunction with significant digits results in undefined behavior.
 *
 * <p>It is also possible to specify the <em>rounding mode</em> to use. The default rounding mode is
 * "half even", which rounds numbers to their closest increment, with ties broken in favor of
 * trailing numbers being even. For more information, see {@link #setRoundingMode} and <a
 * href="http://userguide.icu-project.org/formatparse/numbers/rounding-modes">the ICU User
 * Guide</a>.
 *
 * <h3>Pattern Strings</h3>
 *
 * <p>A <em>pattern string</em> is a way to serialize some of the available properties for decimal
 * formatting. However, not all properties are capable of being serialized into a pattern string;
 * see {@link #applyPattern} for more information.
 *
 * <p>Most users should not need to interface with pattern strings directly.
 *
 * <p>ICU DecimalFormat aims to follow the specification for pattern strings in <a
 * href="http://unicode.org/reports/tr35/tr35-numbers.html#Number_Format_Patterns">UTS #35</a>.
 * Refer to that specification for more information on pattern string syntax.
 *
 * <h4>Pattern String BNF</h4>
 *
 * The following BNF is used when parsing the pattern string into property values:
 *
 * <pre>
 * pattern    := subpattern (';' subpattern)?
 * subpattern := prefix? number exponent? suffix?
 * number     := (integer ('.' fraction)?) | sigDigits
 * prefix     := '&#92;u0000'..'&#92;uFFFD' - specialCharacters
 * suffix     := '&#92;u0000'..'&#92;uFFFD' - specialCharacters
 * integer    := '#'* '0'* '0'
 * fraction   := '0'* '#'*
 * sigDigits  := '#'* '@' '@'* '#'*
 * exponent   := 'E' '+'? '0'* '0'
 * padSpec    := '*' padChar
 * padChar    := '&#92;u0000'..'&#92;uFFFD' - quote
 * &#32;
 * Notation:
 *   X*       0 or more instances of X
 *   X?       0 or 1 instances of X
 *   X|Y      either X or Y
 *   C..D     any character from C up to D, inclusive
 *   S-T      characters in S, except those in T
 * </pre>
 *
 * <p>The first subpattern is for positive numbers. The second (optional) subpattern is for negative
 * numbers.
 *
 * <p>Not indicated in the BNF syntax above:
 *
 * <ul>
 *   <li>The grouping separator ',' can occur inside the integer and sigDigits elements, between any
 *       two pattern characters of that element, as long as the integer or sigDigits element is not
 *       followed by the exponent element.
 *   <li>Two grouping intervals are recognized: That between the decimal point and the first
 *       grouping symbol, and that between the first and second grouping symbols. These intervals
 *       are identical in most locales, but in some locales they differ. For example, the pattern
 *       &quot;#,##,###&quot; formats the number 123456789 as &quot;12,34,56,789&quot;.
 *   <li>The pad specifier <code>padSpec</code> may appear before the prefix, after the prefix,
 *       before the suffix, after the suffix, or not at all.
 *   <li>In place of '0', the digits '1' through '9' may be used to indicate a rounding increment.
 * </ul>
 *
 * <h3>Parsing</h3>
 *
 * <p>DecimalFormat aims to be able to parse anything that it can output as a formatted string.
 *
 * <p>There are two primary parse modes: <em>lenient</em> and <em>strict</em>. Lenient mode should
 * be used if the goal is to parse user input to a number; strict mode should be used if the goal is
 * validation. The default is lenient mode. For more information, see {@link #setParseStrict}.
 *
 * <p><code>DecimalFormat</code> parses all Unicode characters that represent decimal digits, as
 * defined by {@link UCharacter#digit}. In addition, <code>DecimalFormat</code> also recognizes as
 * digits the ten consecutive characters starting with the localized zero digit defined in the
 * {@link DecimalFormatSymbols} object. During formatting, the {@link DecimalFormatSymbols}-based
 * digits are output.
 *
 * <p>Grouping separators are ignored in lenient mode (default). In strict mode, grouping separators
 * must match the locale-specified grouping sizes.
 *
 * <p>When using {@link #parseCurrency}, all currencies are accepted, not just the currency
 * currently set in the formatter. In addition, the formatter is able to parse every currency style
 * format for a particular locale no matter which style the formatter is constructed with. For
 * example, a formatter instance gotten from NumberFormat.getInstance(ULocale,
 * NumberFormat.CURRENCYSTYLE) can parse both "USD1.00" and "3.00 US dollars".
 *
 * <p>Whitespace characters (lenient mode) and control characters (lenient and strict mode),
 * collectively called "ignorables", do not need to match in identity or quantity between the
 * pattern string and the input string. For example, the pattern "# %" matches "35 %" (with a single
 * space), "35%" (with no space), "35&nbsp;%" (with a non-breaking space), and "35&nbsp; %" (with
 * multiple spaces). Arbitrary ignorables are also allowed at boundaries between the parts of the
 * number: prefix, number, exponent separator, and suffix. Ignorable whitespace characters are those
 * having the Unicode "blank" property for regular expressions, defined in UTS #18 Annex C, which is
 * "horizontal" whitespace, like spaces and tabs, but not "vertical" whitespace, like line breaks.
 * Ignorable control characters are those in the Unicode set [:Default_Ignorable_Code_Point:].
 *
 * <p>If {@link #parse(String, ParsePosition)} fails to parse a string, it returns <code>null</code>
 * and leaves the parse position unchanged. The convenience method {@link #parse(String)} indicates
 * parse failure by throwing a {@link java.text.ParseException}.
 *
 * <p>Under the hood, a state table parsing engine is used. To debug a parsing failure during
 * development, use the following pattern to print details about the state table transitions:
 *
 * <pre>
 * com.ibm.icu.impl.number.Parse.DEBUGGING = true;
 * df.parse("123.45", ppos);
 * com.ibm.icu.impl.number.Parse.DEBUGGING = false;
 * </pre>
 *
 * <h3>Thread Safety and Best Practices</h3>
 *
 * <p>Starting with ICU 59, instances of DecimalFormat are thread-safe.
 *
 * <p>Under the hood, DecimalFormat maintains an immutable formatter object that is rebuilt whenever
 * any of the property setters are called. It is therefore best practice to call property setters
 * only during construction and not when formatting numbers online.
 *
 * @see java.text.Format
 * @see NumberFormat
 * @stable ICU 2.0
 */
public class DecimalFormat extends NumberFormat {

  /** New serialization in ICU 59: declare different version from ICU 58. */
  private static final long serialVersionUID = 864413376551465018L;

  /**
   * One non-transient field such that deserialization can determine the version of the class. This
   * field has existed since the very earliest versions of DecimalFormat.
   */
  @SuppressWarnings("unused")
  private final int serialVersionOnStream = 5;

  //=====================================================================================//
  //                                   INSTANCE FIELDS                                   //
  //=====================================================================================//

  // Fields are package-private, so that subclasses can use them.
  // properties should be final, but clone won't work if we make it final.
  // All fields are transient because custom serialization is used.

  /**
   * The property bag corresponding to user-specified settings and settings from the pattern string.
   * In principle this should be final, but serialize and clone won't work if it is final. Does not
   * need to be volatile because the reference never changes.
   */
  /* final */ transient DecimalFormatProperties properties;

  /**
   * The symbols for the current locale. Volatile because threads may read and write at the same
   * time.
   */
  transient volatile DecimalFormatSymbols symbols;

  /**
   * The pre-computed formatter object. Setters cause this to be re-computed atomically. The {@link
   * #format} method uses the formatter directly without needing to synchronize. Volatile because
   * threads may read and write at the same time.
   */
  transient volatile LocalizedNumberFormatter formatter;

  /**
   * The effective properties as exported from the formatter object. Volatile because threads may
   * read and write at the same time.
   */
  transient volatile DecimalFormatProperties exportedProperties;

  transient volatile NumberParserImpl parser;
  transient volatile NumberParserImpl currencyParser;

  //=====================================================================================//
  //                                    CONSTRUCTORS                                     //
  //=====================================================================================//

  /**
   * Creates a DecimalFormat based on the number pattern and symbols for the default locale. This is
   * a convenient way to obtain a DecimalFormat instance when internationalization is not the main
   * concern.
   *
   * <p>Most users should call the factory methods on NumberFormat, such as {@link
   * NumberFormat#getNumberInstance}, which return localized formatter objects, instead of the
   * DecimalFormat constructors.
   *
   * @see NumberFormat#getInstance
   * @see NumberFormat#getNumberInstance
   * @see NumberFormat#getCurrencyInstance
   * @see NumberFormat#getPercentInstance
   * @see Category#FORMAT
   * @stable ICU 2.0
   */
  public DecimalFormat() {
    // Use the locale's default pattern
    ULocale def = ULocale.getDefault(ULocale.Category.FORMAT);
    String pattern = getPattern(def, NumberFormat.NUMBERSTYLE);
    symbols = getDefaultSymbols();
    properties = new DecimalFormatProperties();
    exportedProperties = new DecimalFormatProperties();
    // Regression: ignore pattern rounding information if the pattern has currency symbols.
    setPropertiesFromPattern(pattern, PatternStringParser.IGNORE_ROUNDING_IF_CURRENCY);
    refreshFormatter();
  }

  /**
   * Creates a DecimalFormat based on the given pattern, using symbols for the default locale. This
   * is a convenient way to obtain a DecimalFormat instance when internationalization is not the
   * main concern.
   *
   * <p>Most users should call the factory methods on NumberFormat, such as {@link
   * NumberFormat#getNumberInstance}, which return localized formatter objects, instead of the
   * DecimalFormat constructors.
   *
   * @param pattern A pattern string such as "#,##0.00" conforming to <a
   *     href="http://unicode.org/reports/tr35/tr35-numbers.html#Number_Format_Patterns">UTS
   *     #35</a>.
   * @throws IllegalArgumentException if the given pattern is invalid.
   * @see NumberFormat#getInstance
   * @see NumberFormat#getNumberInstance
   * @see NumberFormat#getCurrencyInstance
   * @see NumberFormat#getPercentInstance
   * @see Category#FORMAT
   * @stable ICU 2.0
   */
  public DecimalFormat(String pattern) {
    symbols = getDefaultSymbols();
    properties = new DecimalFormatProperties();
    exportedProperties = new DecimalFormatProperties();
    // Regression: ignore pattern rounding information if the pattern has currency symbols.
    setPropertiesFromPattern(pattern, PatternStringParser.IGNORE_ROUNDING_IF_CURRENCY);
    refreshFormatter();
  }

  /**
   * Creates a DecimalFormat based on the given pattern and symbols. Use this constructor if you
   * want complete control over the behavior of the formatter.
   *
   * <p>Most users should call the factory methods on NumberFormat, such as {@link
   * NumberFormat#getNumberInstance}, which return localized formatter objects, instead of the
   * DecimalFormat constructors.
   *
   * @param pattern A pattern string such as "#,##0.00" conforming to <a
   *     href="http://unicode.org/reports/tr35/tr35-numbers.html#Number_Format_Patterns">UTS
   *     #35</a>.
   * @param symbols The set of symbols to be used.
   * @exception IllegalArgumentException if the given pattern is invalid
   * @see NumberFormat#getInstance
   * @see NumberFormat#getNumberInstance
   * @see NumberFormat#getCurrencyInstance
   * @see NumberFormat#getPercentInstance
   * @see DecimalFormatSymbols
   * @stable ICU 2.0
   */
  public DecimalFormat(String pattern, DecimalFormatSymbols symbols) {
    this.symbols = (DecimalFormatSymbols) symbols.clone();
    properties = new DecimalFormatProperties();
    exportedProperties = new DecimalFormatProperties();
    // Regression: ignore pattern rounding information if the pattern has currency symbols.
    setPropertiesFromPattern(pattern, PatternStringParser.IGNORE_ROUNDING_IF_CURRENCY);
    refreshFormatter();
  }

  /**
   * Creates a DecimalFormat based on the given pattern and symbols, with additional control over
   * the behavior of currency. The style argument determines whether currency rounding rules should
   * override the pattern, and the {@link CurrencyPluralInfo} object is used for customizing the
   * plural forms used for currency long names.
   *
   * <p>Most users should call the factory methods on NumberFormat, such as {@link
   * NumberFormat#getNumberInstance}, which return localized formatter objects, instead of the
   * DecimalFormat constructors.
   *
   * @param pattern a non-localized pattern string
   * @param symbols the set of symbols to be used
   * @param infoInput the information used for currency plural format, including currency plural
   *     patterns and plural rules.
   * @param style the decimal formatting style, it is one of the following values:
   *     NumberFormat.NUMBERSTYLE; NumberFormat.CURRENCYSTYLE; NumberFormat.PERCENTSTYLE;
   *     NumberFormat.SCIENTIFICSTYLE; NumberFormat.INTEGERSTYLE; NumberFormat.ISOCURRENCYSTYLE;
   *     NumberFormat.PLURALCURRENCYSTYLE;
   * @stable ICU 4.2
   */
  public DecimalFormat(
      String pattern, DecimalFormatSymbols symbols, CurrencyPluralInfo infoInput, int style) {
    this(pattern, symbols, style);
    properties.setCurrencyPluralInfo(infoInput);
    refreshFormatter();
  }

  /** Package-private constructor used by NumberFormat. */
  DecimalFormat(String pattern, DecimalFormatSymbols symbols, int choice) {
    this.symbols = (DecimalFormatSymbols) symbols.clone();
    properties = new DecimalFormatProperties();
    exportedProperties = new DecimalFormatProperties();
    // If choice is a currency type, ignore the rounding information.
    if (choice == CURRENCYSTYLE
        || choice == ISOCURRENCYSTYLE
        || choice == ACCOUNTINGCURRENCYSTYLE
        || choice == CASHCURRENCYSTYLE
        || choice == STANDARDCURRENCYSTYLE
        || choice == PLURALCURRENCYSTYLE) {
      setPropertiesFromPattern(pattern, PatternStringParser.IGNORE_ROUNDING_ALWAYS);
    } else {
      setPropertiesFromPattern(pattern, PatternStringParser.IGNORE_ROUNDING_IF_CURRENCY);
    }
    refreshFormatter();
  }

  private static DecimalFormatSymbols getDefaultSymbols() {
    return DecimalFormatSymbols.getInstance();
  }

  /**
   * Parses the given pattern string and overwrites the settings specified in the pattern string.
   * The properties corresponding to the following setters are overwritten, either with their
   * default values or with the value specified in the pattern string:
   *
   * <ol>
   *   <li>{@link #setDecimalSeparatorAlwaysShown}
   *   <li>{@link #setExponentSignAlwaysShown}
   *   <li>{@link #setFormatWidth}
   *   <li>{@link #setGroupingSize}
   *   <li>{@link #setMultiplier} (percent/permille)
   *   <li>{@link #setMaximumFractionDigits}
   *   <li>{@link #setMaximumIntegerDigits}
   *   <li>{@link #setMaximumSignificantDigits}
   *   <li>{@link #setMinimumExponentDigits}
   *   <li>{@link #setMinimumFractionDigits}
   *   <li>{@link #setMinimumIntegerDigits}
   *   <li>{@link #setMinimumSignificantDigits}
   *   <li>{@link #setPadPosition}
   *   <li>{@link #setPadCharacter}
   *   <li>{@link #setRoundingIncrement}
   *   <li>{@link #setSecondaryGroupingSize}
   * </ol>
   *
   * All other settings remain untouched.
   *
   * <p>For more information on pattern strings, see <a
   * href="http://unicode.org/reports/tr35/tr35-numbers.html#Number_Format_Patterns">UTS #35</a>.
   *
   * @stable ICU 2.0
   */
  public synchronized void applyPattern(String pattern) {
    setPropertiesFromPattern(pattern, PatternStringParser.IGNORE_ROUNDING_NEVER);
    // Backwards compatibility: clear out user-specified prefix and suffix,
    // as well as CurrencyPluralInfo.
    properties.setPositivePrefix(null);
    properties.setNegativePrefix(null);
    properties.setPositiveSuffix(null);
    properties.setNegativeSuffix(null);
    properties.setCurrencyPluralInfo(null);
    refreshFormatter();
  }

  /**
   * Converts the given string to standard notation and then parses it using {@link #applyPattern}.
   * This method is provided for backwards compatibility and should not be used in new projects.
   *
   * <p>Localized notation means that instead of using generic placeholders in the pattern, you use
   * the corresponding locale-specific characters instead. For example, in locale <em>fr-FR</em>,
   * the period in the pattern "0.000" means "decimal" in standard notation (as it does in every
   * other locale), but it means "grouping" in localized notation.
   *
   * @param localizedPattern The pattern string in localized notation.
   * @stable ICU 2.0
   */
  public synchronized void applyLocalizedPattern(String localizedPattern) {
    String pattern = PatternStringUtils.convertLocalized(localizedPattern, symbols, false);
    applyPattern(pattern);
  }

  //=====================================================================================//
  //                                CLONE AND SERIALIZE                                  //
  //=====================================================================================//

  /** @stable ICU 2.0 */
  @Override
  public Object clone() {
    DecimalFormat other = (DecimalFormat) super.clone();
    other.symbols = (DecimalFormatSymbols) symbols.clone();
    other.properties = properties.clone();
    other.exportedProperties = new DecimalFormatProperties();
    other.refreshFormatter();
    return other;
  }

  /**
   * Custom serialization: save property bag and symbols; the formatter object can be re-created
   * from just that amount of information.
   */
  private synchronized void writeObject(ObjectOutputStream oos) throws IOException {
    // ICU 59 custom serialization.
    // Write class metadata and serialVersionOnStream field:
    oos.defaultWriteObject();
    // Extra int for possible future use:
    oos.writeInt(0);
    // 1) Property Bag
    oos.writeObject(properties);
    // 2) DecimalFormatSymbols
    oos.writeObject(symbols);
  }

  /**
   * Custom serialization: re-create object from serialized property bag and symbols. Also supports
   * reading from the legacy (pre-ICU4J 59) format and converting it to the new form.
   */
  private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
    ObjectInputStream.GetField fieldGetter = ois.readFields();
    ObjectStreamField[] serializedFields = fieldGetter.getObjectStreamClass().getFields();
    int serialVersion = fieldGetter.get("serialVersionOnStream", -1);

    if (serialVersion > 5) {
      throw new IOException(
          "Cannot deserialize newer com.ibm.icu.text.DecimalFormat (v" + serialVersion + ")");
    } else if (serialVersion == 5) {
      ///// ICU 59+ SERIALIZATION FORMAT /////
      // We expect this field and no other fields:
      if (serializedFields.length > 1) {
        throw new IOException("Too many fields when reading serial version 5");
      }
      // Extra int for possible future use:
      ois.readInt();
      // 1) Property Bag
      Object serializedProperties = ois.readObject();
      if (serializedProperties instanceof DecimalFormatProperties) {
        // ICU 60+
        properties = (DecimalFormatProperties) serializedProperties;
      } else {
        // ICU 59
        properties = ((com.ibm.icu.impl.number.Properties) serializedProperties).getInstance();
      }
      // 2) DecimalFormatSymbols
      symbols = (DecimalFormatSymbols) ois.readObject();
      // Re-build transient fields
      exportedProperties = new DecimalFormatProperties();
      refreshFormatter();
    } else {
      ///// LEGACY SERIALIZATION FORMAT /////
      properties = new DecimalFormatProperties();
      // Loop through the fields. Not all fields necessarily exist in the serialization.
      String pp = null, ppp = null, ps = null, psp = null;
      String np = null, npp = null, ns = null, nsp = null;
      for (ObjectStreamField field : serializedFields) {
        String name = field.getName();
        if (name.equals("decimalSeparatorAlwaysShown")) {
          setDecimalSeparatorAlwaysShown(fieldGetter.get("decimalSeparatorAlwaysShown", false));
        } else if (name.equals("exponentSignAlwaysShown")) {
          setExponentSignAlwaysShown(fieldGetter.get("exponentSignAlwaysShown", false));
        } else if (name.equals("formatWidth")) {
          setFormatWidth(fieldGetter.get("formatWidth", 0));
        } else if (name.equals("groupingSize")) {
          setGroupingSize(fieldGetter.get("groupingSize", (byte) 3));
        } else if (name.equals("groupingSize2")) {
          setSecondaryGroupingSize(fieldGetter.get("groupingSize2", (byte) 0));
        } else if (name.equals("maxSignificantDigits")) {
          setMaximumSignificantDigits(fieldGetter.get("maxSignificantDigits", 6));
        } else if (name.equals("minExponentDigits")) {
          setMinimumExponentDigits(fieldGetter.get("minExponentDigits", (byte) 0));
        } else if (name.equals("minSignificantDigits")) {
          setMinimumSignificantDigits(fieldGetter.get("minSignificantDigits", 1));
        } else if (name.equals("multiplier")) {
          setMultiplier(fieldGetter.get("multiplier", 1));
        } else if (name.equals("pad")) {
          setPadCharacter(fieldGetter.get("pad", '\u0020'));
        } else if (name.equals("padPosition")) {
          setPadPosition(fieldGetter.get("padPosition", 0));
        } else if (name.equals("parseBigDecimal")) {
          setParseBigDecimal(fieldGetter.get("parseBigDecimal", false));
        } else if (name.equals("parseRequireDecimalPoint")) {
          setDecimalPatternMatchRequired(fieldGetter.get("parseRequireDecimalPoint", false));
        } else if (name.equals("roundingMode")) {
          setRoundingMode(fieldGetter.get("roundingMode", 0));
        } else if (name.equals("useExponentialNotation")) {
          setScientificNotation(fieldGetter.get("useExponentialNotation", false));
        } else if (name.equals("useSignificantDigits")) {
          setSignificantDigitsUsed(fieldGetter.get("useSignificantDigits", false));
        } else if (name.equals("currencyPluralInfo")) {
          setCurrencyPluralInfo((CurrencyPluralInfo) fieldGetter.get("currencyPluralInfo", null));
        } else if (name.equals("mathContext")) {
          setMathContextICU((MathContext) fieldGetter.get("mathContext", null));
        } else if (name.equals("negPrefixPattern")) {
          npp = (String) fieldGetter.get("negPrefixPattern", null);
        } else if (name.equals("negSuffixPattern")) {
          nsp = (String) fieldGetter.get("negSuffixPattern", null);
        } else if (name.equals("negativePrefix")) {
          np = (String) fieldGetter.get("negativePrefix", null);
        } else if (name.equals("negativeSuffix")) {
          ns = (String) fieldGetter.get("negativeSuffix", null);
        } else if (name.equals("posPrefixPattern")) {
          ppp = (String) fieldGetter.get("posPrefixPattern", null);
        } else if (name.equals("posSuffixPattern")) {
          psp = (String) fieldGetter.get("posSuffixPattern", null);
        } else if (name.equals("positivePrefix")) {
          pp = (String) fieldGetter.get("positivePrefix", null);
        } else if (name.equals("positiveSuffix")) {
          ps = (String) fieldGetter.get("positiveSuffix", null);
        } else if (name.equals("roundingIncrement")) {
          setRoundingIncrement((java.math.BigDecimal) fieldGetter.get("roundingIncrement", null));
        } else if (name.equals("symbols")) {
          setDecimalFormatSymbols((DecimalFormatSymbols) fieldGetter.get("symbols", null));
        } else {
          // The following fields are ignored:
          // "PARSE_MAX_EXPONENT"
          // "currencySignCount"
          // "style"
          // "attributes"
          // "currencyChoice"
          // "formatPattern"
          // "currencyUsage" => ignore this because the old code puts currencyUsage directly into min/max fraction.
        }
      }
      // Resolve affixes
      if (npp == null) {
        properties.setNegativePrefix(np);
      } else {
        properties.setNegativePrefixPattern(npp);
      }
      if (nsp == null) {
        properties.setNegativeSuffix(ns);
      } else {
        properties.setNegativeSuffixPattern(nsp);
      }
      if (ppp == null) {
        properties.setPositivePrefix(pp);
      } else {
        properties.setPositivePrefixPattern(ppp);
      }
      if (psp == null) {
        properties.setPositiveSuffix(ps);
      } else {
        properties.setPositiveSuffixPattern(psp);
      }
      // Extract values from parent NumberFormat class.  Have to use reflection here.
      java.lang.reflect.Field getter;
      try {
        getter = NumberFormat.class.getDeclaredField("groupingUsed");
        getter.setAccessible(true);
        setGroupingUsed((Boolean) getter.get(this));
        getter = NumberFormat.class.getDeclaredField("parseIntegerOnly");
        getter.setAccessible(true);
        setParseIntegerOnly((Boolean) getter.get(this));
        getter = NumberFormat.class.getDeclaredField("maximumIntegerDigits");
        getter.setAccessible(true);
        setMaximumIntegerDigits((Integer) getter.get(this));
        getter = NumberFormat.class.getDeclaredField("minimumIntegerDigits");
        getter.setAccessible(true);
        setMinimumIntegerDigits((Integer) getter.get(this));
        getter = NumberFormat.class.getDeclaredField("maximumFractionDigits");
        getter.setAccessible(true);
        setMaximumFractionDigits((Integer) getter.get(this));
        getter = NumberFormat.class.getDeclaredField("minimumFractionDigits");
        getter.setAccessible(true);
        setMinimumFractionDigits((Integer) getter.get(this));
        getter = NumberFormat.class.getDeclaredField("currency");
        getter.setAccessible(true);
        setCurrency((Currency) getter.get(this));
        getter = NumberFormat.class.getDeclaredField("parseStrict");
        getter.setAccessible(true);
        setParseStrict((Boolean) getter.get(this));
      } catch (IllegalArgumentException e) {
        throw new IOException(e);
      } catch (IllegalAccessException e) {
        throw new IOException(e);
      } catch (NoSuchFieldException e) {
        throw new IOException(e);
      } catch (SecurityException e) {
        throw new IOException(e);
      }
      // Finish initialization
      if (symbols == null) {
        symbols = getDefaultSymbols();
      }
      exportedProperties = new DecimalFormatProperties();
      refreshFormatter();
    }
  }

  //=====================================================================================//
  //                               FORMAT AND PARSE APIS                                 //
  //=====================================================================================//

  /**
   * {@inheritDoc}
   *
   * @stable ICU 2.0
   */
  @Override
  public StringBuffer format(double number, StringBuffer result, FieldPosition fieldPosition) {
    DecimalQuantity dq = new DecimalQuantity_DualStorageBCD(number);
    FormattedStringBuilder string = new FormattedStringBuilder();
    formatter.formatImpl(dq, string);
    fieldPositionHelper(dq, string, fieldPosition, result.length());
    Utility.appendTo(string, result);
    return result;
  }

  /**
   * {@inheritDoc}
   *
   * @stable ICU 2.0
   */
  @Override
  public StringBuffer format(long number, StringBuffer result, FieldPosition fieldPosition) {
    DecimalQuantity dq = new DecimalQuantity_DualStorageBCD(number);
    FormattedStringBuilder string = new FormattedStringBuilder();
    formatter.formatImpl(dq, string);
    fieldPositionHelper(dq, string, fieldPosition, result.length());
    Utility.appendTo(string, result);
    return result;
  }

  /**
   * {@inheritDoc}
   *
   * @stable ICU 2.0
   */
  @Override
  public StringBuffer format(BigInteger number, StringBuffer result, FieldPosition fieldPosition) {
    DecimalQuantity dq = new DecimalQuantity_DualStorageBCD(number);
    FormattedStringBuilder string = new FormattedStringBuilder();
    formatter.formatImpl(dq, string);
    fieldPositionHelper(dq, string, fieldPosition, result.length());
    Utility.appendTo(string, result);
    return result;
  }

  /**
   * {@inheritDoc}
   *
   * @stable ICU 2.0
   */
  @Override
  public StringBuffer format(
      java.math.BigDecimal number, StringBuffer result, FieldPosition fieldPosition) {
    DecimalQuantity dq = new DecimalQuantity_DualStorageBCD(number);
    FormattedStringBuilder string = new FormattedStringBuilder();
    formatter.formatImpl(dq, string);
    fieldPositionHelper(dq, string, fieldPosition, result.length());
    Utility.appendTo(string, result);
    return result;
  }

  /**
   * {@inheritDoc}
   *
   * @stable ICU 2.0
   */
  @Override
  public StringBuffer format(BigDecimal number, StringBuffer result, FieldPosition fieldPosition) {
    DecimalQuantity dq = new DecimalQuantity_DualStorageBCD(number);
    FormattedStringBuilder string = new FormattedStringBuilder();
    formatter.formatImpl(dq, string);
    fieldPositionHelper(dq, string, fieldPosition, result.length());
    Utility.appendTo(string, result);
    return result;
  }

  /**
   * {@inheritDoc}
   *
   * @stable ICU 3.6
   */
  @Override
  public AttributedCharacterIterator formatToCharacterIterator(Object obj) {
    if (!(obj instanceof Number)) throw new IllegalArgumentException();
    Number number = (Number) obj;
    FormattedNumber output = formatter.format(number);
    return output.toCharacterIterator();
  }

  /**
   * {@inheritDoc}
   *
   * @stable ICU 3.0
   */
  @Override
  public StringBuffer format(CurrencyAmount currAmt, StringBuffer result, FieldPosition fieldPosition) {
    // We need to make localSymbols in order for monetary symbols to be initialized.
    // Also, bypass the CurrencyAmount override of LocalizedNumberFormatter#format,
    // because its caching mechanism will not provide any benefit here.
    DecimalFormatSymbols localSymbols = (DecimalFormatSymbols) symbols.clone();
    localSymbols.setCurrency(currAmt.getCurrency());

    DecimalQuantity dq = new DecimalQuantity_DualStorageBCD(currAmt.getNumber());
    FormattedStringBuilder string = new FormattedStringBuilder();
    formatter.symbols(localSymbols)
            .unit(currAmt.getCurrency())
            .formatImpl(dq, string);
    fieldPositionHelper(dq, string, fieldPosition, result.length());
    Utility.appendTo(string, result);
    return result;
  }

  /**
   * {@inheritDoc}
   *
   * @stable ICU 2.0
   */
  @Override
  public Number parse(String text, ParsePosition parsePosition) {
      if (text == null) {
          throw new IllegalArgumentException("Text cannot be null");
      }
      if (parsePosition == null) {
          parsePosition = new ParsePosition(0);
      }
      if (parsePosition.getIndex() < 0) {
          throw new IllegalArgumentException("Cannot start parsing at a negative offset");
      }
      if (parsePosition.getIndex() >= text.length()) {
          // For backwards compatibility, this is not an exception, just an empty result.
          return null;
      }

      ParsedNumber result = new ParsedNumber();
      // Note: if this is a currency instance, currencies will be matched despite the fact that we are not in the
      // parseCurrency method (backwards compatibility)
      int startIndex = parsePosition.getIndex();
      NumberParserImpl parser = getParser();
      parser.parse(text, startIndex, true, result);
      if (result.success()) {
          parsePosition.setIndex(result.charEnd);
          // TODO: Accessing properties here is technically not thread-safe
          Number number = result.getNumber(parser.getParseFlags());
          // Backwards compatibility: return com.ibm.icu.math.BigDecimal
          if (number instanceof java.math.BigDecimal) {
              number = safeConvertBigDecimal((java.math.BigDecimal) number);
          }
          return number;
      } else {
          parsePosition.setErrorIndex(startIndex + result.charEnd);
          return null;
      }
  }

  /**
   * {@inheritDoc}
   *
   * @stable ICU 49
   */
  @Override
  public CurrencyAmount parseCurrency(CharSequence text, ParsePosition parsePosition) {
      if (text == null) {
          throw new IllegalArgumentException("Text cannot be null");
      }
      if (parsePosition == null) {
          parsePosition = new ParsePosition(0);
      }
      if (parsePosition.getIndex() < 0) {
          throw new IllegalArgumentException("Cannot start parsing at a negative offset");
      }
      if (parsePosition.getIndex() >= text.length()) {
          // For backwards compatibility, this is not an exception, just an empty result.
          return null;
      }

      ParsedNumber result = new ParsedNumber();
      int startIndex = parsePosition.getIndex();
      NumberParserImpl parser = getCurrencyParser();
      parser.parse(text.toString(), startIndex, true, result);
      if (result.success()) {
          parsePosition.setIndex(result.charEnd);
          // TODO: Accessing properties here is technically not thread-safe
          Number number = result.getNumber(parser.getParseFlags());
          // Backwards compatibility: return com.ibm.icu.math.BigDecimal
          if (number instanceof java.math.BigDecimal) {
              number = safeConvertBigDecimal((java.math.BigDecimal) number);
          }
          Currency currency = Currency.getInstance(result.currencyCode);
          return new CurrencyAmount(number, currency);
      } else {
          parsePosition.setErrorIndex(startIndex + result.charEnd);
          return null;
      }
  }

  //=====================================================================================//
  //                                GETTERS AND SETTERS                                  //
  //=====================================================================================//

  /**
   * Returns a copy of the decimal format symbols used by this formatter.
   *
   * @return desired DecimalFormatSymbols
   * @see DecimalFormatSymbols
   * @stable ICU 2.0
   */
  public synchronized DecimalFormatSymbols getDecimalFormatSymbols() {
    return (DecimalFormatSymbols) symbols.clone();
  }

  /**
   * Sets the decimal format symbols used by this formatter. The formatter uses a copy of the
   * provided symbols.
   *
   * @param newSymbols desired DecimalFormatSymbols
   * @see DecimalFormatSymbols
   * @stable ICU 2.0
   */
  public synchronized void setDecimalFormatSymbols(DecimalFormatSymbols newSymbols) {
    symbols = (DecimalFormatSymbols) newSymbols.clone();
    refreshFormatter();
  }

  /**
   * <strong>Affixes:</strong> Gets the positive prefix string currently being used to format
   * numbers.
   *
   * <p>If the affix was specified via the pattern, the string returned by this method will have
   * locale symbols substituted in place of special characters according to the LDML specification.
   * If the affix was specified via {@link #setPositivePrefix}, the string will be returned
   * literally.
   *
   * @return The string being prepended to positive numbers.
   * @category Affixes
   * @stable ICU 2.0
   */
  public synchronized String getPositivePrefix() {
    return formatter.getAffixImpl(true, false);
  }

  /**
   * <strong>Affixes:</strong> Sets the string to prepend to positive numbers. For example, if you
   * set the value "#", then the number 123 will be formatted as "#123" in the locale
   * <em>en-US</em>.
   *
   * <p>Using this method overrides the affix specified via the pattern, and unlike the pattern, the
   * string given to this method will be interpreted literally WITHOUT locale symbol substitutions.
   *
   * @param prefix The literal string to prepend to positive numbers.
   * @category Affixes
   * @stable ICU 2.0
   */
  public synchronized void setPositivePrefix(String prefix) {
    if (prefix == null) {
      throw new NullPointerException();
    }
    properties.setPositivePrefix(prefix);
    refreshFormatter();
  }

  /**
   * <strong>Affixes:</strong> Gets the negative prefix string currently being used to format
   * numbers.
   *
   * <p>If the affix was specified via the pattern, the string returned by this method will have
   * locale symbols substituted in place of special characters according to the LDML specification.
   * If the affix was specified via {@link #setNegativePrefix}, the string will be returned
   * literally.
   *
   * @return The string being prepended to negative numbers.
   * @category Affixes
   * @stable ICU 2.0
   */
  public synchronized String getNegativePrefix() {
    return formatter.getAffixImpl(true, true);
  }

  /**
   * <strong>Affixes:</strong> Sets the string to prepend to negative numbers. For example, if you
   * set the value "#", then the number -123 will be formatted as "#123" in the locale
   * <em>en-US</em> (overriding the implicit default '-' in the pattern).
   *
   * <p>Using this method overrides the affix specified via the pattern, and unlike the pattern, the
   * string given to this method will be interpreted literally WITHOUT locale symbol substitutions.
   *
   * @param prefix The literal string to prepend to negative numbers.
   * @category Affixes
   * @stable ICU 2.0
   */
  public synchronized void setNegativePrefix(String prefix) {
    if (prefix == null) {
      throw new NullPointerException();
    }
    properties.setNegativePrefix(prefix);
    refreshFormatter();
  }

  /**
   * <strong>Affixes:</strong> Gets the positive suffix string currently being used to format
   * numbers.
   *
   * <p>If the affix was specified via the pattern, the string returned by this method will have
   * locale symbols substituted in place of special characters according to the LDML specification.
   * If the affix was specified via {@link #setPositiveSuffix}, the string will be returned
   * literally.
   *
   * @return The string being appended to positive numbers.
   * @category Affixes
   * @stable ICU 2.0
   */
  public synchronized String getPositiveSuffix() {
    return formatter.getAffixImpl(false, false);
  }

  /**
   * <strong>Affixes:</strong> Sets the string to append to positive numbers. For example, if you
   * set the value "#", then the number 123 will be formatted as "123#" in the locale
   * <em>en-US</em>.
   *
   * <p>Using this method overrides the affix specified via the pattern, and unlike the pattern, the
   * string given to this method will be interpreted literally WITHOUT locale symbol substitutions.
   *
   * @param suffix The literal string to append to positive numbers.
   * @category Affixes
   * @stable ICU 2.0
   */
  public synchronized void setPositiveSuffix(String suffix) {
    if (suffix == null) {
      throw new NullPointerException();
    }
    properties.setPositiveSuffix(suffix);
    refreshFormatter();
  }

  /**
   * <strong>Affixes:</strong> Gets the negative suffix string currently being used to format
   * numbers.
   *
   * <p>If the affix was specified via the pattern, the string returned by this method will have
   * locale symbols substituted in place of special characters according to the LDML specification.
   * If the affix was specified via {@link #setNegativeSuffix}, the string will be returned
   * literally.
   *
   * @return The string being appended to negative numbers.
   * @category Affixes
   * @stable ICU 2.0
   */
  public synchronized String getNegativeSuffix() {
    return formatter.getAffixImpl(false, true);
  }

  /**
   * <strong>Affixes:</strong> Sets the string to append to negative numbers. For example, if you
   * set the value "#", then the number 123 will be formatted as "123#" in the locale
   * <em>en-US</em>.
   *
   * <p>Using this method overrides the affix specified via the pattern, and unlike the pattern, the
   * string given to this method will be interpreted literally WITHOUT locale symbol substitutions.
   *
   * @param suffix The literal string to append to negative numbers.
   * @category Affixes
   * @stable ICU 2.0
   */
  public synchronized void setNegativeSuffix(String suffix) {
    if (suffix == null) {
      throw new NullPointerException();
    }
    properties.setNegativeSuffix(suffix);
    refreshFormatter();
  }

  /**
   * {@icu} Returns whether the sign is being shown on positive numbers.
   *
   * @return Whether the sign is shown on positive numbers and zero.
   * @see #setSignAlwaysShown
   * @category Affixes
   * @stable ICU 64
   */
  public synchronized boolean isSignAlwaysShown() {
    // This is not in the exported properties
    return properties.getSignAlwaysShown();
  }

  /**
   * Sets whether to always shown the plus sign ('+' in <em>en</em>) on positive numbers. The rules
   * in UTS #35 section 3.2.1 will be followed to ensure a locale-aware placement of the sign.
   *
   * <p>More specifically, the following strategy will be used to place the plus sign:
   *
   * <ol>
   *   <li><em>Patterns without a negative subpattern:</em> The locale's plus sign will be prepended
   *       to the positive prefix.
   *   <li><em>Patterns with a negative subpattern without a '-' sign (e.g., accounting):</em> The
   *       locale's plus sign will be prepended to the positive prefix, as in case 1.
   *   <li><em>Patterns with a negative subpattern that has a '-' sign:</em> The locale's plus sign
   *       will substitute the '-' in the negative subpattern. The positive subpattern will be
   *       unused.
   * </ol>
   *
   * This method is designed to be used <em>instead of</em> applying a pattern containing an
   * explicit plus sign, such as "+0;-0". The behavior when combining this method with explicit plus
   * signs in the pattern is undefined.
   *
   * @param value true to always show a sign; false to hide the sign on positive numbers and zero.
   * @category Affixes
   * @stable ICU 64
   */
  public synchronized void setSignAlwaysShown(boolean value) {
    properties.setSignAlwaysShown(value);
    refreshFormatter();
  }

  /**
   * Returns the multiplier being applied to numbers before they are formatted.
   *
   * @see #setMultiplier
   * @category Multipliers
   * @stable ICU 2.0
   */
  public synchronized int getMultiplier() {
    if (properties.getMultiplier() != null) {
      return properties.getMultiplier().intValue();
    } else {
      return (int) Math.pow(10, properties.getMagnitudeMultiplier());
    }
  }

  /**
   * Sets a number that will be used to multiply all numbers prior to formatting. For example, when
   * formatting percents, a multiplier of 100 can be used.
   *
   * <p>If a percent or permille sign is specified in the pattern, the multiplier is automatically
   * set to 100 or 1000, respectively.
   *
   * <p>If the number specified here is a power of 10, a more efficient code path will be used.
   *
   * @param multiplier The number by which all numbers passed to {@link #format} will be multiplied.
   * @throws IllegalArgumentException If the given multiplier is zero.
   * @throws ArithmeticException when inverting multiplier produces a non-terminating decimal result
   *         in conjunction with MathContext of unlimited precision.
   * @category Multipliers
   * @stable ICU 2.0
   */
  public synchronized void setMultiplier(int multiplier) {
    if (multiplier == 0) {
      throw new IllegalArgumentException("Multiplier must be nonzero.");
    }

    // Try to convert to a magnitude multiplier first
    int delta = 0;
    int value = multiplier;
    while (value != 1) {
      delta++;
      int temp = value / 10;
      if (temp * 10 != value) {
        delta = -1;
        break;
      }
      value = temp;
    }
    if (delta != -1) {
      properties.setMagnitudeMultiplier(delta);
      properties.setMultiplier(null);
    } else {
      properties.setMagnitudeMultiplier(0);
      properties.setMultiplier(java.math.BigDecimal.valueOf(multiplier));
    }
    refreshFormatter();
  }

  /**
   * {@icu} Returns the increment to which numbers are being rounded.
   *
   * @see #setRoundingIncrement
   * @category Rounding
   * @stable ICU 2.0
   */
  public synchronized java.math.BigDecimal getRoundingIncrement() {
    return exportedProperties.getRoundingIncrement();
  }

  /**
   * {@icu} <strong>Rounding and Digit Limits:</strong> Sets an increment, or interval, to which
   * numbers are rounded. For example, a rounding increment of 0.05 will cause the number 1.23 to be
   * rounded to 1.25 in the default rounding mode.
   *
   * <p>The rounding increment can be specified via the pattern string: for example, the pattern
   * "#,##0.05" encodes a rounding increment of 0.05.
   *
   * <p>The rounding increment is applied <em>after</em> any multipliers might take effect; for
   * example, in scientific notation or when {@link #setMultiplier} is used.
   *
   * <p>See {@link #setMaximumFractionDigits} and {@link #setMaximumSignificantDigits} for two other
   * ways of specifying rounding strategies.
   *
   * @param increment The increment to which numbers are to be rounded.
   * @see #setRoundingMode
   * @see #setMaximumFractionDigits
   * @see #setMaximumSignificantDigits
   * @category Rounding
   * @stable ICU 2.0
   */
  public synchronized void setRoundingIncrement(java.math.BigDecimal increment) {
    // Backwards compatibility: ignore rounding increment if zero,
    // and instead set maximum fraction digits.
    if (increment != null && increment.compareTo(java.math.BigDecimal.ZERO) == 0) {
      properties.setMaximumFractionDigits(Integer.MAX_VALUE);
      return;
    }

    properties.setRoundingIncrement(increment);
    refreshFormatter();
  }

  /**
   * {@icu} <strong>Rounding and Digit Limits:</strong> Overload of {@link
   * #setRoundingIncrement(java.math.BigDecimal)}.
   *
   * @param increment The increment to which numbers are to be rounded.
   * @see #setRoundingIncrement
   * @category Rounding
   * @stable ICU 3.6
   */
  public synchronized void setRoundingIncrement(BigDecimal increment) {
    java.math.BigDecimal javaBigDecimal = (increment == null) ? null : increment.toBigDecimal();
    setRoundingIncrement(javaBigDecimal);
  }

  /**
   * {@icu} <strong>Rounding and Digit Limits:</strong> Overload of {@link
   * #setRoundingIncrement(java.math.BigDecimal)}.
   *
   * @param increment The increment to which numbers are to be rounded.
   * @see #setRoundingIncrement
   * @category Rounding
   * @stable ICU 2.0
   */
  public synchronized void setRoundingIncrement(double increment) {
    if (increment == 0) {
      setRoundingIncrement((java.math.BigDecimal) null);
    } else {
      java.math.BigDecimal javaBigDecimal = java.math.BigDecimal.valueOf(increment);
      setRoundingIncrement(javaBigDecimal);
    }
  }

  /**
   * Returns the rounding mode being used to round numbers.
   *
   * @see #setRoundingMode
   * @category Rounding
   * @stable ICU 2.0
   */
  @Override
  public synchronized int getRoundingMode() {
    RoundingMode mode = exportedProperties.getRoundingMode();
    return (mode == null) ? 0 : mode.ordinal();
  }

  /**
   * <strong>Rounding and Digit Limits:</strong> Sets the {@link RoundingMode} used to round
   * numbers. The default rounding mode is HALF_EVEN, which rounds decimals to their closest whole
   * number, and rounds to the closest even number if at the midpoint.
   *
   * <p>For more detail on rounding modes, see <a
   * href="http://userguide.icu-project.org/formatparse/numbers/rounding-modes">the ICU User
   * Guide</a>.
   *
   * <p>For backwards compatibility, the rounding mode is specified as an int argument, which can be
   * from either the constants in {@link BigDecimal} or the ordinal value of {@link RoundingMode}.
   * The following two calls are functionally equivalent.
   *
   * <pre>
   * df.setRoundingMode(BigDecimal.ROUND_CEILING);
   * df.setRoundingMode(RoundingMode.CEILING.ordinal());
   * </pre>
   *
   * @param roundingMode The integer constant rounding mode to use when formatting numbers.
   * @category Rounding
   * @stable ICU 2.0
   */
  @Override
  public synchronized void setRoundingMode(int roundingMode) {
    properties.setRoundingMode(RoundingMode.valueOf(roundingMode));
    refreshFormatter();
  }

  /**
   * {@icu} Returns the {@link java.math.MathContext} being used to round numbers.
   *
   * @see #setMathContext
   * @category Rounding
   * @stable ICU 4.2
   */
  public synchronized java.math.MathContext getMathContext() {
    java.math.MathContext mathContext = exportedProperties.getMathContext();
    assert mathContext != null;
    return mathContext;
  }

  /**
   * {@icu} <strong>Rounding and Digit Limits:</strong> Sets the {@link java.math.MathContext} used
   * to round numbers. A "math context" encodes both a rounding mode and a number of significant
   * digits. Most users should call {@link #setRoundingMode} and/or {@link
   * #setMaximumSignificantDigits} instead of this method.
   *
   * <p>When formatting, since no division is ever performed, the default MathContext is unlimited
   * significant digits. However, when division occurs during parsing to correct for percentages and
   * multipliers, a MathContext of 34 digits, the IEEE 754R Decimal128 standard, is used by default.
   * If you require more than 34 digits when parsing, you can set a custom MathContext using this
   * method.
   *
   * @param mathContext The MathContext to use when rounding numbers.
   * @throws ArithmeticException when inverting multiplier produces a non-terminating decimal result
   *         in conjunction with MathContext of unlimited precision.
   * @see java.math.MathContext
   * @category Rounding
   * @stable ICU 4.2
   */
  public synchronized void setMathContext(java.math.MathContext mathContext) {
    properties.setMathContext(mathContext);
    refreshFormatter();
  }

  // Remember the ICU math context form in order to be able to return it from the API.
  // NOTE: This value is not serialized. (should it be?)
  private transient int icuMathContextForm = MathContext.PLAIN;

  /**
   * {@icu} Returns the {@link com.ibm.icu.math.MathContext} being used to round numbers.
   *
   * @see #setMathContext
   * @category Rounding
   * @stable ICU 4.2
   */
  public synchronized MathContext getMathContextICU() {
    java.math.MathContext mathContext = getMathContext();
    return new MathContext(
        mathContext.getPrecision(),
        icuMathContextForm,
        false,
        mathContext.getRoundingMode().ordinal());
  }

  /**
   * {@icu} <strong>Rounding and Digit Limits:</strong> Overload of {@link #setMathContext} for
   * {@link com.ibm.icu.math.MathContext}.
   *
   * @param mathContextICU The MathContext to use when rounding numbers.
   * @throws ArithmeticException when inverting multiplier produces a non-terminating decimal result
   *         in conjunction with MathContext of unlimited precision.
   * @see #setMathContext(java.math.MathContext)
   * @category Rounding
   * @stable ICU 4.2
   */
  public synchronized void setMathContextICU(MathContext mathContextICU) {
    icuMathContextForm = mathContextICU.getForm();
    java.math.MathContext mathContext;
    if (mathContextICU.getLostDigits()) {
      // The getLostDigits() feature in ICU MathContext means "throw an ArithmeticException if
      // rounding causes digits to be lost". That feature is called RoundingMode.UNNECESSARY in
      // Java MathContext.
      mathContext = new java.math.MathContext(mathContextICU.getDigits(), RoundingMode.UNNECESSARY);
    } else {
      mathContext =
          new java.math.MathContext(
              mathContextICU.getDigits(), RoundingMode.valueOf(mathContextICU.getRoundingMode()));
    }
    setMathContext(mathContext);
  }

  /**
   * Returns the effective minimum number of digits before the decimal separator.
   *
   * @see #setMinimumIntegerDigits
   * @category Rounding
   * @stable ICU 2.0
   */
  @Override
  public synchronized int getMinimumIntegerDigits() {
    return exportedProperties.getMinimumIntegerDigits();
  }

  /**
   * <strong>Rounding and Digit Limits:</strong> Sets the minimum number of digits to display before
   * the decimal separator. If the number has fewer than this many digits, the number is padded with
   * zeros.
   *
   * <p>For example, if minimum integer digits is 3, the number 12.3 will be printed as "001.23".
   *
   * <p>Minimum integer and minimum and maximum fraction digits can be specified via the pattern
   * string. For example, "#,#00.00#" has 2 minimum integer digits, 2 minimum fraction digits, and 3
   * maximum fraction digits. Note that it is not possible to specify maximium integer digits in the
   * pattern except in scientific notation.
   *
   * <p>If minimum and maximum integer, fraction, or significant digits conflict with each other,
   * the most recently specified value is used. For example, if there is a formatter with minInt=5,
   * and then you set maxInt=3, then minInt will be changed to 3.
   *
   * @param value The minimum number of digits before the decimal separator.
   * @category Rounding
   * @stable ICU 2.0
   */
  @Override
  public synchronized void setMinimumIntegerDigits(int value) {
    // For backwards compatibility, conflicting min/max need to keep the most recent setting.
    int max = properties.getMaximumIntegerDigits();
    if (max >= 0 && max < value) {
      properties.setMaximumIntegerDigits(value);
    }
    properties.setMinimumIntegerDigits(value);
    refreshFormatter();
  }

  /**
   * Returns the effective maximum number of digits before the decimal separator.
   *
   * @see #setMaximumIntegerDigits
   * @category Rounding
   * @stable ICU 2.0
   */
  @Override
  public synchronized int getMaximumIntegerDigits() {
    return exportedProperties.getMaximumIntegerDigits();
  }

  /**
   * <strong>Rounding and Digit Limits:</strong> Sets the maximum number of digits to display before
   * the decimal separator. If the number has more than this many digits, the number is truncated.
   *
   * <p>For example, if maximum integer digits is 3, the number 12345 will be printed as "345".
   *
   * <p>Minimum integer and minimum and maximum fraction digits can be specified via the pattern
   * string. For example, "#,#00.00#" has 2 minimum integer digits, 2 minimum fraction digits, and 3
   * maximum fraction digits. Note that it is not possible to specify maximium integer digits in the
   * pattern except in scientific notation.
   *
   * <p>If minimum and maximum integer, fraction, or significant digits conflict with each other,
   * the most recently specified value is used. For example, if there is a formatter with minInt=5,
   * and then you set maxInt=3, then minInt will be changed to 3.
   *
   * @param value The maximum number of digits before the decimal separator.
   * @category Rounding
   * @stable ICU 2.0
   */
  @Override
  public synchronized void setMaximumIntegerDigits(int value) {
    int min = properties.getMinimumIntegerDigits();
    if (min >= 0 && min > value) {
      properties.setMinimumIntegerDigits(value);
    }
    properties.setMaximumIntegerDigits(value);
    refreshFormatter();
  }

  /**
   * Returns the effective minimum number of integer digits after the decimal separator.
   *
   * @see #setMaximumIntegerDigits
   * @category Rounding
   * @stable ICU 2.0
   */
  @Override
  public synchronized int getMinimumFractionDigits() {
    return exportedProperties.getMinimumFractionDigits();
  }

  /**
   * <strong>Rounding and Digit Limits:</strong> Sets the minimum number of digits to display after
   * the decimal separator. If the number has fewer than this many digits, the number is padded with
   * zeros.
   *
   * <p>For example, if minimum fraction digits is 2, the number 123.4 will be printed as "123.40".
   *
   * <p>Minimum integer and minimum and maximum fraction digits can be specified via the pattern
   * string. For example, "#,#00.00#" has 2 minimum integer digits, 2 minimum fraction digits, and 3
   * maximum fraction digits. Note that it is not possible to specify maximium integer digits in the
   * pattern except in scientific notation.
   *
   * <p>If minimum and maximum integer, fraction, or significant digits conflict with each other,
   * the most recently specified value is used. For example, if there is a formatter with minInt=5,
   * and then you set maxInt=3, then minInt will be changed to 3.
   *
   * <p>See {@link #setRoundingIncrement} and {@link #setMaximumSignificantDigits} for two other
   * ways of specifying rounding strategies.
   *
   * @param value The minimum number of integer digits after the decimal separator.
   * @see #setRoundingMode
   * @see #setRoundingIncrement
   * @see #setMaximumSignificantDigits
   * @category Rounding
   * @stable ICU 2.0
   */
  @Override
  public synchronized void setMinimumFractionDigits(int value) {
    int max = properties.getMaximumFractionDigits();
    if (max >= 0 && max < value) {
      properties.setMaximumFractionDigits(value);
    }
    properties.setMinimumFractionDigits(value);
    refreshFormatter();
  }

  /**
   * Returns the effective maximum number of integer digits after the decimal separator.
   *
   * @see #setMaximumIntegerDigits
   * @category Rounding
   * @stable ICU 2.0
   */
  @Override
  public synchronized int getMaximumFractionDigits() {
    return exportedProperties.getMaximumFractionDigits();
  }

  /**
   * <strong>Rounding and Digit Limits:</strong> Sets the maximum number of digits to display after
   * the decimal separator. If the number has more than this many digits, the number is rounded
   * according to the rounding mode.
   *
   * <p>For example, if maximum fraction digits is 2, the number 123.456 will be printed as
   * "123.46".
   *
   * <p>Minimum integer and minimum and maximum fraction digits can be specified via the pattern
   * string. For example, "#,#00.00#" has 2 minimum integer digits, 2 minimum fraction digits, and 3
   * maximum fraction digits. Note that it is not possible to specify maximium integer digits in the
   * pattern except in scientific notation.
   *
   * <p>If minimum and maximum integer, fraction, or significant digits conflict with each other,
   * the most recently specified value is used. For example, if there is a formatter with minInt=5,
   * and then you set maxInt=3, then minInt will be changed to 3.
   *
   * @param value The maximum number of integer digits after the decimal separator.
   * @see #setRoundingMode
   * @category Rounding
   * @stable ICU 2.0
   */
  @Override
  public synchronized void setMaximumFractionDigits(int value) {
    int min = properties.getMinimumFractionDigits();
    if (min >= 0 && min > value) {
      properties.setMinimumFractionDigits(value);
    }
    properties.setMaximumFractionDigits(value);
    refreshFormatter();
  }

  /**
   * {@icu} Returns whether significant digits are being used in rounding.
   *
   * @see #setSignificantDigitsUsed
   * @category Rounding
   * @stable ICU 3.0
   */
  public synchronized boolean areSignificantDigitsUsed() {
    return properties.getMinimumSignificantDigits() != -1
        || properties.getMaximumSignificantDigits() != -1;
  }

  /**
   * {@icu} <strong>Rounding and Digit Limits:</strong> Sets whether significant digits are to be
   * used in rounding.
   *
   * <p>Calling <code>df.setSignificantDigitsUsed(true)</code> is functionally equivalent to:
   *
   * <pre>
   * df.setMinimumSignificantDigits(1);
   * df.setMaximumSignificantDigits(6);
   * </pre>
   *
   * @param useSignificantDigits true to enable significant digit rounding; false to disable it.
   * @category Rounding
   * @stable ICU 3.0
   */
  public synchronized void setSignificantDigitsUsed(boolean useSignificantDigits) {
    int oldMinSig = properties.getMinimumSignificantDigits();
    int oldMaxSig = properties.getMaximumSignificantDigits();
    // These are the default values from the old implementation.
    if (useSignificantDigits) {
      if (oldMinSig != -1 || oldMaxSig != -1) {
        return;
      }
    } else {
      if (oldMinSig == -1 && oldMaxSig == -1) {
        return;
      }
    }
    int minSig = useSignificantDigits ? 1 : -1;
    int maxSig = useSignificantDigits ? 6 : -1;
    properties.setMinimumSignificantDigits(minSig);
    properties.setMaximumSignificantDigits(maxSig);
    refreshFormatter();
  }

  /**
   * {@icu} Returns the effective minimum number of significant digits displayed.
   *
   * @see #setMinimumSignificantDigits
   * @category Rounding
   * @stable ICU 3.0
   */
  public synchronized int getMinimumSignificantDigits() {
    return exportedProperties.getMinimumSignificantDigits();
  }

  /**
   * {@icu} <strong>Rounding and Digit Limits:</strong> Sets the minimum number of significant
   * digits to be displayed. If the number of significant digits is less than this value, the number
   * will be padded with zeros as necessary.
   *
   * <p>For example, if minimum significant digits is 3 and the number is 1.2, the number will be
   * printed as "1.20".
   *
   * <p>If minimum and maximum integer, fraction, or significant digits conflict with each other,
   * the most recently specified value is used. For example, if there is a formatter with minInt=5,
   * and then you set maxInt=3, then minInt will be changed to 3.
   *
   * @param value The minimum number of significant digits to display.
   * @category Rounding
   * @stable ICU 3.0
   */
  public synchronized void setMinimumSignificantDigits(int value) {
    int max = properties.getMaximumSignificantDigits();
    if (max >= 0 && max < value) {
      properties.setMaximumSignificantDigits(value);
    }
    properties.setMinimumSignificantDigits(value);
    refreshFormatter();
  }

  /**
   * {@icu} Returns the effective maximum number of significant digits displayed.
   *
   * @see #setMaximumSignificantDigits
   * @category Rounding
   * @stable ICU 3.0
   */
  public synchronized int getMaximumSignificantDigits() {
    return exportedProperties.getMaximumSignificantDigits();
  }

  /**
   * {@icu} <strong>Rounding and Digit Limits:</strong> Sets the maximum number of significant
   * digits to be displayed. If the number of significant digits in the number exceeds this value,
   * the number will be rounded according to the current rounding mode.
   *
   * <p>For example, if maximum significant digits is 3 and the number is 12345, the number will be
   * printed as "12300".
   *
   * <p>If minimum and maximum integer, fraction, or significant digits conflict with each other,
   * the most recently specified value is used. For example, if there is a formatter with minInt=5,
   * and then you set maxInt=3, then minInt will be changed to 3.
   *
   * <p>See {@link #setRoundingIncrement} and {@link #setMaximumFractionDigits} for two other ways
   * of specifying rounding strategies.
   *
   * @param value The maximum number of significant digits to display.
   * @see #setRoundingMode
   * @see #setRoundingIncrement
   * @see #setMaximumFractionDigits
   * @category Rounding
   * @stable ICU 3.0
   */
  public synchronized void setMaximumSignificantDigits(int value) {
    int min = properties.getMinimumSignificantDigits();
    if (min >= 0 && min > value) {
      properties.setMinimumSignificantDigits(value);
    }
    properties.setMaximumSignificantDigits(value);
    refreshFormatter();
  }

  /**
   * Returns the minimum number of characters in formatted output.
   *
   * @see #setFormatWidth
   * @category Padding
   * @stable ICU 2.0
   */
  public synchronized int getFormatWidth() {
    return properties.getFormatWidth();
  }

  /**
   * <strong>Padding:</strong> Sets the minimum width of the string output by the formatting
   * pipeline. For example, if padding is enabled and paddingWidth is set to 6, formatting the
   * number "3.14159" with the pattern "0.00" will result in "··3.14" if '·' is your padding string.
   *
   * <p>If the number is longer than your padding width, the number will display as if no padding
   * width had been specified, which may result in strings longer than the padding width.
   *
   * <p>Padding can be specified in the pattern string using the '*' symbol. For example, the format
   * "*x######0" has a format width of 7 and a pad character of 'x'.
   *
   * <p>Padding is currently counted in UTF-16 code units; see <a
   * href="http://bugs.icu-project.org/trac/ticket/13034">ticket #13034</a> for more information.
   *
   * @param width The minimum number of characters in the output.
   * @see #setPadCharacter
   * @see #setPadPosition
   * @category Padding
   * @stable ICU 2.0
   */
  public synchronized void setFormatWidth(int width) {
    properties.setFormatWidth(width);
    refreshFormatter();
  }

  /**
   * {@icu} Returns the character used for padding.
   *
   * @see #setPadCharacter
   * @category Padding
   * @stable ICU 2.0
   */
  public synchronized char getPadCharacter() {
    CharSequence paddingString = properties.getPadString();
    if (paddingString == null) {
      return Padder.FALLBACK_PADDING_STRING.charAt(0);
    } else {
      return paddingString.charAt(0);
    }
  }

  /**
   * {@icu} <strong>Padding:</strong> Sets the character used to pad numbers that are narrower than
   * the width specified in {@link #setFormatWidth}.
   *
   * <p>In the pattern string, the padding character is the token that follows '*' before or after
   * the prefix or suffix.
   *
   * @param padChar The character used for padding.
   * @see #setFormatWidth
   * @category Padding
   * @stable ICU 2.0
   */
  public synchronized void setPadCharacter(char padChar) {
    properties.setPadString(Character.toString(padChar));
    refreshFormatter();
  }

  /**
   * {@icu} Returns the position used for padding.
   *
   * @see #setPadPosition
   * @category Padding
   * @stable ICU 2.0
   */
  public synchronized int getPadPosition() {
    PadPosition loc = properties.getPadPosition();
    return (loc == null) ? PAD_BEFORE_PREFIX : loc.toOld();
  }

  /**
   * {@icu} <strong>Padding:</strong> Sets the position where to insert the pad character when
   * narrower than the width specified in {@link #setFormatWidth}. For example, consider the pattern
   * "P123S" with padding width 8 and padding char "*". The four positions are:
   *
   * <ul>
   *   <li>{@link DecimalFormat#PAD_BEFORE_PREFIX} ⇒ "***P123S"
   *   <li>{@link DecimalFormat#PAD_AFTER_PREFIX} ⇒ "P***123S"
   *   <li>{@link DecimalFormat#PAD_BEFORE_SUFFIX} ⇒ "P123***S"
   *   <li>{@link DecimalFormat#PAD_AFTER_SUFFIX} ⇒ "P123S***"
   * </ul>
   *
   * @param padPos The position used for padding.
   * @see #setFormatWidth
   * @category Padding
   * @stable ICU 2.0
   */
  public synchronized void setPadPosition(int padPos) {
    properties.setPadPosition(PadPosition.fromOld(padPos));
    refreshFormatter();
  }

  /**
   * {@icu} Returns whether scientific (exponential) notation is enabled on this formatter.
   *
   * @see #setScientificNotation
   * @category ScientificNotation
   * @stable ICU 2.0
   */
  public synchronized boolean isScientificNotation() {
    return properties.getMinimumExponentDigits() != -1;
  }

  /**
   * {@icu} <strong>Scientific Notation:</strong> Sets whether this formatter should print in
   * scientific (exponential) notation. For example, if scientific notation is enabled, the number
   * 123000 will be printed as "1.23E5" in locale <em>en-US</em>. A locale-specific symbol is used
   * as the exponent separator.
   *
   * <p>Calling <code>df.setScientificNotation(true)</code> is functionally equivalent to calling
   * <code>df.setMinimumExponentDigits(1)</code>.
   *
   * @param useScientific true to enable scientific notation; false to disable it.
   * @see #setMinimumExponentDigits
   * @category ScientificNotation
   * @stable ICU 2.0
   */
  public synchronized void setScientificNotation(boolean useScientific) {
    if (useScientific) {
      properties.setMinimumExponentDigits(1);
    } else {
      properties.setMinimumExponentDigits(-1);
    }
    refreshFormatter();
  }

  /**
   * {@icu} Returns the minimum number of digits printed in the exponent in scientific notation.
   *
   * @see #setMinimumExponentDigits
   * @category ScientificNotation
   * @stable ICU 2.0
   */
  public synchronized byte getMinimumExponentDigits() {
    return (byte) properties.getMinimumExponentDigits();
  }

  /**
   * {@icu} <strong>Scientific Notation:</strong> Sets the minimum number of digits to be printed in
   * the exponent. For example, if minimum exponent digits is 3, the number 123000 will be printed
   * as "1.23E005".
   *
   * <p>This setting corresponds to the number of zeros after the 'E' in a pattern string such as
   * "0.00E000".
   *
   * @param minExpDig The minimum number of digits in the exponent.
   * @category ScientificNotation
   * @stable ICU 2.0
   */
  public synchronized void setMinimumExponentDigits(byte minExpDig) {
    properties.setMinimumExponentDigits(minExpDig);
    refreshFormatter();
  }

  /**
   * {@icu} Returns whether the sign (plus or minus) is always printed in scientific notation.
   *
   * @see #setExponentSignAlwaysShown
   * @category ScientificNotation
   * @stable ICU 2.0
   */
  public synchronized boolean isExponentSignAlwaysShown() {
    return properties.getExponentSignAlwaysShown();
  }

  /**
   * {@icu} <strong>Scientific Notation:</strong> Sets whether the sign (plus or minus) is always to
   * be shown in the exponent in scientific notation. For example, if this setting is enabled, the
   * number 123000 will be printed as "1.23E+5" in locale <em>en-US</em>. The number 0.0000123 will
   * always be printed as "1.23E-5" in locale <em>en-US</em> whether or not this setting is enabled.
   *
   * <p>This setting corresponds to the '+' in a pattern such as "0.00E+0".
   *
   * @param expSignAlways true to always shown the sign in the exponent; false to show it for
   *     negatives but not positives.
   * @category ScientificNotation
   * @stable ICU 2.0
   */
  public synchronized void setExponentSignAlwaysShown(boolean expSignAlways) {
    properties.setExponentSignAlwaysShown(expSignAlways);
    refreshFormatter();
  }

  /**
   * Returns whether or not grouping separators are being printed in the output.
   *
   * @see #setGroupingUsed
   * @category Separators
   * @stable ICU 2.0
   */
  @Override
  public synchronized boolean isGroupingUsed() {
    return properties.getGroupingUsed();
  }

  /**
   * <strong>Grouping:</strong> Sets whether grouping is to be used when formatting numbers.
   * Grouping means whether the thousands, millions, billions, and larger powers of ten should be
   * separated by a grouping separator (a comma in <em>en-US</em>).
   *
   * <p>For example, if grouping is enabled, 12345 will be printed as "12,345" in <em>en-US</em>. If
   * grouping were disabled, it would instead be printed as simply "12345".
   *
   * @param enabled true to enable grouping separators; false to disable them.
   * @see #setGroupingSize
   * @see #setSecondaryGroupingSize
   * @category Separators
   * @stable ICU 2.0
   */
  @Override
  public synchronized void setGroupingUsed(boolean enabled) {
    properties.setGroupingUsed(enabled);
    refreshFormatter();
  }

  /**
   * Returns the primary grouping size in use.
   *
   * @see #setGroupingSize
   * @category Separators
   * @stable ICU 2.0
   */
  public synchronized int getGroupingSize() {
    if (properties.getGroupingSize() < 0) {
      return 0;
    }
    return properties.getGroupingSize();
  }

  /**
   * <strong>Grouping:</strong> Sets the primary grouping size (distance between grouping
   * separators) used when formatting large numbers. For most locales, this defaults to 3: the
   * number of digits between the ones and thousands place, between thousands and millions, and so
   * forth.
   *
   * <p>For example, with a grouping size of 3, the number 1234567 will be formatted as "1,234,567".
   *
   * <p>Grouping size can also be specified in the pattern: for example, "#,##0" corresponds to a
   * grouping size of 3.
   *
   * @param width The grouping size to use.
   * @see #setSecondaryGroupingSize
   * @category Separators
   * @stable ICU 2.0
   */
  public synchronized void setGroupingSize(int width) {
    properties.setGroupingSize(width);
    refreshFormatter();
  }

  /**
   * {@icu} Returns the secondary grouping size in use.
   *
   * @see #setSecondaryGroupingSize
   * @category Separators
   * @stable ICU 2.0
   */
  public synchronized int getSecondaryGroupingSize() {
    int grouping2 = properties.getSecondaryGroupingSize();
    if (grouping2 < 0) {
      return 0;
    }
    return grouping2;
  }

  /**
   * {@icu} <strong>Grouping:</strong> Sets the secondary grouping size (distance between grouping
   * separators after the first separator) used when formatting large numbers. In many south Asian
   * locales, this is set to 2.
   *
   * <p>For example, with primary grouping size 3 and secondary grouping size 2, the number 1234567
   * will be formatted as "12,34,567".
   *
   * <p>Grouping size can also be specified in the pattern: for example, "#,##,##0" corresponds to a
   * primary grouping size of 3 and a secondary grouping size of 2.
   *
   * @param width The secondary grouping size to use.
   * @see #setGroupingSize
   * @category Separators
   * @stable ICU 2.0
   */
  public synchronized void setSecondaryGroupingSize(int width) {
    properties.setSecondaryGroupingSize(width);
    refreshFormatter();
  }

  /**
   * {@icu} Returns the minimum number of digits before grouping is triggered.
   *
   * @see #setMinimumGroupingDigits
   * @category Separators
   * @stable ICU 64
   */
  public synchronized int getMinimumGroupingDigits() {
    if (properties.getMinimumGroupingDigits() > 0) {
      return properties.getMinimumGroupingDigits();
    }
    return 1;
  }

  /**
   * {@icu} Sets the minimum number of digits that must be before the first grouping separator in
   * order for the grouping separator to be printed. For example, if minimum grouping digits is set
   * to 2, in <em>en-US</em>, 1234 will be printed as "1234" and 12345 will be printed as "12,345".
   *
    * Set the value to:
   * <ul>
   * <li>1 to turn off minimum grouping digits.</li>
   * <li>MINIMUM_GROUPING_DIGITS_AUTO to display grouping using the default
   * strategy for all locales.</li>
   * <li>MINIMUM_GROUPING_DIGITS_MIN2 to display grouping using locale defaults,
   * except do not show grouping on values smaller than 10000 (such that there is a minimum of
   * two digits before the first separator).</li>
   * </ul>
   *
   * @param number The minimum number of digits before grouping is triggered.
   * @category Separators
   * @stable ICU 64
   */
  public synchronized void setMinimumGroupingDigits(int number) {
    properties.setMinimumGroupingDigits(number);
    refreshFormatter();
  }

  /**
   * {@icu} Constant for {@link #setMinimumGroupingDigits()} to specify display
   * grouping using the default strategy for all locales.
   *
   * @see #setMinimumGroupingDigits
   * @see #MINIMUM_GROUPING_DIGITS_MIN2
   * @category Separators
   * @provisional This API might change or be removed in a future release.
   * @draft ICU 68
   */
  public static final int MINIMUM_GROUPING_DIGITS_AUTO = -2;

  /**
   * {@icu} Constant for {@link #setMinimumGroupingDigits()} to specify display
   * grouping using locale defaults, except do not show grouping on values smaller than
   * 10000 (such that there is a minimum of two digits before the first separator).
   *
   * @see #setMinimumGroupingDigits
   * @see #MINIMUM_GROUPING_DIGITS_AUTO
   * @category Separators
   * @provisional This API might change or be removed in a future release.
   * @draft ICU 68
   */
  public static final int MINIMUM_GROUPING_DIGITS_MIN2 = -3;

  /**
   * Returns whether the decimal separator is shown on integers.
   *
   * @see #setDecimalSeparatorAlwaysShown
   * @category Separators
   * @stable ICU 2.0
   */
  public synchronized boolean isDecimalSeparatorAlwaysShown() {
    return properties.getDecimalSeparatorAlwaysShown();
  }

  /**
   * <strong>Separators:</strong> Sets whether the decimal separator (a period in <em>en-US</em>) is
   * shown on integers. For example, if this setting is turned on, formatting 123 will result in
   * "123." with the decimal separator.
   *
   * <p>This setting can be specified in the pattern for integer formats: "#,##0." is an example.
   *
   * @param value true to always show the decimal separator; false to show it only when there is a
   *     fraction part of the number.
   * @category Separators
   * @stable ICU 2.0
   */
  public synchronized void setDecimalSeparatorAlwaysShown(boolean value) {
    properties.setDecimalSeparatorAlwaysShown(value);
    refreshFormatter();
  }

  /**
   * Returns the currency used to display currency amounts. May be null.
   *
   * @see #setCurrency
   * @see DecimalFormatSymbols#getCurrency
   * @category Currency
   * @stable ICU 2.6
   */
  @Override
  public synchronized Currency getCurrency() {
    return exportedProperties.getCurrency();
  }

  /**
   * Sets the currency to be used when formatting numbers. The effect is twofold:
   *
   * <ol>
   *   <li>Substitutions for currency symbols in the pattern string will use this currency
   *   <li>The rounding mode will obey the rules for this currency (see {@link #setCurrencyUsage})
   * </ol>
   *
   * <strong>Important:</strong> Displaying the currency in the output requires that the patter
   * associated with this formatter contains a currency symbol '¤'. This will be the case if the
   * instance was created via {@link #getCurrencyInstance} or one of its friends.
   *
   * @param currency The currency to use.
   * @category Currency
   * @stable ICU 2.2
   */
  @Override
  public synchronized void setCurrency(Currency currency) {
    properties.setCurrency(currency);
    if (currency != null) {
      symbols.setCurrency(currency);
    }
    refreshFormatter();
  }

  /**
   * {@icu} Returns the strategy for rounding currency amounts.
   *
   * @see #setCurrencyUsage
   * @category Currency
   * @stable ICU 54
   */
  public synchronized CurrencyUsage getCurrencyUsage() {
    // CurrencyUsage is not exported, so we have to get it from the input property bag.
    // TODO: Should we export CurrencyUsage instead?
    CurrencyUsage usage = properties.getCurrencyUsage();
    if (usage == null) {
      usage = CurrencyUsage.STANDARD;
    }
    return usage;
  }

  /**
   * {@icu} Sets the currency-dependent strategy to use when rounding numbers. There are two
   * strategies:
   *
   * <ul>
   *   <li>STANDARD: When the amount displayed is intended for banking statements or electronic
   *       transfer.
   *   <li>CASH: When the amount displayed is intended to be representable in physical currency,
   *       like at a cash register.
   * </ul>
   *
   * CASH mode is relevant in currencies that do not have tender down to the penny. For more
   * information on the two rounding strategies, see <a
   * href="http://unicode.org/reports/tr35/tr35-numbers.html#Supplemental_Currency_Data">UTS
   * #35</a>. If omitted, the strategy defaults to STANDARD. To override currency rounding
   * altogether, use {@link #setMinimumFractionDigits} and {@link #setMaximumFractionDigits} or
   * {@link #setRoundingIncrement}.
   *
   * @param usage The strategy to use when rounding in the current currency.
   * @category Currency
   * @stable ICU 54
   */
  public synchronized void setCurrencyUsage(CurrencyUsage usage) {
    properties.setCurrencyUsage(usage);
    refreshFormatter();
  }

  /**
   * {@icu} Returns the current instance of CurrencyPluralInfo.
   *
   * @see #setCurrencyPluralInfo
   * @category Currency
   * @stable ICU 4.2
   */
  public synchronized CurrencyPluralInfo getCurrencyPluralInfo() {
    // CurrencyPluralInfo also is not exported.
    return properties.getCurrencyPluralInfo();
  }

  /**
   * {@icu} Sets a custom instance of CurrencyPluralInfo. CurrencyPluralInfo generates pattern
   * strings for printing currency long names.
   *
   * <p><strong>Most users should not call this method directly.</strong> You should instead create
   * your formatter via <code>NumberFormat.getInstance(NumberFormat.PLURALCURRENCYSTYLE)</code>.
   *
   * @param newInfo The CurrencyPluralInfo to use when printing currency long names.
   * @category Currency
   * @stable ICU 4.2
   */
  public synchronized void setCurrencyPluralInfo(CurrencyPluralInfo newInfo) {
    properties.setCurrencyPluralInfo(newInfo);
    refreshFormatter();
  }

  /**
   * Returns whether {@link #parse} will always return a BigDecimal.
   *
   * @see #setParseBigDecimal
   * @category Parsing
   * @stable ICU 3.6
   */
  public synchronized boolean isParseBigDecimal() {
    return properties.getParseToBigDecimal();
  }

  /**
   * Whether to make {@link #parse} prefer returning a {@link com.ibm.icu.math.BigDecimal} when
   * possible. For strings corresponding to return values of Infinity, -Infinity, NaN, and -0.0, a
   * Double will be returned even if ParseBigDecimal is enabled.
   *
   * @param value true to cause {@link #parse} to prefer BigDecimal; false to let {@link #parse}
   *     return additional data types like Long or BigInteger.
   * @category Parsing
   * @stable ICU 3.6
   */
  public synchronized void setParseBigDecimal(boolean value) {
    properties.setParseToBigDecimal(value);
    refreshFormatter();
  }

  /**
   * Always returns 1000, the default prior to ICU 59.
   *
   * @category Parsing
   * @deprecated Setting max parse digits has no effect since ICU4J 59.
   */
  @Deprecated
  public int getParseMaxDigits() {
    return 1000;
  }

  /**
   * @param maxDigits Prior to ICU 59, the maximum number of digits in the output number after
   *     exponential notation is applied.
   * @category Parsing
   * @deprecated Setting max parse digits has no effect since ICU4J 59.
   */
  @Deprecated
  public void setParseMaxDigits(int maxDigits) {}

  /**
   * {@inheritDoc}
   *
   * @category Parsing
   * @stable ICU 3.6
   */
  @Override
  public synchronized boolean isParseStrict() {
    return properties.getParseMode() == ParseMode.STRICT;
  }

  /**
   * {@inheritDoc}
   *
   * @category Parsing
   * @stable ICU 3.6
   */
  @Override
  public synchronized void setParseStrict(boolean parseStrict) {
    ParseMode mode = parseStrict ? ParseMode.STRICT : ParseMode.LENIENT;
    properties.setParseMode(mode);
    refreshFormatter();
  }

  /**
   * Android libcore uses this internal method to set {@link ParseMode#JAVA_COMPATIBILITY}.
   * @internal
   * @deprecated This API is ICU internal only.
   */
  @Deprecated
public synchronized void setParseStrictMode(ParseMode parseMode) {
    properties.setParseMode(parseMode);
    refreshFormatter();
  }

  /**
   * {@inheritDoc}
   *
   * @see #setParseIntegerOnly
   * @category Parsing
   * @stable ICU 2.0
   */
  @Override
  public synchronized boolean isParseIntegerOnly() {
    return properties.getParseIntegerOnly();
  }

  /**
   * <strong>Parsing:</strong> {@inheritDoc}
   *
   * <p>This is functionally equivalent to calling {@link #setDecimalPatternMatchRequired} and a
   * pattern without a decimal point.
   *
   * @param parseIntegerOnly true to ignore fractional parts of numbers when parsing; false to
   *     consume fractional parts.
   * @category Parsing
   * @stable ICU 2.0
   */
  @Override
  public synchronized void setParseIntegerOnly(boolean parseIntegerOnly) {
    properties.setParseIntegerOnly(parseIntegerOnly);
    refreshFormatter();
  }

  /**
   * {@icu} Returns whether the presence of a decimal point must match the pattern.
   *
   * @see #setDecimalPatternMatchRequired
   * @category Parsing
   * @stable ICU 54
   */
  public synchronized boolean isDecimalPatternMatchRequired() {
    return properties.getDecimalPatternMatchRequired();
  }

  /**
   * {@icu} <strong>Parsing:</strong> This method is used to either <em>require</em> or
   * <em>forbid</em> the presence of a decimal point in the string being parsed (disabled by
   * default). This feature was designed to be an extra layer of strictness on top of strict
   * parsing, although it can be used in either lenient mode or strict mode.
   *
   * <p>To <em>require</em> a decimal point, call this method in combination with either a pattern
   * containing a decimal point or with {@link #setDecimalSeparatorAlwaysShown}.
   *
   * <pre>
   * // Require a decimal point in the string being parsed:
   * df.applyPattern("#.");
   * df.setDecimalPatternMatchRequired(true);
   *
   * // Alternatively:
   * df.setDecimalSeparatorAlwaysShown(true);
   * df.setDecimalPatternMatchRequired(true);
   * </pre>
   *
   * To <em>forbid</em> a decimal point, call this method in combination with a pattern containing
   * no decimal point. Alternatively, use {@link #setParseIntegerOnly} for the same behavior without
   * depending on the contents of the pattern string.
   *
   * <pre>
   * // Forbid a decimal point in the string being parsed:
   * df.applyPattern("#");
   * df.setDecimalPatternMatchRequired(true);
   * </pre>
   *
   * @param value true to either require or forbid the decimal point according to the pattern; false
   *     to disable this feature.
   * @see #setParseIntegerOnly
   * @category Parsing
   * @stable ICU 54
   */
  public synchronized void setDecimalPatternMatchRequired(boolean value) {
    properties.setDecimalPatternMatchRequired(value);
    refreshFormatter();
  }

  /**
   * {@icu} Returns whether to ignore exponents when parsing.
   *
   * @see #setParseNoExponent
   * @category Parsing
   * @stable ICU 64
   */
  public synchronized boolean isParseNoExponent() {
    return properties.getParseNoExponent();
  }

  /**
   * {@icu} Specifies whether to stop parsing when an exponent separator is encountered. For
   * example, parses "123E4" to 123 (with parse position 3) instead of 1230000 (with parse position
   * 5).
   *
   * @param value true to prevent exponents from being parsed; false to allow them to be parsed.
   * @category Parsing
   * @stable ICU 64
   */
  public synchronized void setParseNoExponent(boolean value) {
    properties.setParseNoExponent(value);
    refreshFormatter();
  }

  /**
   * {@icu} Returns whether to force case (uppercase/lowercase) to match when parsing.
   *
   * @see #setParseNoExponent
   * @category Parsing
   * @stable ICU 64
   */
  public synchronized boolean isParseCaseSensitive() {
    return properties.getParseCaseSensitive();
  }

  /**
   * {@icu} Specifies whether parsing should require cases to match in affixes, exponent separators,
   * and currency codes. Case mapping is performed for each code point using {@link
   * UCharacter#foldCase}.
   *
   * @param value true to force case (uppercase/lowercase) to match when parsing; false to ignore
   *     case and perform case folding.
   * @category Parsing
   * @stable ICU 64
   */
  public synchronized void setParseCaseSensitive(boolean value) {
    properties.setParseCaseSensitive(value);
    refreshFormatter();
  }

  // TODO(sffc): Uncomment for ICU 60 API proposal.
  //
  //  /**
  //   * {@icu} Returns the strategy used for choosing between grouping and decimal separators when
  //   * parsing.
  //   *
  //   * @see #setParseGroupingMode
  //   * @category Parsing
  //   */
  //  public synchronized GroupingMode getParseGroupingMode() {
  //    return properties.getParseGroupingMode();
  //  }
  //
  //  /**
  //   * {@icu} Sets the strategy used during parsing when a code point needs to be interpreted as
  //   * either a decimal separator or a grouping separator.
  //   *
  //   * <p>The comma, period, space, and apostrophe have different meanings in different locales. For
  //   * example, in <em>en-US</em> and most American locales, the period is used as a decimal
  //   * separator, but in <em>es-PY</em> and most European locales, it is used as a grouping separator.
  //   *
  //   * Suppose you are in <em>fr-FR</em> the parser encounters the string "1.234".  In <em>fr-FR</em>,
  //   * the grouping is a space and the decimal is a comma.  The <em>grouping mode</em> is a mechanism
  //   * to let you specify whether to accept the string as 1234 (GroupingMode.DEFAULT) or whether to reject it since the separators
  //   * don't match (GroupingMode.RESTRICTED).
  //   *
  //   * When resolving grouping separators, it is the <em>equivalence class</em> of separators that is considered.
  //   * For example, a period is seen as equal to a fixed set of other period-like characters.
  //   *
  //   * @param groupingMode The strategy to use; either DEFAULT or RESTRICTED.
  //   * @category Parsing
  //   */
  //  public synchronized void setParseGroupingMode(GroupingMode groupingMode) {
  //    properties.setParseGroupingMode(groupingMode);
  //    refreshFormatter();
  //  }

  //=====================================================================================//
  //                                     UTILITIES                                       //
  //=====================================================================================//

  /**
   * Tests for equality between this formatter and another formatter.
   *
   * <p>If two DecimalFormat instances are equal, then they will always produce the same output.
   * However, the reverse is not necessarily true: if two DecimalFormat instances always produce the
   * same output, they are not necessarily equal.
   *
   * @stable ICU 2.0
   */
  @Override
  public synchronized boolean equals(Object obj) {
    if (obj == null) return false;
    if (obj == this) return true;
    if (!(obj instanceof DecimalFormat)) return false;
    DecimalFormat other = (DecimalFormat) obj;
    return properties.equals(other.properties) && symbols.equals(other.symbols);
  }

  /**
   * {@inheritDoc}
   *
   * @stable ICU 2.0
   */
  @Override
  public synchronized int hashCode() {
    return properties.hashCode() ^ symbols.hashCode();
  }

  /**
   * Returns the default value of toString() with extra DecimalFormat-specific information appended
   * to the end of the string. This extra information is intended for debugging purposes, and the
   * format is not guaranteed to be stable.
   *
   * @stable ICU 2.0
   */
  @Override
  public String toString() {
    StringBuilder result = new StringBuilder();
    result.append(getClass().getName());
    result.append("@");
    result.append(Integer.toHexString(hashCode()));
    result.append(" { symbols@");
    result.append(Integer.toHexString(symbols.hashCode()));
    synchronized (this) {
      properties.toStringBare(result);
    }
    result.append(" }");
    return result.toString();
  }

  /**
   * Serializes this formatter object to a decimal format pattern string. The result of this method
   * is guaranteed to be <em>functionally</em> equivalent to the pattern string used to create this
   * instance after incorporating values from the setter methods.
   *
   * <p>For more information on decimal format pattern strings, see <a
   * href="http://unicode.org/reports/tr35/tr35-numbers.html#Number_Format_Patterns">UTS #35</a>.
   *
   * <p><strong>Important:</strong> Not all properties are capable of being encoded in a pattern
   * string. See a list of properties in {@link #applyPattern}.
   *
   * @return A decimal format pattern string.
   * @stable ICU 2.0
   */
  public synchronized String toPattern() {
    // Pull some properties from exportedProperties and others from properties
    // to keep affix patterns intact.  In particular, pull rounding properties
    // so that CurrencyUsage is reflected properly.
    // TODO: Consider putting this logic in PatternString.java instead.
    DecimalFormatProperties tprops = new DecimalFormatProperties().copyFrom(properties);
    boolean useCurrency = ((tprops.getCurrency() != null)
            || tprops.getCurrencyPluralInfo() != null
            || tprops.getCurrencyUsage() != null
            || AffixUtils.hasCurrencySymbols(tprops.getPositivePrefixPattern())
            || AffixUtils.hasCurrencySymbols(tprops.getPositiveSuffixPattern())
            || AffixUtils.hasCurrencySymbols(tprops.getNegativePrefixPattern())
            || AffixUtils.hasCurrencySymbols(tprops.getNegativeSuffixPattern()));
    if (useCurrency) {
      tprops.setMinimumFractionDigits(exportedProperties.getMinimumFractionDigits());
      tprops.setMaximumFractionDigits(exportedProperties.getMaximumFractionDigits());
      tprops.setRoundingIncrement(exportedProperties.getRoundingIncrement());
    }
    return PatternStringUtils.propertiesToPatternString(tprops);
  }

  /**
   * Calls {@link #toPattern} and converts the string to localized notation. For more information on
   * localized notation, see {@link #applyLocalizedPattern}. This method is provided for backwards
   * compatibility and should not be used in new projects.
   *
   * @return A decimal format pattern string in localized notation.
   * @stable ICU 2.0
   */
  public synchronized String toLocalizedPattern() {
    String pattern = toPattern();
    return PatternStringUtils.convertLocalized(pattern, symbols, true);
  }

  /**
   * Converts this DecimalFormat to a NumberFormatter.  Starting in ICU 60,
   * NumberFormatter is the recommended way to format numbers.
   *
   * @return An instance of {@link LocalizedNumberFormatter} with the same behavior as this instance of
   * DecimalFormat.
   * @see NumberFormatter
   * @stable ICU 60
   */
  public LocalizedNumberFormatter toNumberFormatter() {
      return formatter;
  }

  /**
   * @internal
   * @deprecated This API is ICU internal only.
   */
  @Deprecated
  public IFixedDecimal getFixedDecimal(double number) {
    return formatter.format(number).getFixedDecimal();
  }

  /** Rebuilds the formatter object from the property bag. */
  void refreshFormatter() {
    if (exportedProperties == null) {
      // exportedProperties is null only when the formatter is not ready yet.
      // The only time when this happens is during legacy deserialization.
      return;
    }
    ULocale locale = this.getLocale(ULocale.ACTUAL_LOCALE);
    if (locale == null) {
      // Constructor
      locale = symbols.getLocale(ULocale.ACTUAL_LOCALE);
    }
    if (locale == null) {
      // Deserialization
      locale = symbols.getULocale();
    }
    assert locale != null;
    formatter = NumberFormatter.fromDecimalFormat(properties, symbols, exportedProperties).locale(locale);

    // Lazy-initialize the parsers only when we need them.
    parser = null;
    currencyParser = null;
  }

  NumberParserImpl getParser() {
    if (parser == null) {
      parser = NumberParserImpl.createParserFromProperties(properties, symbols, false);
    }
    return parser;
  }

  NumberParserImpl getCurrencyParser() {
    if (currencyParser == null) {
      currencyParser = NumberParserImpl.createParserFromProperties(properties, symbols, true);
    }
    return currencyParser;
  }

  /**
   * Converts a java.math.BigDecimal to a com.ibm.icu.math.BigDecimal with fallback for numbers
   * outside of the range supported by com.ibm.icu.math.BigDecimal.
   *
   * @param number
   * @return
   */
  private Number safeConvertBigDecimal(java.math.BigDecimal number) {
    try {
      return new com.ibm.icu.math.BigDecimal(number);
    } catch (NumberFormatException e) {
      if (number.signum() > 0 && number.scale() < 0) {
        return Double.POSITIVE_INFINITY;
      } else if (number.scale() < 0) {
        return Double.NEGATIVE_INFINITY;
      } else if (number.signum() < 0) {
        return -0.0;
      } else {
        return 0.0;
      }
    }
  }

  /**
   * Updates the property bag with settings from the given pattern.
   *
   * @param pattern The pattern string to parse.
   * @param ignoreRounding Whether to leave out rounding information (minFrac, maxFrac, and rounding
   *     increment) when parsing the pattern. This may be desirable if a custom rounding mode, such
   *     as CurrencyUsage, is to be used instead. One of {@link
   *     PatternStringParser#IGNORE_ROUNDING_ALWAYS}, {@link PatternStringParser#IGNORE_ROUNDING_IF_CURRENCY},
   *     or {@link PatternStringParser#IGNORE_ROUNDING_NEVER}.
   * @see PatternAndPropertyUtils#parseToExistingProperties
   */
  void setPropertiesFromPattern(String pattern, int ignoreRounding) {
    if (pattern == null) {
      throw new NullPointerException();
    }
    PatternStringParser.parseToExistingProperties(pattern, properties, ignoreRounding);
  }

  static void fieldPositionHelper(
          DecimalQuantity dq, FormattedStringBuilder string, FieldPosition fieldPosition, int offset) {
      // always return first occurrence:
      fieldPosition.setBeginIndex(0);
      fieldPosition.setEndIndex(0);
      dq.populateUFieldPosition(fieldPosition);
      boolean found = FormattedValueStringBuilderImpl.nextFieldPosition(string, fieldPosition);;
      if (found && offset != 0) {
          fieldPosition.setBeginIndex(fieldPosition.getBeginIndex() + offset);
          fieldPosition.setEndIndex(fieldPosition.getEndIndex() + offset);
      }
  }

  /**
   * @internal
   * @deprecated This API is ICU internal only.
   */
  @Deprecated
  public synchronized void setProperties(PropertySetter func) {
    func.set(properties);
    refreshFormatter();
  }

  /**
   * @internal
   * @deprecated This API is ICU internal only.
   */
  @Deprecated
  public static interface PropertySetter {
    /**
     * @internal
     * @deprecated This API is ICU internal only.
     */
    @Deprecated
    public void set(DecimalFormatProperties props);
  }

  /**
   * {@icu} Constant for {@link #getPadPosition()} and {@link #setPadPosition(int)} to specify pad
   * characters inserted before the prefix.
   *
   * @see #setPadPosition
   * @see #getPadPosition
   * @see #PAD_AFTER_PREFIX
   * @see #PAD_BEFORE_SUFFIX
   * @see #PAD_AFTER_SUFFIX
   * @stable ICU 2.0
   */
  public static final int PAD_BEFORE_PREFIX = 0;

  /**
   * {@icu} Constant for {@link #getPadPosition()} and {@link #setPadPosition(int)} to specify pad
   * characters inserted after the prefix.
   *
   * @see #setPadPosition
   * @see #getPadPosition
   * @see #PAD_BEFORE_PREFIX
   * @see #PAD_BEFORE_SUFFIX
   * @see #PAD_AFTER_SUFFIX
   * @stable ICU 2.0
   */
  public static final int PAD_AFTER_PREFIX = 1;

  /**
   * {@icu} Constant for {@link #getPadPosition()} and {@link #setPadPosition(int)} to specify pad
   * characters inserted before the suffix.
   *
   * @see #setPadPosition
   * @see #getPadPosition
   * @see #PAD_BEFORE_PREFIX
   * @see #PAD_AFTER_PREFIX
   * @see #PAD_AFTER_SUFFIX
   * @stable ICU 2.0
   */
  public static final int PAD_BEFORE_SUFFIX = 2;

  /**
   * {@icu} Constant for {@link #getPadPosition()} and {@link #setPadPosition(int)} to specify pad
   * characters inserted after the suffix.
   *
   * @see #setPadPosition
   * @see #getPadPosition
   * @see #PAD_BEFORE_PREFIX
   * @see #PAD_AFTER_PREFIX
   * @see #PAD_BEFORE_SUFFIX
   * @stable ICU 2.0
   */
  public static final int PAD_AFTER_SUFFIX = 3;
}
