]> granicus.if.org Git - icu/commitdiff
ICU-13177 Fixing ICU4J warnings in DecimalFormatProperties and CompactNotation. ...
authorShane Carr <shane@unicode.org>
Thu, 28 Sep 2017 23:26:57 +0000 (23:26 +0000)
committerShane Carr <shane@unicode.org>
Thu, 28 Sep 2017 23:26:57 +0000 (23:26 +0000)
X-SVN-Rev: 40511

icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalFormatProperties.java
icu4j/main/classes/core/src/com/ibm/icu/number/CompactNotation.java

index 3e8c8e594dcd86fa0a1ad40ca5acd784601b3128..26859abe166c0997721067e8fc11bb8d76a0304e 100644 (file)
@@ -26,1331 +26,1367 @@ import com.ibm.icu.util.Currency.CurrencyUsage;
 
 public class DecimalFormatProperties implements Cloneable, Serializable {
 
-  private static final DecimalFormatProperties DEFAULT = new DecimalFormatProperties();
-
-  /** Auto-generated. */
-  private static final long serialVersionUID = 4095518955889349243L;
-
-  // The setters in this class should NOT have any side-effects or perform any validation.  It is
-  // up to the consumer of the property bag to deal with property validation.
-
-  // The fields are all marked "transient" because custom serialization is being used.
-
-  /*--------------------------------------------------------------------------------------------+/
-  /| IMPORTANT!                                                                                 |/
-  /| WHEN ADDING A NEW PROPERTY, add it here, in #_clear(), in #_copyFrom(), in #equals(),      |/
-  /| and in #_hashCode().                                                                       |/
-  /|                                                                                            |/
-  /| The unit test PropertiesTest will catch if you forget to add it to #clear(), #copyFrom(),  |/
-  /| or #equals(), but it will NOT catch if you forget to add it to #hashCode().                |/
-  /+--------------------------------------------------------------------------------------------*/
-
-  private transient Map<String, Map<String, String>> compactCustomData;
-  private transient CompactStyle compactStyle;
-  private transient Currency currency;
-  private transient CurrencyPluralInfo currencyPluralInfo;
-  private transient CurrencyUsage currencyUsage;
-  private transient boolean decimalPatternMatchRequired;
-  private transient boolean decimalSeparatorAlwaysShown;
-  private transient boolean exponentSignAlwaysShown;
-  private transient int formatWidth;
-  private transient int groupingSize;
-  private transient int magnitudeMultiplier;
-  private transient MathContext mathContext;
-  private transient int maximumFractionDigits;
-  private transient int maximumIntegerDigits;
-  private transient int maximumSignificantDigits;
-  private transient int minimumExponentDigits;
-  private transient int minimumFractionDigits;
-  private transient int minimumGroupingDigits;
-  private transient int minimumIntegerDigits;
-  private transient int minimumSignificantDigits;
-  private transient BigDecimal multiplier;
-  private transient String negativePrefix;
-  private transient String negativePrefixPattern;
-  private transient String negativeSuffix;
-  private transient String negativeSuffixPattern;
-  private transient PadPosition padPosition;
-  private transient String padString;
-  private transient boolean parseCaseSensitive;
-  private transient GroupingMode parseGroupingMode;
-  private transient boolean parseIntegerOnly;
-  private transient ParseMode parseMode;
-  private transient boolean parseNoExponent;
-  private transient boolean parseToBigDecimal;
-  private transient PluralRules pluralRules;
-  private transient String positivePrefix;
-  private transient String positivePrefixPattern;
-  private transient String positiveSuffix;
-  private transient String positiveSuffixPattern;
-  private transient BigDecimal roundingIncrement;
-  private transient RoundingMode roundingMode;
-  private transient int secondaryGroupingSize;
-  private transient boolean signAlwaysShown;
-
-  /*--------------------------------------------------------------------------------------------+/
-  /| IMPORTANT!                                                                                 |/
-  /| WHEN ADDING A NEW PROPERTY, add it here, in #_clear(), in #_copyFrom(), in #equals(),      |/
-  /| and in #_hashCode().                                                                       |/
-  /|                                                                                            |/
-  /| The unit test PropertiesTest will catch if you forget to add it to #clear(), #copyFrom(),  |/
-  /| or #equals(), but it will NOT catch if you forget to add it to #hashCode().                |/
-  /+--------------------------------------------------------------------------------------------*/
-
-  public DecimalFormatProperties() {
-    clear();
-  }
-
-  /**
-   * Sets all properties to their defaults (unset).
-   *
-   * <p>All integers default to -1 EXCEPT FOR MAGNITUDE MULTIPLIER which has a default of 0 (since
-   * negative numbers are important).
-   *
-   * <p>All booleans default to false.
-   *
-   * <p>All non-primitive types default to null.
-   *
-   * @return The property bag, for chaining.
-   */
-  private DecimalFormatProperties _clear() {
-    compactCustomData = null;
-    compactStyle = null;
-    currency = null;
-    currencyPluralInfo = null;
-    currencyUsage = null;
-    decimalPatternMatchRequired = false;
-    decimalSeparatorAlwaysShown = false;
-    exponentSignAlwaysShown = false;
-    formatWidth = -1;
-    groupingSize = -1;
-    magnitudeMultiplier = 0;
-    mathContext = null;
-    maximumFractionDigits = -1;
-    maximumIntegerDigits = -1;
-    maximumSignificantDigits = -1;
-    minimumExponentDigits = -1;
-    minimumFractionDigits = -1;
-    minimumGroupingDigits = -1;
-    minimumIntegerDigits = -1;
-    minimumSignificantDigits = -1;
-    multiplier = null;
-    negativePrefix = null;
-    negativePrefixPattern = null;
-    negativeSuffix = null;
-    negativeSuffixPattern = null;
-    padPosition = null;
-    padString = null;
-    parseCaseSensitive = false;
-    parseGroupingMode = null;
-    parseIntegerOnly = false;
-    parseMode = null;
-    parseNoExponent = false;
-    parseToBigDecimal = false;
-    pluralRules = null;
-    positivePrefix = null;
-    positivePrefixPattern = null;
-    positiveSuffix = null;
-    positiveSuffixPattern = null;
-    roundingIncrement = null;
-    roundingMode = null;
-    secondaryGroupingSize = -1;
-    signAlwaysShown = false;
-    return this;
-  }
-
-  private DecimalFormatProperties _copyFrom(DecimalFormatProperties other) {
-    compactCustomData = other.compactCustomData;
-    compactStyle = other.compactStyle;
-    currency = other.currency;
-    currencyPluralInfo = other.currencyPluralInfo;
-    currencyUsage = other.currencyUsage;
-    decimalPatternMatchRequired = other.decimalPatternMatchRequired;
-    decimalSeparatorAlwaysShown = other.decimalSeparatorAlwaysShown;
-    exponentSignAlwaysShown = other.exponentSignAlwaysShown;
-    formatWidth = other.formatWidth;
-    groupingSize = other.groupingSize;
-    magnitudeMultiplier = other.magnitudeMultiplier;
-    mathContext = other.mathContext;
-    maximumFractionDigits = other.maximumFractionDigits;
-    maximumIntegerDigits = other.maximumIntegerDigits;
-    maximumSignificantDigits = other.maximumSignificantDigits;
-    minimumExponentDigits = other.minimumExponentDigits;
-    minimumFractionDigits = other.minimumFractionDigits;
-    minimumGroupingDigits = other.minimumGroupingDigits;
-    minimumIntegerDigits = other.minimumIntegerDigits;
-    minimumSignificantDigits = other.minimumSignificantDigits;
-    multiplier = other.multiplier;
-    negativePrefix = other.negativePrefix;
-    negativePrefixPattern = other.negativePrefixPattern;
-    negativeSuffix = other.negativeSuffix;
-    negativeSuffixPattern = other.negativeSuffixPattern;
-    padPosition = other.padPosition;
-    padString = other.padString;
-    parseCaseSensitive = other.parseCaseSensitive;
-    parseGroupingMode = other.parseGroupingMode;
-    parseIntegerOnly = other.parseIntegerOnly;
-    parseMode = other.parseMode;
-    parseNoExponent = other.parseNoExponent;
-    parseToBigDecimal = other.parseToBigDecimal;
-    pluralRules = other.pluralRules;
-    positivePrefix = other.positivePrefix;
-    positivePrefixPattern = other.positivePrefixPattern;
-    positiveSuffix = other.positiveSuffix;
-    positiveSuffixPattern = other.positiveSuffixPattern;
-    roundingIncrement = other.roundingIncrement;
-    roundingMode = other.roundingMode;
-    secondaryGroupingSize = other.secondaryGroupingSize;
-    signAlwaysShown = other.signAlwaysShown;
-    return this;
-  }
-
-  private boolean _equals(DecimalFormatProperties other) {
-    boolean eq = true;
-    eq = eq && _equalsHelper(compactCustomData, other.compactCustomData);
-    eq = eq && _equalsHelper(compactStyle, other.compactStyle);
-    eq = eq && _equalsHelper(currency, other.currency);
-    eq = eq && _equalsHelper(currencyPluralInfo, other.currencyPluralInfo);
-    eq = eq && _equalsHelper(currencyUsage, other.currencyUsage);
-    eq = eq && _equalsHelper(decimalPatternMatchRequired, other.decimalPatternMatchRequired);
-    eq = eq && _equalsHelper(decimalSeparatorAlwaysShown, other.decimalSeparatorAlwaysShown);
-    eq = eq && _equalsHelper(exponentSignAlwaysShown, other.exponentSignAlwaysShown);
-    eq = eq && _equalsHelper(formatWidth, other.formatWidth);
-    eq = eq && _equalsHelper(groupingSize, other.groupingSize);
-    eq = eq && _equalsHelper(magnitudeMultiplier, other.magnitudeMultiplier);
-    eq = eq && _equalsHelper(mathContext, other.mathContext);
-    eq = eq && _equalsHelper(maximumFractionDigits, other.maximumFractionDigits);
-    eq = eq && _equalsHelper(maximumIntegerDigits, other.maximumIntegerDigits);
-    eq = eq && _equalsHelper(maximumSignificantDigits, other.maximumSignificantDigits);
-    eq = eq && _equalsHelper(minimumExponentDigits, other.minimumExponentDigits);
-    eq = eq && _equalsHelper(minimumFractionDigits, other.minimumFractionDigits);
-    eq = eq && _equalsHelper(minimumGroupingDigits, other.minimumGroupingDigits);
-    eq = eq && _equalsHelper(minimumIntegerDigits, other.minimumIntegerDigits);
-    eq = eq && _equalsHelper(minimumSignificantDigits, other.minimumSignificantDigits);
-    eq = eq && _equalsHelper(multiplier, other.multiplier);
-    eq = eq && _equalsHelper(negativePrefix, other.negativePrefix);
-    eq = eq && _equalsHelper(negativePrefixPattern, other.negativePrefixPattern);
-    eq = eq && _equalsHelper(negativeSuffix, other.negativeSuffix);
-    eq = eq && _equalsHelper(negativeSuffixPattern, other.negativeSuffixPattern);
-    eq = eq && _equalsHelper(padPosition, other.padPosition);
-    eq = eq && _equalsHelper(padString, other.padString);
-    eq = eq && _equalsHelper(parseCaseSensitive, other.parseCaseSensitive);
-    eq = eq && _equalsHelper(parseGroupingMode, other.parseGroupingMode);
-    eq = eq && _equalsHelper(parseIntegerOnly, other.parseIntegerOnly);
-    eq = eq && _equalsHelper(parseMode, other.parseMode);
-    eq = eq && _equalsHelper(parseNoExponent, other.parseNoExponent);
-    eq = eq && _equalsHelper(parseToBigDecimal, other.parseToBigDecimal);
-    eq = eq && _equalsHelper(pluralRules, other.pluralRules);
-    eq = eq && _equalsHelper(positivePrefix, other.positivePrefix);
-    eq = eq && _equalsHelper(positivePrefixPattern, other.positivePrefixPattern);
-    eq = eq && _equalsHelper(positiveSuffix, other.positiveSuffix);
-    eq = eq && _equalsHelper(positiveSuffixPattern, other.positiveSuffixPattern);
-    eq = eq && _equalsHelper(roundingIncrement, other.roundingIncrement);
-    eq = eq && _equalsHelper(roundingMode, other.roundingMode);
-    eq = eq && _equalsHelper(secondaryGroupingSize, other.secondaryGroupingSize);
-    eq = eq && _equalsHelper(signAlwaysShown, other.signAlwaysShown);
-    return eq;
-  }
-
-  private boolean _equalsHelper(boolean mine, boolean theirs) {
-    return mine == theirs;
-  }
-
-  private boolean _equalsHelper(int mine, int theirs) {
-    return mine == theirs;
-  }
-
-  private boolean _equalsHelper(Object mine, Object theirs) {
-    if (mine == theirs) return true;
-    if (mine == null) return false;
-    return mine.equals(theirs);
-  }
-
-  private int _hashCode() {
-    int hashCode = 0;
-    hashCode ^= _hashCodeHelper(compactCustomData);
-    hashCode ^= _hashCodeHelper(compactStyle);
-    hashCode ^= _hashCodeHelper(currency);
-    hashCode ^= _hashCodeHelper(currencyPluralInfo);
-    hashCode ^= _hashCodeHelper(currencyUsage);
-    hashCode ^= _hashCodeHelper(decimalPatternMatchRequired);
-    hashCode ^= _hashCodeHelper(decimalSeparatorAlwaysShown);
-    hashCode ^= _hashCodeHelper(exponentSignAlwaysShown);
-    hashCode ^= _hashCodeHelper(formatWidth);
-    hashCode ^= _hashCodeHelper(groupingSize);
-    hashCode ^= _hashCodeHelper(magnitudeMultiplier);
-    hashCode ^= _hashCodeHelper(mathContext);
-    hashCode ^= _hashCodeHelper(maximumFractionDigits);
-    hashCode ^= _hashCodeHelper(maximumIntegerDigits);
-    hashCode ^= _hashCodeHelper(maximumSignificantDigits);
-    hashCode ^= _hashCodeHelper(minimumExponentDigits);
-    hashCode ^= _hashCodeHelper(minimumFractionDigits);
-    hashCode ^= _hashCodeHelper(minimumGroupingDigits);
-    hashCode ^= _hashCodeHelper(minimumIntegerDigits);
-    hashCode ^= _hashCodeHelper(minimumSignificantDigits);
-    hashCode ^= _hashCodeHelper(multiplier);
-    hashCode ^= _hashCodeHelper(negativePrefix);
-    hashCode ^= _hashCodeHelper(negativePrefixPattern);
-    hashCode ^= _hashCodeHelper(negativeSuffix);
-    hashCode ^= _hashCodeHelper(negativeSuffixPattern);
-    hashCode ^= _hashCodeHelper(padPosition);
-    hashCode ^= _hashCodeHelper(padString);
-    hashCode ^= _hashCodeHelper(parseCaseSensitive);
-    hashCode ^= _hashCodeHelper(parseGroupingMode);
-    hashCode ^= _hashCodeHelper(parseIntegerOnly);
-    hashCode ^= _hashCodeHelper(parseMode);
-    hashCode ^= _hashCodeHelper(parseNoExponent);
-    hashCode ^= _hashCodeHelper(parseToBigDecimal);
-    hashCode ^= _hashCodeHelper(pluralRules);
-    hashCode ^= _hashCodeHelper(positivePrefix);
-    hashCode ^= _hashCodeHelper(positivePrefixPattern);
-    hashCode ^= _hashCodeHelper(positiveSuffix);
-    hashCode ^= _hashCodeHelper(positiveSuffixPattern);
-    hashCode ^= _hashCodeHelper(roundingIncrement);
-    hashCode ^= _hashCodeHelper(roundingMode);
-    hashCode ^= _hashCodeHelper(secondaryGroupingSize);
-    hashCode ^= _hashCodeHelper(signAlwaysShown);
-    return hashCode;
-  }
-
-  private int _hashCodeHelper(boolean value) {
-    return value ? 1 : 0;
-  }
-
-  private int _hashCodeHelper(int value) {
-    return value * 13;
-  }
-
-  private int _hashCodeHelper(Object value) {
-    if (value == null) return 0;
-    return value.hashCode();
-  }
-
-  public DecimalFormatProperties clear() {
-    return _clear();
-  }
-
-  /** Creates and returns a shallow copy of the property bag. */
-  @Override
-  public DecimalFormatProperties clone() {
-    // super.clone() returns a shallow copy.
-    try {
-      return (DecimalFormatProperties) super.clone();
-    } catch (CloneNotSupportedException e) {
-      // Should never happen since super is Object
-      throw new UnsupportedOperationException(e);
-    }
-  }
-
-  /**
-   * Shallow-copies the properties from the given property bag into this property bag.
-   *
-   * @param other The property bag from which to copy and which will not be modified.
-   * @return The current property bag (the one modified by this operation), for chaining.
-   */
-  public DecimalFormatProperties copyFrom(DecimalFormatProperties other) {
-    return _copyFrom(other);
-  }
-
-  @Override
-  public boolean equals(Object other) {
-    if (other == null) return false;
-    if (this == other) return true;
-    if (!(other instanceof DecimalFormatProperties)) return false;
-    return _equals((DecimalFormatProperties) other);
-  }
-
-  /// BEGIN GETTERS/SETTERS ///
-
-  public Map<String, Map<String, String>> getCompactCustomData() {
-    return compactCustomData;
-  }
-
-  public CompactStyle getCompactStyle() {
-    return compactStyle;
-  }
-
-  public Currency getCurrency() {
-    return currency;
-  }
-
-  public CurrencyPluralInfo getCurrencyPluralInfo() {
-    return currencyPluralInfo;
-  }
-
-  public CurrencyUsage getCurrencyUsage() {
-    return currencyUsage;
-  }
-
-  public boolean getDecimalPatternMatchRequired() {
-    return decimalPatternMatchRequired;
-  }
-
-  public boolean getDecimalSeparatorAlwaysShown() {
-    return decimalSeparatorAlwaysShown;
-  }
-
-  public boolean getExponentSignAlwaysShown() {
-    return exponentSignAlwaysShown;
-  }
-
-  public int getFormatWidth() {
-    return formatWidth;
-  }
-
-  public int getGroupingSize() {
-    return groupingSize;
-  }
-
-  public int getMagnitudeMultiplier() {
-    return magnitudeMultiplier;
-  }
-
-  public MathContext getMathContext() {
-    return mathContext;
-  }
-
-  public int getMaximumFractionDigits() {
-    return maximumFractionDigits;
-  }
-
-  public int getMaximumIntegerDigits() {
-    return maximumIntegerDigits;
-  }
-
-  public int getMaximumSignificantDigits() {
-    return maximumSignificantDigits;
-  }
-
-  public int getMinimumExponentDigits() {
-    return minimumExponentDigits;
-  }
-
-  public int getMinimumFractionDigits() {
-    return minimumFractionDigits;
-  }
-
-  public int getMinimumGroupingDigits() {
-    return minimumGroupingDigits;
-  }
-
-  public int getMinimumIntegerDigits() {
-    return minimumIntegerDigits;
-  }
-
-  public int getMinimumSignificantDigits() {
-    return minimumSignificantDigits;
-  }
-
-  public BigDecimal getMultiplier() {
-    return multiplier;
-  }
-
-  public String getNegativePrefix() {
-    return negativePrefix;
-  }
+    private static final DecimalFormatProperties DEFAULT = new DecimalFormatProperties();
+
+    /** Auto-generated. */
+    private static final long serialVersionUID = 4095518955889349243L;
+
+    // The setters in this class should NOT have any side-effects or perform any validation. It is
+    // up to the consumer of the property bag to deal with property validation.
+
+    // The fields are all marked "transient" because custom serialization is being used.
+
+    /*--------------------------------------------------------------------------------------------+/
+    /| IMPORTANT!                                                                                 |/
+    /| WHEN ADDING A NEW PROPERTY, add it here, in #_clear(), in #_copyFrom(), in #equals(),      |/
+    /| and in #_hashCode().                                                                       |/
+    /|                                                                                            |/
+    /| The unit test PropertiesTest will catch if you forget to add it to #clear(), #copyFrom(),  |/
+    /| or #equals(), but it will NOT catch if you forget to add it to #hashCode().                |/
+    /+--------------------------------------------------------------------------------------------*/
+
+    private transient Map<String, Map<String, String>> compactCustomData;
+    private transient CompactStyle compactStyle;
+    private transient Currency currency;
+    private transient CurrencyPluralInfo currencyPluralInfo;
+    private transient CurrencyUsage currencyUsage;
+    private transient boolean decimalPatternMatchRequired;
+    private transient boolean decimalSeparatorAlwaysShown;
+    private transient boolean exponentSignAlwaysShown;
+    private transient int formatWidth;
+    private transient int groupingSize;
+    private transient int magnitudeMultiplier;
+    private transient MathContext mathContext;
+    private transient int maximumFractionDigits;
+    private transient int maximumIntegerDigits;
+    private transient int maximumSignificantDigits;
+    private transient int minimumExponentDigits;
+    private transient int minimumFractionDigits;
+    private transient int minimumGroupingDigits;
+    private transient int minimumIntegerDigits;
+    private transient int minimumSignificantDigits;
+    private transient BigDecimal multiplier;
+    private transient String negativePrefix;
+    private transient String negativePrefixPattern;
+    private transient String negativeSuffix;
+    private transient String negativeSuffixPattern;
+    private transient PadPosition padPosition;
+    private transient String padString;
+    private transient boolean parseCaseSensitive;
+    private transient GroupingMode parseGroupingMode;
+    private transient boolean parseIntegerOnly;
+    private transient ParseMode parseMode;
+    private transient boolean parseNoExponent;
+    private transient boolean parseToBigDecimal;
+    private transient PluralRules pluralRules;
+    private transient String positivePrefix;
+    private transient String positivePrefixPattern;
+    private transient String positiveSuffix;
+    private transient String positiveSuffixPattern;
+    private transient BigDecimal roundingIncrement;
+    private transient RoundingMode roundingMode;
+    private transient int secondaryGroupingSize;
+    private transient boolean signAlwaysShown;
+
+    /*--------------------------------------------------------------------------------------------+/
+    /| IMPORTANT!                                                                                 |/
+    /| WHEN ADDING A NEW PROPERTY, add it here, in #_clear(), in #_copyFrom(), in #equals(),      |/
+    /| and in #_hashCode().                                                                       |/
+    /|                                                                                            |/
+    /| The unit test PropertiesTest will catch if you forget to add it to #clear(), #copyFrom(),  |/
+    /| or #equals(), but it will NOT catch if you forget to add it to #hashCode().                |/
+    /+--------------------------------------------------------------------------------------------*/
+
+    public DecimalFormatProperties() {
+        clear();
+    }
+
+    /**
+     * Sets all properties to their defaults (unset).
+     *
+     * <p>
+     * All integers default to -1 EXCEPT FOR MAGNITUDE MULTIPLIER which has a default of 0 (since negative numbers are
+     * important).
+     *
+     * <p>
+     * All booleans default to false.
+     *
+     * <p>
+     * All non-primitive types default to null.
+     *
+     * @return The property bag, for chaining.
+     */
+    private DecimalFormatProperties _clear() {
+        compactCustomData = null;
+        compactStyle = null;
+        currency = null;
+        currencyPluralInfo = null;
+        currencyUsage = null;
+        decimalPatternMatchRequired = false;
+        decimalSeparatorAlwaysShown = false;
+        exponentSignAlwaysShown = false;
+        formatWidth = -1;
+        groupingSize = -1;
+        magnitudeMultiplier = 0;
+        mathContext = null;
+        maximumFractionDigits = -1;
+        maximumIntegerDigits = -1;
+        maximumSignificantDigits = -1;
+        minimumExponentDigits = -1;
+        minimumFractionDigits = -1;
+        minimumGroupingDigits = -1;
+        minimumIntegerDigits = -1;
+        minimumSignificantDigits = -1;
+        multiplier = null;
+        negativePrefix = null;
+        negativePrefixPattern = null;
+        negativeSuffix = null;
+        negativeSuffixPattern = null;
+        padPosition = null;
+        padString = null;
+        parseCaseSensitive = false;
+        parseGroupingMode = null;
+        parseIntegerOnly = false;
+        parseMode = null;
+        parseNoExponent = false;
+        parseToBigDecimal = false;
+        pluralRules = null;
+        positivePrefix = null;
+        positivePrefixPattern = null;
+        positiveSuffix = null;
+        positiveSuffixPattern = null;
+        roundingIncrement = null;
+        roundingMode = null;
+        secondaryGroupingSize = -1;
+        signAlwaysShown = false;
+        return this;
+    }
+
+    private DecimalFormatProperties _copyFrom(DecimalFormatProperties other) {
+        compactCustomData = other.compactCustomData;
+        compactStyle = other.compactStyle;
+        currency = other.currency;
+        currencyPluralInfo = other.currencyPluralInfo;
+        currencyUsage = other.currencyUsage;
+        decimalPatternMatchRequired = other.decimalPatternMatchRequired;
+        decimalSeparatorAlwaysShown = other.decimalSeparatorAlwaysShown;
+        exponentSignAlwaysShown = other.exponentSignAlwaysShown;
+        formatWidth = other.formatWidth;
+        groupingSize = other.groupingSize;
+        magnitudeMultiplier = other.magnitudeMultiplier;
+        mathContext = other.mathContext;
+        maximumFractionDigits = other.maximumFractionDigits;
+        maximumIntegerDigits = other.maximumIntegerDigits;
+        maximumSignificantDigits = other.maximumSignificantDigits;
+        minimumExponentDigits = other.minimumExponentDigits;
+        minimumFractionDigits = other.minimumFractionDigits;
+        minimumGroupingDigits = other.minimumGroupingDigits;
+        minimumIntegerDigits = other.minimumIntegerDigits;
+        minimumSignificantDigits = other.minimumSignificantDigits;
+        multiplier = other.multiplier;
+        negativePrefix = other.negativePrefix;
+        negativePrefixPattern = other.negativePrefixPattern;
+        negativeSuffix = other.negativeSuffix;
+        negativeSuffixPattern = other.negativeSuffixPattern;
+        padPosition = other.padPosition;
+        padString = other.padString;
+        parseCaseSensitive = other.parseCaseSensitive;
+        parseGroupingMode = other.parseGroupingMode;
+        parseIntegerOnly = other.parseIntegerOnly;
+        parseMode = other.parseMode;
+        parseNoExponent = other.parseNoExponent;
+        parseToBigDecimal = other.parseToBigDecimal;
+        pluralRules = other.pluralRules;
+        positivePrefix = other.positivePrefix;
+        positivePrefixPattern = other.positivePrefixPattern;
+        positiveSuffix = other.positiveSuffix;
+        positiveSuffixPattern = other.positiveSuffixPattern;
+        roundingIncrement = other.roundingIncrement;
+        roundingMode = other.roundingMode;
+        secondaryGroupingSize = other.secondaryGroupingSize;
+        signAlwaysShown = other.signAlwaysShown;
+        return this;
+    }
+
+    private boolean _equals(DecimalFormatProperties other) {
+        boolean eq = true;
+        eq = eq && _equalsHelper(compactCustomData, other.compactCustomData);
+        eq = eq && _equalsHelper(compactStyle, other.compactStyle);
+        eq = eq && _equalsHelper(currency, other.currency);
+        eq = eq && _equalsHelper(currencyPluralInfo, other.currencyPluralInfo);
+        eq = eq && _equalsHelper(currencyUsage, other.currencyUsage);
+        eq = eq && _equalsHelper(decimalPatternMatchRequired, other.decimalPatternMatchRequired);
+        eq = eq && _equalsHelper(decimalSeparatorAlwaysShown, other.decimalSeparatorAlwaysShown);
+        eq = eq && _equalsHelper(exponentSignAlwaysShown, other.exponentSignAlwaysShown);
+        eq = eq && _equalsHelper(formatWidth, other.formatWidth);
+        eq = eq && _equalsHelper(groupingSize, other.groupingSize);
+        eq = eq && _equalsHelper(magnitudeMultiplier, other.magnitudeMultiplier);
+        eq = eq && _equalsHelper(mathContext, other.mathContext);
+        eq = eq && _equalsHelper(maximumFractionDigits, other.maximumFractionDigits);
+        eq = eq && _equalsHelper(maximumIntegerDigits, other.maximumIntegerDigits);
+        eq = eq && _equalsHelper(maximumSignificantDigits, other.maximumSignificantDigits);
+        eq = eq && _equalsHelper(minimumExponentDigits, other.minimumExponentDigits);
+        eq = eq && _equalsHelper(minimumFractionDigits, other.minimumFractionDigits);
+        eq = eq && _equalsHelper(minimumGroupingDigits, other.minimumGroupingDigits);
+        eq = eq && _equalsHelper(minimumIntegerDigits, other.minimumIntegerDigits);
+        eq = eq && _equalsHelper(minimumSignificantDigits, other.minimumSignificantDigits);
+        eq = eq && _equalsHelper(multiplier, other.multiplier);
+        eq = eq && _equalsHelper(negativePrefix, other.negativePrefix);
+        eq = eq && _equalsHelper(negativePrefixPattern, other.negativePrefixPattern);
+        eq = eq && _equalsHelper(negativeSuffix, other.negativeSuffix);
+        eq = eq && _equalsHelper(negativeSuffixPattern, other.negativeSuffixPattern);
+        eq = eq && _equalsHelper(padPosition, other.padPosition);
+        eq = eq && _equalsHelper(padString, other.padString);
+        eq = eq && _equalsHelper(parseCaseSensitive, other.parseCaseSensitive);
+        eq = eq && _equalsHelper(parseGroupingMode, other.parseGroupingMode);
+        eq = eq && _equalsHelper(parseIntegerOnly, other.parseIntegerOnly);
+        eq = eq && _equalsHelper(parseMode, other.parseMode);
+        eq = eq && _equalsHelper(parseNoExponent, other.parseNoExponent);
+        eq = eq && _equalsHelper(parseToBigDecimal, other.parseToBigDecimal);
+        eq = eq && _equalsHelper(pluralRules, other.pluralRules);
+        eq = eq && _equalsHelper(positivePrefix, other.positivePrefix);
+        eq = eq && _equalsHelper(positivePrefixPattern, other.positivePrefixPattern);
+        eq = eq && _equalsHelper(positiveSuffix, other.positiveSuffix);
+        eq = eq && _equalsHelper(positiveSuffixPattern, other.positiveSuffixPattern);
+        eq = eq && _equalsHelper(roundingIncrement, other.roundingIncrement);
+        eq = eq && _equalsHelper(roundingMode, other.roundingMode);
+        eq = eq && _equalsHelper(secondaryGroupingSize, other.secondaryGroupingSize);
+        eq = eq && _equalsHelper(signAlwaysShown, other.signAlwaysShown);
+        return eq;
+    }
+
+    private boolean _equalsHelper(boolean mine, boolean theirs) {
+        return mine == theirs;
+    }
+
+    private boolean _equalsHelper(int mine, int theirs) {
+        return mine == theirs;
+    }
+
+    private boolean _equalsHelper(Object mine, Object theirs) {
+        if (mine == theirs)
+            return true;
+        if (mine == null)
+            return false;
+        return mine.equals(theirs);
+    }
+
+    private int _hashCode() {
+        int hashCode = 0;
+        hashCode ^= _hashCodeHelper(compactCustomData);
+        hashCode ^= _hashCodeHelper(compactStyle);
+        hashCode ^= _hashCodeHelper(currency);
+        hashCode ^= _hashCodeHelper(currencyPluralInfo);
+        hashCode ^= _hashCodeHelper(currencyUsage);
+        hashCode ^= _hashCodeHelper(decimalPatternMatchRequired);
+        hashCode ^= _hashCodeHelper(decimalSeparatorAlwaysShown);
+        hashCode ^= _hashCodeHelper(exponentSignAlwaysShown);
+        hashCode ^= _hashCodeHelper(formatWidth);
+        hashCode ^= _hashCodeHelper(groupingSize);
+        hashCode ^= _hashCodeHelper(magnitudeMultiplier);
+        hashCode ^= _hashCodeHelper(mathContext);
+        hashCode ^= _hashCodeHelper(maximumFractionDigits);
+        hashCode ^= _hashCodeHelper(maximumIntegerDigits);
+        hashCode ^= _hashCodeHelper(maximumSignificantDigits);
+        hashCode ^= _hashCodeHelper(minimumExponentDigits);
+        hashCode ^= _hashCodeHelper(minimumFractionDigits);
+        hashCode ^= _hashCodeHelper(minimumGroupingDigits);
+        hashCode ^= _hashCodeHelper(minimumIntegerDigits);
+        hashCode ^= _hashCodeHelper(minimumSignificantDigits);
+        hashCode ^= _hashCodeHelper(multiplier);
+        hashCode ^= _hashCodeHelper(negativePrefix);
+        hashCode ^= _hashCodeHelper(negativePrefixPattern);
+        hashCode ^= _hashCodeHelper(negativeSuffix);
+        hashCode ^= _hashCodeHelper(negativeSuffixPattern);
+        hashCode ^= _hashCodeHelper(padPosition);
+        hashCode ^= _hashCodeHelper(padString);
+        hashCode ^= _hashCodeHelper(parseCaseSensitive);
+        hashCode ^= _hashCodeHelper(parseGroupingMode);
+        hashCode ^= _hashCodeHelper(parseIntegerOnly);
+        hashCode ^= _hashCodeHelper(parseMode);
+        hashCode ^= _hashCodeHelper(parseNoExponent);
+        hashCode ^= _hashCodeHelper(parseToBigDecimal);
+        hashCode ^= _hashCodeHelper(pluralRules);
+        hashCode ^= _hashCodeHelper(positivePrefix);
+        hashCode ^= _hashCodeHelper(positivePrefixPattern);
+        hashCode ^= _hashCodeHelper(positiveSuffix);
+        hashCode ^= _hashCodeHelper(positiveSuffixPattern);
+        hashCode ^= _hashCodeHelper(roundingIncrement);
+        hashCode ^= _hashCodeHelper(roundingMode);
+        hashCode ^= _hashCodeHelper(secondaryGroupingSize);
+        hashCode ^= _hashCodeHelper(signAlwaysShown);
+        return hashCode;
+    }
+
+    private int _hashCodeHelper(boolean value) {
+        return value ? 1 : 0;
+    }
+
+    private int _hashCodeHelper(int value) {
+        return value * 13;
+    }
+
+    private int _hashCodeHelper(Object value) {
+        if (value == null)
+            return 0;
+        return value.hashCode();
+    }
+
+    public DecimalFormatProperties clear() {
+        return _clear();
+    }
+
+    /** Creates and returns a shallow copy of the property bag. */
+    @Override
+    public DecimalFormatProperties clone() {
+        // super.clone() returns a shallow copy.
+        try {
+            return (DecimalFormatProperties) super.clone();
+        } catch (CloneNotSupportedException e) {
+            // Should never happen since super is Object
+            throw new UnsupportedOperationException(e);
+        }
+    }
+
+    /**
+     * Shallow-copies the properties from the given property bag into this property bag.
+     *
+     * @param other
+     *            The property bag from which to copy and which will not be modified.
+     * @return The current property bag (the one modified by this operation), for chaining.
+     */
+    public DecimalFormatProperties copyFrom(DecimalFormatProperties other) {
+        return _copyFrom(other);
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (other == null)
+            return false;
+        if (this == other)
+            return true;
+        if (!(other instanceof DecimalFormatProperties))
+            return false;
+        return _equals((DecimalFormatProperties) other);
+    }
+
+    /// BEGIN GETTERS/SETTERS ///
+
+    public Map<String, Map<String, String>> getCompactCustomData() {
+        return compactCustomData;
+    }
+
+    public CompactStyle getCompactStyle() {
+        return compactStyle;
+    }
+
+    public Currency getCurrency() {
+        return currency;
+    }
+
+    public CurrencyPluralInfo getCurrencyPluralInfo() {
+        return currencyPluralInfo;
+    }
+
+    public CurrencyUsage getCurrencyUsage() {
+        return currencyUsage;
+    }
+
+    public boolean getDecimalPatternMatchRequired() {
+        return decimalPatternMatchRequired;
+    }
+
+    public boolean getDecimalSeparatorAlwaysShown() {
+        return decimalSeparatorAlwaysShown;
+    }
+
+    public boolean getExponentSignAlwaysShown() {
+        return exponentSignAlwaysShown;
+    }
+
+    public int getFormatWidth() {
+        return formatWidth;
+    }
+
+    public int getGroupingSize() {
+        return groupingSize;
+    }
+
+    public int getMagnitudeMultiplier() {
+        return magnitudeMultiplier;
+    }
+
+    public MathContext getMathContext() {
+        return mathContext;
+    }
+
+    public int getMaximumFractionDigits() {
+        return maximumFractionDigits;
+    }
+
+    public int getMaximumIntegerDigits() {
+        return maximumIntegerDigits;
+    }
+
+    public int getMaximumSignificantDigits() {
+        return maximumSignificantDigits;
+    }
+
+    public int getMinimumExponentDigits() {
+        return minimumExponentDigits;
+    }
+
+    public int getMinimumFractionDigits() {
+        return minimumFractionDigits;
+    }
+
+    public int getMinimumGroupingDigits() {
+        return minimumGroupingDigits;
+    }
+
+    public int getMinimumIntegerDigits() {
+        return minimumIntegerDigits;
+    }
+
+    public int getMinimumSignificantDigits() {
+        return minimumSignificantDigits;
+    }
+
+    public BigDecimal getMultiplier() {
+        return multiplier;
+    }
+
+    public String getNegativePrefix() {
+        return negativePrefix;
+    }
+
+    public String getNegativePrefixPattern() {
+        return negativePrefixPattern;
+    }
+
+    public String getNegativeSuffix() {
+        return negativeSuffix;
+    }
+
+    public String getNegativeSuffixPattern() {
+        return negativeSuffixPattern;
+    }
+
+    public PadPosition getPadPosition() {
+        return padPosition;
+    }
+
+    public String getPadString() {
+        return padString;
+    }
+
+    public boolean getParseCaseSensitive() {
+        return parseCaseSensitive;
+    }
+
+    public GroupingMode getParseGroupingMode() {
+        return parseGroupingMode;
+    }
+
+    public boolean getParseIntegerOnly() {
+        return parseIntegerOnly;
+    }
+
+    public ParseMode getParseMode() {
+        return parseMode;
+    }
+
+    public boolean getParseNoExponent() {
+        return parseNoExponent;
+    }
+
+    public boolean getParseToBigDecimal() {
+        return parseToBigDecimal;
+    }
+
+    public PluralRules getPluralRules() {
+        return pluralRules;
+    }
+
+    public String getPositivePrefix() {
+        return positivePrefix;
+    }
+
+    public String getPositivePrefixPattern() {
+        return positivePrefixPattern;
+    }
+
+    public String getPositiveSuffix() {
+        return positiveSuffix;
+    }
+
+    public String getPositiveSuffixPattern() {
+        return positiveSuffixPattern;
+    }
 
-  public String getNegativePrefixPattern() {
-    return negativePrefixPattern;
-  }
+    public BigDecimal getRoundingIncrement() {
+        return roundingIncrement;
+    }
+
+    public RoundingMode getRoundingMode() {
+        return roundingMode;
+    }
+
+    public int getSecondaryGroupingSize() {
+        return secondaryGroupingSize;
+    }
+
+    public boolean getSignAlwaysShown() {
+        return signAlwaysShown;
+    }
 
-  public String getNegativeSuffix() {
-    return negativeSuffix;
-  }
+    @Override
+    public int hashCode() {
+        return _hashCode();
+    }
 
-  public String getNegativeSuffixPattern() {
-    return negativeSuffixPattern;
-  }
+    /** Custom serialization: re-create object from serialized properties. */
+    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
+        readObjectImpl(ois);
+    }
 
-  public PadPosition getPadPosition() {
-    return padPosition;
-  }
-
-  public String getPadString() {
-    return padString;
-  }
-
-  public boolean getParseCaseSensitive() {
-    return parseCaseSensitive;
-  }
-
-  public GroupingMode getParseGroupingMode() {
-    return parseGroupingMode;
-  }
-
-  public boolean getParseIntegerOnly() {
-    return parseIntegerOnly;
-  }
-
-  public ParseMode getParseMode() {
-    return parseMode;
-  }
-
-  public boolean getParseNoExponent() {
-    return parseNoExponent;
-  }
-
-  public boolean getParseToBigDecimal() {
-    return parseToBigDecimal;
-  }
-
-  public PluralRules getPluralRules() {
-    return pluralRules;
-  }
-
-  public String getPositivePrefix() {
-    return positivePrefix;
-  }
-
-  public String getPositivePrefixPattern() {
-    return positivePrefixPattern;
-  }
-
-  public String getPositiveSuffix() {
-    return positiveSuffix;
-  }
-
-  public String getPositiveSuffixPattern() {
-    return positiveSuffixPattern;
-  }
-
-  public BigDecimal getRoundingIncrement() {
-    return roundingIncrement;
-  }
-
-  public RoundingMode getRoundingMode() {
-    return roundingMode;
-  }
-
-  public int getSecondaryGroupingSize() {
-    return secondaryGroupingSize;
-  }
-
-  public boolean getSignAlwaysShown() {
-    return signAlwaysShown;
-  }
-
-  @Override
-  public int hashCode() {
-    return _hashCode();
-  }
-
-  /** Custom serialization: re-create object from serialized properties. */
-  private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
-    readObjectImpl(ois);
-  }
-
-  /* package-private */ void readObjectImpl(ObjectInputStream ois) throws IOException, ClassNotFoundException {
-    ois.defaultReadObject();
-
-    // Initialize to empty
-    clear();
-
-    // Extra int for possible future use
-    ois.readInt();
-
-    // 1) How many fields were serialized?
-    int count = ois.readInt();
-
-    // 2) Read each field by its name and value
-    for (int i = 0; i < count; i++) {
-      String name = (String) ois.readObject();
-      Object value = ois.readObject();
-
-      // Get the field reference
-      Field field = null;
-      try {
-        field = DecimalFormatProperties.class.getDeclaredField(name);
-      } catch (NoSuchFieldException e) {
-        // The field name does not exist! Possibly corrupted serialization. Ignore this entry.
-        continue;
-      } catch (SecurityException e) {
-        // Should not happen
-        throw new AssertionError(e);
-      }
-
-      // NOTE: If the type of a field were changed in the future, this would be the place to check:
-      // If the variable `value` is the old type, perform any conversions necessary.
-
-      // Save value into the field
-      try {
-        field.set(this, value);
-      } catch (IllegalArgumentException e) {
-        // Should not happen
-        throw new AssertionError(e);
-      } catch (IllegalAccessException e) {
-        // Should not happen
-        throw new AssertionError(e);
-      }
-    }
-  }
-
-  /**
-   * Specifies custom data to be used instead of CLDR data when constructing a CompactDecimalFormat.
-   * The argument should be a map with the following structure:
-   *
-   * <pre>
-   * {
-   *   "1000": {
-   *     "one": "0 thousand",
-   *     "other": "0 thousand"
-   *   },
-   *   "10000": {
-   *     "one": "00 thousand",
-   *     "other": "00 thousand"
-   *   },
-   *   // ...
-   * }
-   * </pre>
-   *
-   * This API endpoint is used by the CLDR Survey Tool.
-   *
-   * @param compactCustomData A map with the above structure.
-   * @return The property bag, for chaining.
-   */
-  public DecimalFormatProperties setCompactCustomData(Map<String, Map<String, String>> compactCustomData) {
-    // TODO: compactCustomData is not immutable.
-    this.compactCustomData = compactCustomData;
-    return this;
-  }
-
-  /**
-   * Use compact decimal formatting with the specified {@link CompactStyle}. CompactStyle.SHORT
-   * produces output like "10K" in locale <em>en-US</em>, whereas CompactStyle.LONG produces output
-   * like "10 thousand" in that locale.
-   *
-   * @param compactStyle The style of prefixes/suffixes to append.
-   * @return The property bag, for chaining.
-   */
-  public DecimalFormatProperties setCompactStyle(CompactStyle compactStyle) {
-    this.compactStyle = compactStyle;
-    return this;
-  }
-
-  /**
-   * Use the specified currency to substitute currency placeholders ('¤') in the pattern string.
-   *
-   * @param currency The currency.
-   * @return The property bag, for chaining.
-   */
-  public DecimalFormatProperties setCurrency(Currency currency) {
-    this.currency = currency;
-    return this;
-  }
-
-  /**
-   * Use the specified {@link CurrencyPluralInfo} instance when formatting currency long names.
-   *
-   * @param currencyPluralInfo The currency plural info object.
-   * @return The property bag, for chaining.
-   */
-  public DecimalFormatProperties setCurrencyPluralInfo(CurrencyPluralInfo currencyPluralInfo) {
-    // TODO: In order to maintain immutability, we have to perform a clone here.
-    // It would be better to just retire CurrencyPluralInfo entirely.
-    if (currencyPluralInfo != null) {
-      currencyPluralInfo = (CurrencyPluralInfo) currencyPluralInfo.clone();
-    }
-    this.currencyPluralInfo = currencyPluralInfo;
-    return this;
-  }
-
-  /**
-   * Use the specified {@link CurrencyUsage} instance, which provides default rounding rules for the
-   * currency in two styles, CurrencyUsage.CASH and CurrencyUsage.STANDARD.
-   *
-   * <p>The CurrencyUsage specified here will not be used unless there is a currency placeholder in
-   * the pattern.
-   *
-   * @param currencyUsage The currency usage. Defaults to CurrencyUsage.STANDARD.
-   * @return The property bag, for chaining.
-   */
-  public DecimalFormatProperties setCurrencyUsage(CurrencyUsage currencyUsage) {
-    this.currencyUsage = currencyUsage;
-    return this;
-  }
-
-  /**
-   * PARSING: Whether to require that the presence of decimal point matches the pattern. If a
-   * decimal point is not present, but the pattern contained a decimal point, parse will not
-   * succeed: null will be returned from <code>parse()</code>, and an error index will be set in the
-   * {@link ParsePosition}.
-   *
-   * @param decimalPatternMatchRequired true to set an error if decimal is not present
-   * @return The property bag, for chaining.
-   */
-  public DecimalFormatProperties setDecimalPatternMatchRequired(boolean decimalPatternMatchRequired) {
-    this.decimalPatternMatchRequired = decimalPatternMatchRequired;
-    return this;
-  }
-
-  /**
-   * Sets whether to always show the decimal point, even if the number doesn't require one. For
-   * example, if always show decimal is true, the number 123 would be formatted as "123." in locale
-   * <em>en-US</em>.
-   *
-   * @param decimalSeparatorAlwaysShown Whether to show the decimal point when it is optional.
-   * @return The property bag, for chaining.
-   */
-  public DecimalFormatProperties setDecimalSeparatorAlwaysShown(boolean alwaysShowDecimal) {
-    this.decimalSeparatorAlwaysShown = alwaysShowDecimal;
-    return this;
-  }
-
-  /**
-   * Sets whether to show the plus sign in the exponent part of numbers with a zero or positive
-   * exponent. For example, the number "1200" with the pattern "0.0E0" would be formatted as
-   * "1.2E+3" instead of "1.2E3" in <em>en-US</em>.
-   *
-   * @param exponentSignAlwaysShown Whether to show the plus sign in positive exponents.
-   * @return The property bag, for chaining.
-   */
-  public DecimalFormatProperties setExponentSignAlwaysShown(boolean exponentSignAlwaysShown) {
-    this.exponentSignAlwaysShown = exponentSignAlwaysShown;
-    return this;
-  }
-
-  /**
-   * 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>Width is counted in UTF-16 code units.
-   *
-   * @param formatWidth The output width.
-   * @return The property bag, for chaining.
-   * @see #setPadPosition
-   * @see #setPadString
-   */
-  public DecimalFormatProperties setFormatWidth(int paddingWidth) {
-    this.formatWidth = paddingWidth;
-    return this;
-  }
-
-  /**
-   * Sets the number of digits between grouping separators. For example, the <em>en-US</em> locale
-   * uses a grouping size of 3, so the number 1234567 would be formatted as "1,234,567". For locales
-   * whose grouping sizes vary with magnitude, see {@link #setSecondaryGroupingSize(int)}.
-   *
-   * @param groupingSize The primary grouping size.
-   * @return The property bag, for chaining.
-   */
-  public DecimalFormatProperties setGroupingSize(int groupingSize) {
-    this.groupingSize = groupingSize;
-    return this;
-  }
-
-  /**
-   * Multiply all numbers by this power of ten before formatting. Negative multipliers reduce the
-   * magnitude and make numbers smaller (closer to zero).
-   *
-   * @param magnitudeMultiplier The number of powers of ten to scale.
-   * @return The property bag, for chaining.
-   * @see #setMultiplier
-   */
-  public DecimalFormatProperties setMagnitudeMultiplier(int magnitudeMultiplier) {
-    this.magnitudeMultiplier = magnitudeMultiplier;
-    return this;
-  }
-
-  /**
-   * Sets the {@link MathContext} to be used during math and rounding operations. A MathContext
-   * encapsulates a RoundingMode and the number of significant digits in the output.
-   *
-   * @param mathContext The math context to use when rounding is required.
-   * @return The property bag, for chaining.
-   * @see MathContext
-   * @see #setRoundingMode
-   */
-  public DecimalFormatProperties setMathContext(MathContext mathContext) {
-    this.mathContext = mathContext;
-    return this;
-  }
-
-  /**
-   * Sets the maximum number of digits to display after the decimal point. If the number has fewer
-   * than this number of digits, the number will be rounded off using the rounding mode specified by
-   * {@link #setRoundingMode(RoundingMode)}. The pattern "#00.0#", for example, corresponds to 2
-   * maximum fraction digits, and the number 456.789 would be formatted as "456.79" in locale
-   * <em>en-US</em> with the default rounding mode. Note that the number 456.999 would be formatted
-   * as "457.0" given the same configurations.
-   *
-   * @param maximumFractionDigits The maximum number of fraction digits to output.
-   * @return The property bag, for chaining.
-   */
-  public DecimalFormatProperties setMaximumFractionDigits(int maximumFractionDigits) {
-    this.maximumFractionDigits = maximumFractionDigits;
-    return this;
-  }
-
-  /**
-   * Sets the maximum number of digits to display before the decimal point. If the number has more
-   * than this number of digits, the extra digits will be truncated. For example, if maximum integer
-   * digits is 2, and you attempt to format the number 1970, you will get "70" in locale
-   * <em>en-US</em>. It is not possible to specify the maximum integer digits using a pattern
-   * string, except in the special case of a scientific format pattern.
-   *
-   * @param maximumIntegerDigits The maximum number of integer digits to output.
-   * @return The property bag, for chaining.
-   */
-  public DecimalFormatProperties setMaximumIntegerDigits(int maximumIntegerDigits) {
-    this.maximumIntegerDigits = maximumIntegerDigits;
-    return this;
-  }
-
-  /**
-   * Sets the maximum number of significant digits to display. The number of significant digits is
-   * equal to the number of digits counted from the leftmost nonzero digit through the rightmost
-   * nonzero digit; for example, the number "2010" has 3 significant digits. If the number has more
-   * significant digits than specified here, the extra significant digits will be rounded off using
-   * the rounding mode specified by {@link #setRoundingMode(RoundingMode)}. For example, if maximum
-   * significant digits is 3, the number 1234.56 will be formatted as "1230" in locale
-   * <em>en-US</em> with the default rounding mode.
-   *
-   * <p>If both maximum significant digits and maximum integer/fraction digits are set at the same
-   * time, the behavior is undefined.
-   *
-   * <p>The number of significant digits can be specified in a pattern string using the '@'
-   * character. For example, the pattern "@@#" corresponds to a minimum of 2 and a maximum of 3
-   * significant digits.
-   *
-   * @param maximumSignificantDigits The maximum number of significant digits to display.
-   * @return The property bag, for chaining.
-   */
-  public DecimalFormatProperties setMaximumSignificantDigits(int maximumSignificantDigits) {
-    this.maximumSignificantDigits = maximumSignificantDigits;
-    return this;
-  }
-
-  /**
-   * Sets the minimum number of digits to display in the exponent. For example, the number "1200"
-   * with the pattern "0.0E00", which has 2 exponent digits, would be formatted as "1.2E03" in
-   * <em>en-US</em>.
-   *
-   * @param minimumExponentDigits The minimum number of digits to display in the exponent field.
-   * @return The property bag, for chaining.
-   */
-  public DecimalFormatProperties setMinimumExponentDigits(int exponentDigits) {
-    this.minimumExponentDigits = exponentDigits;
-    return this;
-  }
-
-  /**
-   * Sets the minimum number of digits to display after the decimal point. If the number has fewer
-   * than this number of digits, the number will be padded with zeros. The pattern "#00.0#", for
-   * example, corresponds to 1 minimum fraction digit, and the number 456 would be formatted as
-   * "456.0" in locale <em>en-US</em>.
-   *
-   * @param minimumFractionDigits The minimum number of fraction digits to output.
-   * @return The property bag, for chaining.
-   */
-  public DecimalFormatProperties setMinimumFractionDigits(int minimumFractionDigits) {
-    this.minimumFractionDigits = minimumFractionDigits;
-    return this;
-  }
-
-  /**
-   * Sets the minimum number of digits required to be beyond the first grouping separator in order
-   * to enable grouping. For example, if the minimum grouping digits is 2, then 1234 would be
-   * formatted as "1234" but 12345 would be formatted as "12,345" in <em>en-US</em>. Note that
-   * 1234567 would still be formatted as "1,234,567", not "1234,567".
-   *
-   * @param minimumGroupingDigits How many digits must appear before a grouping separator before
-   *     enabling grouping.
-   * @return The property bag, for chaining.
-   */
-  public DecimalFormatProperties setMinimumGroupingDigits(int minimumGroupingDigits) {
-    this.minimumGroupingDigits = minimumGroupingDigits;
-    return this;
-  }
-
-  /**
-   * Sets the minimum number of digits to display before the decimal point. If the number has fewer
-   * than this number of digits, the number will be padded with zeros. The pattern "#00.0#", for
-   * example, corresponds to 2 minimum integer digits, and the number 5.3 would be formatted as
-   * "05.3" in locale <em>en-US</em>.
-   *
-   * @param minimumIntegerDigits The minimum number of integer digits to output.
-   * @return The property bag, for chaining.
-   */
-  public DecimalFormatProperties setMinimumIntegerDigits(int minimumIntegerDigits) {
-    this.minimumIntegerDigits = minimumIntegerDigits;
-    return this;
-  }
-
-  /**
-   * Sets the minimum number of significant digits to display. If, after rounding to the number of
-   * significant digits specified by {@link #setMaximumSignificantDigits}, the number of remaining
-   * significant digits is less than the minimum, the number will be padded with zeros. For example,
-   * if minimum significant digits is 3, the number 5.8 will be formatted as "5.80" in locale
-   * <em>en-US</em>. Note that minimum significant digits is relevant only when numbers have digits
-   * after the decimal point.
-   *
-   * <p>If both minimum significant digits and minimum integer/fraction digits are set at the same
-   * time, both values will be respected, and the one that results in the greater number of padding
-   * zeros will be used. For example, formatting the number 73 with 3 minimum significant digits and
-   * 2 minimum fraction digits will produce "73.00".
-   *
-   * <p>The number of significant digits can be specified in a pattern string using the '@'
-   * character. For example, the pattern "@@#" corresponds to a minimum of 2 and a maximum of 3
-   * significant digits.
-   *
-   * @param minimumSignificantDigits The minimum number of significant digits to display.
-   * @return The property bag, for chaining.
-   */
-  public DecimalFormatProperties setMinimumSignificantDigits(int minimumSignificantDigits) {
-    this.minimumSignificantDigits = minimumSignificantDigits;
-    return this;
-  }
-
-  /**
-   * Multiply all numbers by this amount before formatting.
-   *
-   * @param multiplier The amount to multiply by.
-   * @return The property bag, for chaining.
-   * @see #setMagnitudeMultiplier
-   */
-  public DecimalFormatProperties setMultiplier(BigDecimal multiplier) {
-    this.multiplier = multiplier;
-    return this;
-  }
-
-  /**
-   * Sets the prefix to prepend to negative numbers. The prefix will be interpreted literally. For
-   * example, if you set a negative prefix of <code>n</code>, then the number -123 will be formatted
-   * as "n123" in the locale <em>en-US</em>. Note that if the negative prefix is left unset, the
-   * locale's minus sign is used.
-   *
-   * <p>For more information on prefixes and suffixes, see {@link PositiveNegativeAffixFormat}.
-   *
-   * @param negativePrefix The CharSequence to prepend to negative numbers.
-   * @return The property bag, for chaining.
-   * @see PositiveNegativeAffixFormat
-   * @see #setNegativePrefixPattern
-   */
-  public DecimalFormatProperties setNegativePrefix(String negativePrefix) {
-    this.negativePrefix = negativePrefix;
-    return this;
-  }
-
-  /**
-   * Sets the prefix to prepend to negative numbers. Locale-specific symbols will be substituted
-   * into the string according to Unicode Technical Standard #35 (LDML).
-   *
-   * <p>For more information on prefixes and suffixes, see {@link PositiveNegativeAffixFormat}.
-   *
-   * @param negativePrefixPattern The CharSequence to prepend to negative numbers after locale
-   *     symbol substitutions take place.
-   * @return The property bag, for chaining.
-   * @see PositiveNegativeAffixFormat
-   * @see #setNegativePrefix
-   */
-  public DecimalFormatProperties setNegativePrefixPattern(String negativePrefixPattern) {
-    this.negativePrefixPattern = negativePrefixPattern;
-    return this;
-  }
-
-  /**
-   * Sets the suffix to append to negative numbers. The suffix will be interpreted literally. For
-   * example, if you set a suffix prefix of <code>n</code>, then the number -123 will be formatted
-   * as "-123n" in the locale <em>en-US</em>. Note that the minus sign is prepended by default
-   * unless otherwise specified in either the pattern string or in one of the {@link
-   * #setNegativePrefix} methods.
-   *
-   * <p>For more information on prefixes and suffixes, see {@link PositiveNegativeAffixFormat}.
-   *
-   * @param negativeSuffix The CharSequence to append to negative numbers.
-   * @return The property bag, for chaining.
-   * @see PositiveNegativeAffixFormat
-   * @see #setNegativeSuffixPattern
-   */
-  public DecimalFormatProperties setNegativeSuffix(String negativeSuffix) {
-    this.negativeSuffix = negativeSuffix;
-    return this;
-  }
-
-  /**
-   * Sets the suffix to append to negative numbers. Locale-specific symbols will be substituted into
-   * the string according to Unicode Technical Standard #35 (LDML).
-   *
-   * <p>For more information on prefixes and suffixes, see {@link PositiveNegativeAffixFormat}.
-   *
-   * @param negativeSuffixPattern The CharSequence to append to negative numbers after locale symbol
-   *     substitutions take place.
-   * @return The property bag, for chaining.
-   * @see PositiveNegativeAffixFormat
-   * @see #setNegativeSuffix
-   */
-  public DecimalFormatProperties setNegativeSuffixPattern(String negativeSuffixPattern) {
-    this.negativeSuffixPattern = negativeSuffixPattern;
-    return this;
-  }
-
-  /**
-   * Sets the location where the padding string is to be inserted to maintain the padding width: one
-   * of BEFORE_PREFIX, AFTER_PREFIX, BEFORE_SUFFIX, or AFTER_SUFFIX.
-   *
-   * <p>Must be used in conjunction with {@link #setFormatWidth}.
-   *
-   * @param padPosition The output width.
-   * @return The property bag, for chaining.
-   * @see #setFormatWidth
-   */
-  public DecimalFormatProperties setPadPosition(PadPosition paddingLocation) {
-    this.padPosition = paddingLocation;
-    return this;
-  }
-
-  /**
-   * Sets the string used for padding. The string should contain a single character or grapheme
-   * cluster.
-   *
-   * <p>Must be used in conjunction with {@link #setFormatWidth}.
-   *
-   * @param paddingString The padding string. Defaults to an ASCII space (U+0020).
-   * @return The property bag, for chaining.
-   * @see #setFormatWidth
-   */
-  public DecimalFormatProperties setPadString(String paddingString) {
-    this.padString = paddingString;
-    return this;
-  }
-
-  /**
-   * Whether to require cases to match when parsing strings; default is true. Case sensitivity
-   * applies to prefixes, suffixes, the exponent separator, the symbol "NaN", and the infinity
-   * symbol. Grouping separators, decimal separators, and padding are always case-sensitive.
-   * Currencies are always case-insensitive.
-   *
-   * <p>This setting is ignored in fast mode. In fast mode, strings are always compared in a
-   * case-sensitive way.
-   *
-   * @param parseCaseSensitive true to be case-sensitive when parsing; false to allow any case.
-   * @return The property bag, for chaining.
-   */
-  public DecimalFormatProperties setParseCaseSensitive(boolean parseCaseSensitive) {
-    this.parseCaseSensitive = parseCaseSensitive;
-    return this;
-  }
-
-  /**
-   * 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.
-   *
-   * <p>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).
-   *
-   * <p>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 parseGroupingMode The {@link GroupingMode} to use; either DEFAULT or RESTRICTED.
-   * @return The property bag, for chaining.
-   */
-  public DecimalFormatProperties setParseGroupingMode(GroupingMode parseGroupingMode) {
-    this.parseGroupingMode = parseGroupingMode;
-    return this;
-  }
-
-  /**
-   * Whether to ignore the fractional part of numbers. For example, parses "123.4" to "123" instead
-   * of "123.4".
-   *
-   * @param parseIntegerOnly true to parse integers only; false to parse integers with their
-   *     fraction parts
-   * @return The property bag, for chaining.
-   */
-  public DecimalFormatProperties setParseIntegerOnly(boolean parseIntegerOnly) {
-    this.parseIntegerOnly = parseIntegerOnly;
-    return this;
-  }
-
-  /**
-   * Controls certain rules for how strict this parser is when reading strings. See {@link
-   * ParseMode#LENIENT} and {@link ParseMode#STRICT}.
-   *
-   * @param parseMode Either {@link ParseMode#LENIENT} or {@link ParseMode#STRICT}.
-   * @return The property bag, for chaining.
-   */
-  public DecimalFormatProperties setParseMode(ParseMode parseMode) {
-    this.parseMode = parseMode;
-    return this;
-  }
-
-  /**
-   * Whether to ignore the exponential part of numbers. For example, parses "123E4" to "123" instead
-   * of "1230000".
-   *
-   * @param parseIgnoreExponent true to ignore exponents; false to parse them.
-   * @return The property bag, for chaining.
-   */
-  public DecimalFormatProperties setParseNoExponent(boolean parseNoExponent) {
-    this.parseNoExponent = parseNoExponent;
-    return this;
-  }
-
-  /**
-   * Whether to always return a BigDecimal from {@link Parse#parse} and all other parse methods. By
-   * default, a Long or a BigInteger are returned when possible.
-   *
-   * @param parseToBigDecimal true to always return a BigDecimal; false to return a Long or a
-   *     BigInteger when possible.
-   * @return The property bag, for chaining.
-   */
-  public DecimalFormatProperties setParseToBigDecimal(boolean parseToBigDecimal) {
-    this.parseToBigDecimal = parseToBigDecimal;
-    return this;
-  }
-
-  /**
-   * Sets the PluralRules object to use instead of the default for the locale.
-   *
-   * @param pluralRules The object to reference.
-   * @return The property bag, for chaining.
-   */
-  public DecimalFormatProperties setPluralRules(PluralRules pluralRules) {
-    this.pluralRules = pluralRules;
-    return this;
-  }
-
-  /**
-   * Sets the prefix to prepend to positive numbers. The prefix will be interpreted literally. For
-   * example, if you set a positive prefix of <code>p</code>, then the number 123 will be formatted
-   * as "p123" in the locale <em>en-US</em>.
-   *
-   * <p>For more information on prefixes and suffixes, see {@link PositiveNegativeAffixFormat}.
-   *
-   * @param positivePrefix The CharSequence to prepend to positive numbers.
-   * @return The property bag, for chaining.
-   * @see PositiveNegativeAffixFormat
-   * @see #setPositivePrefixPattern
-   */
-  public DecimalFormatProperties setPositivePrefix(String positivePrefix) {
-    this.positivePrefix = positivePrefix;
-    return this;
-  }
-
-  /**
-   * Sets the prefix to prepend to positive numbers. Locale-specific symbols will be substituted
-   * into the string according to Unicode Technical Standard #35 (LDML).
-   *
-   * <p>For more information on prefixes and suffixes, see {@link PositiveNegativeAffixFormat}.
-   *
-   * @param positivePrefixPattern The CharSequence to prepend to positive numbers after locale
-   *     symbol substitutions take place.
-   * @return The property bag, for chaining.
-   * @see PositiveNegativeAffixFormat
-   * @see #setPositivePrefix
-   */
-  public DecimalFormatProperties setPositivePrefixPattern(String positivePrefixPattern) {
-    this.positivePrefixPattern = positivePrefixPattern;
-    return this;
-  }
-
-  /**
-   * Sets the suffix to append to positive numbers. The suffix will be interpreted literally. For
-   * example, if you set a positive suffix of <code>p</code>, then the number 123 will be formatted
-   * as "123p" in the locale <em>en-US</em>.
-   *
-   * <p>For more information on prefixes and suffixes, see {@link PositiveNegativeAffixFormat}.
-   *
-   * @param positiveSuffix The CharSequence to append to positive numbers.
-   * @return The property bag, for chaining.
-   * @see PositiveNegativeAffixFormat
-   * @see #setPositiveSuffixPattern
-   */
-  public DecimalFormatProperties setPositiveSuffix(String positiveSuffix) {
-    this.positiveSuffix = positiveSuffix;
-    return this;
-  }
-
-  /**
-   * Sets the suffix to append to positive numbers. Locale-specific symbols will be substituted into
-   * the string according to Unicode Technical Standard #35 (LDML).
-   *
-   * <p>For more information on prefixes and suffixes, see {@link PositiveNegativeAffixFormat}.
-   *
-   * @param positiveSuffixPattern The CharSequence to append to positive numbers after locale symbol
-   *     substitutions take place.
-   * @return The property bag, for chaining.
-   * @see PositiveNegativeAffixFormat
-   * @see #setPositiveSuffix
-   */
-  public DecimalFormatProperties setPositiveSuffixPattern(String positiveSuffixPattern) {
-    this.positiveSuffixPattern = positiveSuffixPattern;
-    return this;
-  }
-
-  /**
-   * Sets the increment to which to round numbers. For example, with a rounding interval of 0.05,
-   * the number 11.17 would be formatted as "11.15" in locale <em>en-US</em> with the default
-   * rounding mode.
-   *
-   * <p>You can use either a rounding increment or significant digits, but not both at the same
-   * time.
-   *
-   * <p>The rounding increment can be specified in a pattern string. For example, the pattern
-   * "#,##0.05" corresponds to a rounding interval of 0.05 with 1 minimum integer digit and a
-   * grouping size of 3.
-   *
-   * @param roundingIncrement The interval to which to round.
-   * @return The property bag, for chaining.
-   */
-  public DecimalFormatProperties setRoundingIncrement(BigDecimal roundingIncrement) {
-    this.roundingIncrement = roundingIncrement;
-    return this;
-  }
-
-  /**
-   * Sets the rounding mode, which determines under which conditions extra decimal places are
-   * rounded either up or down. See {@link RoundingMode} for details on the choices of rounding
-   * mode. The default if not set explicitly is {@link RoundingMode#HALF_EVEN}.
-   *
-   * <p>This setting is ignored if {@link #setMathContext} is used.
-   *
-   * @param roundingMode The rounding mode to use when rounding is required.
-   * @return The property bag, for chaining.
-   * @see RoundingMode
-   * @see #setMathContext
-   */
-  public DecimalFormatProperties setRoundingMode(RoundingMode roundingMode) {
-    this.roundingMode = roundingMode;
-    return this;
-  }
-
-  /**
-   * Sets the number of digits between grouping separators higher than the least-significant
-   * grouping separator. For example, the locale <em>hi</em> uses a primary grouping size of 3 and a
-   * secondary grouping size of 2, so the number 1234567 would be formatted as "12,34,567".
-   *
-   * <p>The two levels of grouping separators can be specified in the pattern string. For example,
-   * the <em>hi</em> locale's default decimal format pattern is "#,##,##0.###".
-   *
-   * @param secondaryGroupingSize The secondary grouping size.
-   * @return The property bag, for chaining.
-   */
-  public DecimalFormatProperties setSecondaryGroupingSize(int secondaryGroupingSize) {
-    this.secondaryGroupingSize = secondaryGroupingSize;
-    return this;
-  }
-
-  /**
-   * Sets whether to always display of a plus sign on positive numbers.
-   *
-   * <p>If the location of the negative sign is specified by the decimal format pattern (or by the
-   * negative prefix/suffix pattern methods), a plus sign is substituted into that location, in
-   * accordance with Unicode Technical Standard #35 (LDML) section 3.2.1. Otherwise, the plus sign
-   * is prepended to the number. For example, if the decimal format pattern <code>#;#-</code> is
-   * used, then formatting 123 would result in "123+" in the locale <em>en-US</em>.
-   *
-   * <p>This method should be used <em>instead of</em> setting the positive prefix/suffix. The
-   * behavior is undefined if alwaysShowPlusSign is set but the positive prefix/suffix already
-   * contains a plus sign.
-   *
-   * @param plusSignAlwaysShown Whether positive numbers should display a plus sign.
-   * @return The property bag, for chaining.
-   */
-  public DecimalFormatProperties setSignAlwaysShown(boolean signAlwaysShown) {
-    this.signAlwaysShown = signAlwaysShown;
-    return this;
-  }
-
-  @Override
-  public String toString() {
-    StringBuilder result = new StringBuilder();
-    result.append("<Properties");
-    toStringBare(result);
-    result.append(">");
-    return result.toString();
-  }
-
-  /**
-   * Appends a string containing properties that differ from the default, but without being
-   * surrounded by &lt;Properties&gt;.
-   */
-  public void toStringBare(StringBuilder result) {
-    Field[] fields = DecimalFormatProperties.class.getDeclaredFields();
-    for (Field field : fields) {
-      Object myValue, defaultValue;
-      try {
-        myValue = field.get(this);
-        defaultValue = field.get(DEFAULT);
-      } catch (IllegalArgumentException e) {
-        e.printStackTrace();
-        continue;
-      } catch (IllegalAccessException e) {
-        e.printStackTrace();
-        continue;
-      }
-      if (myValue == null && defaultValue == null) {
-        continue;
-      } else if (myValue == null || defaultValue == null) {
-        result.append(" " + field.getName() + ":" + myValue);
-      } else if (!myValue.equals(defaultValue)) {
-        result.append(" " + field.getName() + ":" + myValue);
-      }
-    }
-  }
-
-  /**
-   * Custom serialization: save fields along with their name, so that fields can be easily added in
-   * the future in any order. Only save fields that differ from their default value.
-   */
-  private void writeObject(ObjectOutputStream oos) throws IOException {
-    writeObjectImpl(oos);
-  }
-
-  /* package-private */ void writeObjectImpl(ObjectOutputStream oos) throws IOException {
-    oos.defaultWriteObject();
-
-    // Extra int for possible future use
-    oos.writeInt(0);
-
-    ArrayList<Field> fieldsToSerialize = new ArrayList<Field>();
-    ArrayList<Object> valuesToSerialize = new ArrayList<Object>();
-    Field[] fields = DecimalFormatProperties.class.getDeclaredFields();
-    for (Field field : fields) {
-      if (Modifier.isStatic(field.getModifiers())) {
-        continue;
-      }
-      try {
-        Object myValue = field.get(this);
-        if (myValue == null) {
-          // All *Object* values default to null; no need to serialize.
-          continue;
+    /* package-private */ void readObjectImpl(ObjectInputStream ois) throws IOException, ClassNotFoundException {
+        ois.defaultReadObject();
+
+        // Initialize to empty
+        clear();
+
+        // Extra int for possible future use
+        ois.readInt();
+
+        // 1) How many fields were serialized?
+        int count = ois.readInt();
+
+        // 2) Read each field by its name and value
+        for (int i = 0; i < count; i++) {
+            String name = (String) ois.readObject();
+            Object value = ois.readObject();
+
+            // Get the field reference
+            Field field = null;
+            try {
+                field = DecimalFormatProperties.class.getDeclaredField(name);
+            } catch (NoSuchFieldException e) {
+                // The field name does not exist! Possibly corrupted serialization. Ignore this entry.
+                continue;
+            } catch (SecurityException e) {
+                // Should not happen
+                throw new AssertionError(e);
+            }
+
+            // NOTE: If the type of a field were changed in the future, this would be the place to check:
+            // If the variable `value` is the old type, perform any conversions necessary.
+
+            // Save value into the field
+            try {
+                field.set(this, value);
+            } catch (IllegalArgumentException e) {
+                // Should not happen
+                throw new AssertionError(e);
+            } catch (IllegalAccessException e) {
+                // Should not happen
+                throw new AssertionError(e);
+            }
         }
-        Object defaultValue = field.get(DEFAULT);
-        if (!myValue.equals(defaultValue)) {
-          fieldsToSerialize.add(field);
-          valuesToSerialize.add(myValue);
+    }
+
+    /**
+     * Specifies custom data to be used instead of CLDR data when constructing a CompactDecimalFormat. The argument
+     * should be a map with the following structure:
+     *
+     * <pre>
+     * {
+     *   "1000": {
+     *     "one": "0 thousand",
+     *     "other": "0 thousand"
+     *   },
+     *   "10000": {
+     *     "one": "00 thousand",
+     *     "other": "00 thousand"
+     *   },
+     *   // ...
+     * }
+     * </pre>
+     *
+     * This API endpoint is used by the CLDR Survey Tool.
+     *
+     * @param compactCustomData
+     *            A map with the above structure.
+     * @return The property bag, for chaining.
+     */
+    public DecimalFormatProperties setCompactCustomData(Map<String, Map<String, String>> compactCustomData) {
+        // TODO: compactCustomData is not immutable.
+        this.compactCustomData = compactCustomData;
+        return this;
+    }
+
+    /**
+     * Use compact decimal formatting with the specified {@link CompactStyle}. CompactStyle.SHORT produces output like
+     * "10K" in locale <em>en-US</em>, whereas CompactStyle.LONG produces output like "10 thousand" in that locale.
+     *
+     * @param compactStyle
+     *            The style of prefixes/suffixes to append.
+     * @return The property bag, for chaining.
+     */
+    public DecimalFormatProperties setCompactStyle(CompactStyle compactStyle) {
+        this.compactStyle = compactStyle;
+        return this;
+    }
+
+    /**
+     * Use the specified currency to substitute currency placeholders ('¤') in the pattern string.
+     *
+     * @param currency
+     *            The currency.
+     * @return The property bag, for chaining.
+     */
+    public DecimalFormatProperties setCurrency(Currency currency) {
+        this.currency = currency;
+        return this;
+    }
+
+    /**
+     * Use the specified {@link CurrencyPluralInfo} instance when formatting currency long names.
+     *
+     * @param currencyPluralInfo
+     *            The currency plural info object.
+     * @return The property bag, for chaining.
+     */
+    public DecimalFormatProperties setCurrencyPluralInfo(CurrencyPluralInfo currencyPluralInfo) {
+        // TODO: In order to maintain immutability, we have to perform a clone here.
+        // It would be better to just retire CurrencyPluralInfo entirely.
+        if (currencyPluralInfo != null) {
+            currencyPluralInfo = (CurrencyPluralInfo) currencyPluralInfo.clone();
         }
-      } catch (IllegalArgumentException e) {
-        // Should not happen
-        throw new AssertionError(e);
-      } catch (IllegalAccessException e) {
-        // Should not happen
-        throw new AssertionError(e);
-      }
-    }
-
-    // 1) How many fields are to be serialized?
-    int count = fieldsToSerialize.size();
-    oos.writeInt(count);
-
-    // 2) Write each field with its name and value
-    for (int i = 0; i < count; i++) {
-      Field field = fieldsToSerialize.get(i);
-      Object value = valuesToSerialize.get(i);
-      oos.writeObject(field.getName());
-      oos.writeObject(value);
-    }
-  }
+        this.currencyPluralInfo = currencyPluralInfo;
+        return this;
+    }
+
+    /**
+     * Use the specified {@link CurrencyUsage} instance, which provides default rounding rules for the currency in two
+     * styles, CurrencyUsage.CASH and CurrencyUsage.STANDARD.
+     *
+     * <p>
+     * The CurrencyUsage specified here will not be used unless there is a currency placeholder in the pattern.
+     *
+     * @param currencyUsage
+     *            The currency usage. Defaults to CurrencyUsage.STANDARD.
+     * @return The property bag, for chaining.
+     */
+    public DecimalFormatProperties setCurrencyUsage(CurrencyUsage currencyUsage) {
+        this.currencyUsage = currencyUsage;
+        return this;
+    }
+
+    /**
+     * PARSING: Whether to require that the presence of decimal point matches the pattern. If a decimal point is not
+     * present, but the pattern contained a decimal point, parse will not succeed: null will be returned from
+     * <code>parse()</code>, and an error index will be set in the {@link ParsePosition}.
+     *
+     * @param decimalPatternMatchRequired
+     *            true to set an error if decimal is not present
+     * @return The property bag, for chaining.
+     */
+    public DecimalFormatProperties setDecimalPatternMatchRequired(boolean decimalPatternMatchRequired) {
+        this.decimalPatternMatchRequired = decimalPatternMatchRequired;
+        return this;
+    }
+
+    /**
+     * Sets whether to always show the decimal point, even if the number doesn't require one. For example, if always
+     * show decimal is true, the number 123 would be formatted as "123." in locale <em>en-US</em>.
+     *
+     * @param alwaysShowDecimal
+     *            Whether to show the decimal point when it is optional.
+     * @return The property bag, for chaining.
+     */
+    public DecimalFormatProperties setDecimalSeparatorAlwaysShown(boolean alwaysShowDecimal) {
+        this.decimalSeparatorAlwaysShown = alwaysShowDecimal;
+        return this;
+    }
+
+    /**
+     * Sets whether to show the plus sign in the exponent part of numbers with a zero or positive exponent. For example,
+     * the number "1200" with the pattern "0.0E0" would be formatted as "1.2E+3" instead of "1.2E3" in <em>en-US</em>.
+     *
+     * @param exponentSignAlwaysShown
+     *            Whether to show the plus sign in positive exponents.
+     * @return The property bag, for chaining.
+     */
+    public DecimalFormatProperties setExponentSignAlwaysShown(boolean exponentSignAlwaysShown) {
+        this.exponentSignAlwaysShown = exponentSignAlwaysShown;
+        return this;
+    }
+
+    /**
+     * 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>
+     * Width is counted in UTF-16 code units.
+     *
+     * @param paddingWidth
+     *            The output width.
+     * @return The property bag, for chaining.
+     * @see #setPadPosition
+     * @see #setPadString
+     */
+    public DecimalFormatProperties setFormatWidth(int paddingWidth) {
+        this.formatWidth = paddingWidth;
+        return this;
+    }
+
+    /**
+     * Sets the number of digits between grouping separators. For example, the <em>en-US</em> locale uses a grouping
+     * size of 3, so the number 1234567 would be formatted as "1,234,567". For locales whose grouping sizes vary with
+     * magnitude, see {@link #setSecondaryGroupingSize(int)}.
+     *
+     * @param groupingSize
+     *            The primary grouping size.
+     * @return The property bag, for chaining.
+     */
+    public DecimalFormatProperties setGroupingSize(int groupingSize) {
+        this.groupingSize = groupingSize;
+        return this;
+    }
+
+    /**
+     * Multiply all numbers by this power of ten before formatting. Negative multipliers reduce the magnitude and make
+     * numbers smaller (closer to zero).
+     *
+     * @param magnitudeMultiplier
+     *            The number of powers of ten to scale.
+     * @return The property bag, for chaining.
+     * @see #setMultiplier
+     */
+    public DecimalFormatProperties setMagnitudeMultiplier(int magnitudeMultiplier) {
+        this.magnitudeMultiplier = magnitudeMultiplier;
+        return this;
+    }
+
+    /**
+     * Sets the {@link MathContext} to be used during math and rounding operations. A MathContext encapsulates a
+     * RoundingMode and the number of significant digits in the output.
+     *
+     * @param mathContext
+     *            The math context to use when rounding is required.
+     * @return The property bag, for chaining.
+     * @see MathContext
+     * @see #setRoundingMode
+     */
+    public DecimalFormatProperties setMathContext(MathContext mathContext) {
+        this.mathContext = mathContext;
+        return this;
+    }
+
+    /**
+     * Sets the maximum number of digits to display after the decimal point. If the number has fewer than this number of
+     * digits, the number will be rounded off using the rounding mode specified by
+     * {@link #setRoundingMode(RoundingMode)}. The pattern "#00.0#", for example, corresponds to 2 maximum fraction
+     * digits, and the number 456.789 would be formatted as "456.79" in locale <em>en-US</em> with the default rounding
+     * mode. Note that the number 456.999 would be formatted as "457.0" given the same configurations.
+     *
+     * @param maximumFractionDigits
+     *            The maximum number of fraction digits to output.
+     * @return The property bag, for chaining.
+     */
+    public DecimalFormatProperties setMaximumFractionDigits(int maximumFractionDigits) {
+        this.maximumFractionDigits = maximumFractionDigits;
+        return this;
+    }
+
+    /**
+     * Sets the maximum number of digits to display before the decimal point. If the number has more than this number of
+     * digits, the extra digits will be truncated. For example, if maximum integer digits is 2, and you attempt to
+     * format the number 1970, you will get "70" in locale <em>en-US</em>. It is not possible to specify the maximum
+     * integer digits using a pattern string, except in the special case of a scientific format pattern.
+     *
+     * @param maximumIntegerDigits
+     *            The maximum number of integer digits to output.
+     * @return The property bag, for chaining.
+     */
+    public DecimalFormatProperties setMaximumIntegerDigits(int maximumIntegerDigits) {
+        this.maximumIntegerDigits = maximumIntegerDigits;
+        return this;
+    }
+
+    /**
+     * Sets the maximum number of significant digits to display. The number of significant digits is equal to the number
+     * of digits counted from the leftmost nonzero digit through the rightmost nonzero digit; for example, the number
+     * "2010" has 3 significant digits. If the number has more significant digits than specified here, the extra
+     * significant digits will be rounded off using the rounding mode specified by
+     * {@link #setRoundingMode(RoundingMode)}. For example, if maximum significant digits is 3, the number 1234.56 will
+     * be formatted as "1230" in locale <em>en-US</em> with the default rounding mode.
+     *
+     * <p>
+     * If both maximum significant digits and maximum integer/fraction digits are set at the same time, the behavior is
+     * undefined.
+     *
+     * <p>
+     * The number of significant digits can be specified in a pattern string using the '@' character. For example, the
+     * pattern "@@#" corresponds to a minimum of 2 and a maximum of 3 significant digits.
+     *
+     * @param maximumSignificantDigits
+     *            The maximum number of significant digits to display.
+     * @return The property bag, for chaining.
+     */
+    public DecimalFormatProperties setMaximumSignificantDigits(int maximumSignificantDigits) {
+        this.maximumSignificantDigits = maximumSignificantDigits;
+        return this;
+    }
+
+    /**
+     * Sets the minimum number of digits to display in the exponent. For example, the number "1200" with the pattern
+     * "0.0E00", which has 2 exponent digits, would be formatted as "1.2E03" in <em>en-US</em>.
+     *
+     * @param minimumExponentDigits
+     *            The minimum number of digits to display in the exponent field.
+     * @return The property bag, for chaining.
+     */
+    public DecimalFormatProperties setMinimumExponentDigits(int minimumExponentDigits) {
+        this.minimumExponentDigits = minimumExponentDigits;
+        return this;
+    }
+
+    /**
+     * Sets the minimum number of digits to display after the decimal point. If the number has fewer than this number of
+     * digits, the number will be padded with zeros. The pattern "#00.0#", for example, corresponds to 1 minimum
+     * fraction digit, and the number 456 would be formatted as "456.0" in locale <em>en-US</em>.
+     *
+     * @param minimumFractionDigits
+     *            The minimum number of fraction digits to output.
+     * @return The property bag, for chaining.
+     */
+    public DecimalFormatProperties setMinimumFractionDigits(int minimumFractionDigits) {
+        this.minimumFractionDigits = minimumFractionDigits;
+        return this;
+    }
+
+    /**
+     * Sets the minimum number of digits required to be beyond the first grouping separator in order to enable grouping.
+     * For example, if the minimum grouping digits is 2, then 1234 would be formatted as "1234" but 12345 would be
+     * formatted as "12,345" in <em>en-US</em>. Note that 1234567 would still be formatted as "1,234,567", not
+     * "1234,567".
+     *
+     * @param minimumGroupingDigits
+     *            How many digits must appear before a grouping separator before enabling grouping.
+     * @return The property bag, for chaining.
+     */
+    public DecimalFormatProperties setMinimumGroupingDigits(int minimumGroupingDigits) {
+        this.minimumGroupingDigits = minimumGroupingDigits;
+        return this;
+    }
+
+    /**
+     * Sets the minimum number of digits to display before the decimal point. If the number has fewer than this number
+     * of digits, the number will be padded with zeros. The pattern "#00.0#", for example, corresponds to 2 minimum
+     * integer digits, and the number 5.3 would be formatted as "05.3" in locale <em>en-US</em>.
+     *
+     * @param minimumIntegerDigits
+     *            The minimum number of integer digits to output.
+     * @return The property bag, for chaining.
+     */
+    public DecimalFormatProperties setMinimumIntegerDigits(int minimumIntegerDigits) {
+        this.minimumIntegerDigits = minimumIntegerDigits;
+        return this;
+    }
+
+    /**
+     * Sets the minimum number of significant digits to display. If, after rounding to the number of significant digits
+     * specified by {@link #setMaximumSignificantDigits}, the number of remaining significant digits is less than the
+     * minimum, the number will be padded with zeros. For example, if minimum significant digits is 3, the number 5.8
+     * will be formatted as "5.80" in locale <em>en-US</em>. Note that minimum significant digits is relevant only when
+     * numbers have digits after the decimal point.
+     *
+     * <p>
+     * If both minimum significant digits and minimum integer/fraction digits are set at the same time, both values will
+     * be respected, and the one that results in the greater number of padding zeros will be used. For example,
+     * formatting the number 73 with 3 minimum significant digits and 2 minimum fraction digits will produce "73.00".
+     *
+     * <p>
+     * The number of significant digits can be specified in a pattern string using the '@' character. For example, the
+     * pattern "@@#" corresponds to a minimum of 2 and a maximum of 3 significant digits.
+     *
+     * @param minimumSignificantDigits
+     *            The minimum number of significant digits to display.
+     * @return The property bag, for chaining.
+     */
+    public DecimalFormatProperties setMinimumSignificantDigits(int minimumSignificantDigits) {
+        this.minimumSignificantDigits = minimumSignificantDigits;
+        return this;
+    }
+
+    /**
+     * Multiply all numbers by this amount before formatting.
+     *
+     * @param multiplier
+     *            The amount to multiply by.
+     * @return The property bag, for chaining.
+     * @see #setMagnitudeMultiplier
+     */
+    public DecimalFormatProperties setMultiplier(BigDecimal multiplier) {
+        this.multiplier = multiplier;
+        return this;
+    }
+
+    /**
+     * Sets the prefix to prepend to negative numbers. The prefix will be interpreted literally. For example, if you set
+     * a negative prefix of <code>n</code>, then the number -123 will be formatted as "n123" in the locale
+     * <em>en-US</em>. Note that if the negative prefix is left unset, the locale's minus sign is used.
+     *
+     * <p>
+     * For more information on prefixes and suffixes, see {@link MutablePatternModifier}.
+     *
+     * @param negativePrefix
+     *            The CharSequence to prepend to negative numbers.
+     * @return The property bag, for chaining.
+     * @see #setNegativePrefixPattern
+     */
+    public DecimalFormatProperties setNegativePrefix(String negativePrefix) {
+        this.negativePrefix = negativePrefix;
+        return this;
+    }
+
+    /**
+     * Sets the prefix to prepend to negative numbers. Locale-specific symbols will be substituted into the string
+     * according to Unicode Technical Standard #35 (LDML).
+     *
+     * <p>
+     * For more information on prefixes and suffixes, see {@link MutablePatternModifier}.
+     *
+     * @param negativePrefixPattern
+     *            The CharSequence to prepend to negative numbers after locale symbol substitutions take place.
+     * @return The property bag, for chaining.
+     * @see #setNegativePrefix
+     */
+    public DecimalFormatProperties setNegativePrefixPattern(String negativePrefixPattern) {
+        this.negativePrefixPattern = negativePrefixPattern;
+        return this;
+    }
+
+    /**
+     * Sets the suffix to append to negative numbers. The suffix will be interpreted literally. For example, if you set
+     * a suffix prefix of <code>n</code>, then the number -123 will be formatted as "-123n" in the locale
+     * <em>en-US</em>. Note that the minus sign is prepended by default unless otherwise specified in either the pattern
+     * string or in one of the {@link #setNegativePrefix} methods.
+     *
+     * <p>
+     * For more information on prefixes and suffixes, see {@link MutablePatternModifier}.
+     *
+     * @param negativeSuffix
+     *            The CharSequence to append to negative numbers.
+     * @return The property bag, for chaining.
+     * @see #setNegativeSuffixPattern
+     */
+    public DecimalFormatProperties setNegativeSuffix(String negativeSuffix) {
+        this.negativeSuffix = negativeSuffix;
+        return this;
+    }
+
+    /**
+     * Sets the suffix to append to negative numbers. Locale-specific symbols will be substituted into the string
+     * according to Unicode Technical Standard #35 (LDML).
+     *
+     * <p>
+     * For more information on prefixes and suffixes, see {@link MutablePatternModifier}.
+     *
+     * @param negativeSuffixPattern
+     *            The CharSequence to append to negative numbers after locale symbol substitutions take place.
+     * @return The property bag, for chaining.
+     * @see #setNegativeSuffix
+     */
+    public DecimalFormatProperties setNegativeSuffixPattern(String negativeSuffixPattern) {
+        this.negativeSuffixPattern = negativeSuffixPattern;
+        return this;
+    }
+
+    /**
+     * Sets the location where the padding string is to be inserted to maintain the padding width: one of BEFORE_PREFIX,
+     * AFTER_PREFIX, BEFORE_SUFFIX, or AFTER_SUFFIX.
+     *
+     * <p>
+     * Must be used in conjunction with {@link #setFormatWidth}.
+     *
+     * @param paddingLocation
+     *            The output width.
+     * @return The property bag, for chaining.
+     * @see #setFormatWidth
+     */
+    public DecimalFormatProperties setPadPosition(PadPosition paddingLocation) {
+        this.padPosition = paddingLocation;
+        return this;
+    }
+
+    /**
+     * Sets the string used for padding. The string should contain a single character or grapheme cluster.
+     *
+     * <p>
+     * Must be used in conjunction with {@link #setFormatWidth}.
+     *
+     * @param paddingString
+     *            The padding string. Defaults to an ASCII space (U+0020).
+     * @return The property bag, for chaining.
+     * @see #setFormatWidth
+     */
+    public DecimalFormatProperties setPadString(String paddingString) {
+        this.padString = paddingString;
+        return this;
+    }
+
+    /**
+     * Whether to require cases to match when parsing strings; default is true. Case sensitivity applies to prefixes,
+     * suffixes, the exponent separator, the symbol "NaN", and the infinity symbol. Grouping separators, decimal
+     * separators, and padding are always case-sensitive. Currencies are always case-insensitive.
+     *
+     * <p>
+     * This setting is ignored in fast mode. In fast mode, strings are always compared in a case-sensitive way.
+     *
+     * @param parseCaseSensitive
+     *            true to be case-sensitive when parsing; false to allow any case.
+     * @return The property bag, for chaining.
+     */
+    public DecimalFormatProperties setParseCaseSensitive(boolean parseCaseSensitive) {
+        this.parseCaseSensitive = parseCaseSensitive;
+        return this;
+    }
+
+    /**
+     * 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.
+     *
+     * <p>
+     * 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).
+     *
+     * <p>
+     * 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 parseGroupingMode
+     *            The {@link GroupingMode} to use; either DEFAULT or RESTRICTED.
+     * @return The property bag, for chaining.
+     */
+    public DecimalFormatProperties setParseGroupingMode(GroupingMode parseGroupingMode) {
+        this.parseGroupingMode = parseGroupingMode;
+        return this;
+    }
+
+    /**
+     * Whether to ignore the fractional part of numbers. For example, parses "123.4" to "123" instead of "123.4".
+     *
+     * @param parseIntegerOnly
+     *            true to parse integers only; false to parse integers with their fraction parts
+     * @return The property bag, for chaining.
+     */
+    public DecimalFormatProperties setParseIntegerOnly(boolean parseIntegerOnly) {
+        this.parseIntegerOnly = parseIntegerOnly;
+        return this;
+    }
+
+    /**
+     * Controls certain rules for how strict this parser is when reading strings. See {@link ParseMode#LENIENT} and
+     * {@link ParseMode#STRICT}.
+     *
+     * @param parseMode
+     *            Either {@link ParseMode#LENIENT} or {@link ParseMode#STRICT}.
+     * @return The property bag, for chaining.
+     */
+    public DecimalFormatProperties setParseMode(ParseMode parseMode) {
+        this.parseMode = parseMode;
+        return this;
+    }
+
+    /**
+     * Whether to ignore the exponential part of numbers. For example, parses "123E4" to "123" instead of "1230000".
+     *
+     * @param parseNoExponent
+     *            true to ignore exponents; false to parse them.
+     * @return The property bag, for chaining.
+     */
+    public DecimalFormatProperties setParseNoExponent(boolean parseNoExponent) {
+        this.parseNoExponent = parseNoExponent;
+        return this;
+    }
+
+    /**
+     * Whether to always return a BigDecimal from {@link Parse#parse} and all other parse methods. By default, a Long or
+     * a BigInteger are returned when possible.
+     *
+     * @param parseToBigDecimal
+     *            true to always return a BigDecimal; false to return a Long or a BigInteger when possible.
+     * @return The property bag, for chaining.
+     */
+    public DecimalFormatProperties setParseToBigDecimal(boolean parseToBigDecimal) {
+        this.parseToBigDecimal = parseToBigDecimal;
+        return this;
+    }
+
+    /**
+     * Sets the PluralRules object to use instead of the default for the locale.
+     *
+     * @param pluralRules
+     *            The object to reference.
+     * @return The property bag, for chaining.
+     */
+    public DecimalFormatProperties setPluralRules(PluralRules pluralRules) {
+        this.pluralRules = pluralRules;
+        return this;
+    }
+
+    /**
+     * Sets the prefix to prepend to positive numbers. The prefix will be interpreted literally. For example, if you set
+     * a positive prefix of <code>p</code>, then the number 123 will be formatted as "p123" in the locale
+     * <em>en-US</em>.
+     *
+     * <p>
+     * For more information on prefixes and suffixes, see {@link MutablePatternModifier}.
+     *
+     * @param positivePrefix
+     *            The CharSequence to prepend to positive numbers.
+     * @return The property bag, for chaining.
+     * @see #setPositivePrefixPattern
+     */
+    public DecimalFormatProperties setPositivePrefix(String positivePrefix) {
+        this.positivePrefix = positivePrefix;
+        return this;
+    }
+
+    /**
+     * Sets the prefix to prepend to positive numbers. Locale-specific symbols will be substituted into the string
+     * according to Unicode Technical Standard #35 (LDML).
+     *
+     * <p>
+     * For more information on prefixes and suffixes, see {@link MutablePatternModifier}.
+     *
+     * @param positivePrefixPattern
+     *            The CharSequence to prepend to positive numbers after locale symbol substitutions take place.
+     * @return The property bag, for chaining.
+     * @see #setPositivePrefix
+     */
+    public DecimalFormatProperties setPositivePrefixPattern(String positivePrefixPattern) {
+        this.positivePrefixPattern = positivePrefixPattern;
+        return this;
+    }
+
+    /**
+     * Sets the suffix to append to positive numbers. The suffix will be interpreted literally. For example, if you set
+     * a positive suffix of <code>p</code>, then the number 123 will be formatted as "123p" in the locale
+     * <em>en-US</em>.
+     *
+     * <p>
+     * For more information on prefixes and suffixes, see {@link MutablePatternModifier}.
+     *
+     * @param positiveSuffix
+     *            The CharSequence to append to positive numbers.
+     * @return The property bag, for chaining.
+     * @see #setPositiveSuffixPattern
+     */
+    public DecimalFormatProperties setPositiveSuffix(String positiveSuffix) {
+        this.positiveSuffix = positiveSuffix;
+        return this;
+    }
+
+    /**
+     * Sets the suffix to append to positive numbers. Locale-specific symbols will be substituted into the string
+     * according to Unicode Technical Standard #35 (LDML).
+     *
+     * <p>
+     * For more information on prefixes and suffixes, see {@link MutablePatternModifier}.
+     *
+     * @param positiveSuffixPattern
+     *            The CharSequence to append to positive numbers after locale symbol substitutions take place.
+     * @return The property bag, for chaining.
+     * @see #setPositiveSuffix
+     */
+    public DecimalFormatProperties setPositiveSuffixPattern(String positiveSuffixPattern) {
+        this.positiveSuffixPattern = positiveSuffixPattern;
+        return this;
+    }
+
+    /**
+     * Sets the increment to which to round numbers. For example, with a rounding interval of 0.05, the number 11.17
+     * would be formatted as "11.15" in locale <em>en-US</em> with the default rounding mode.
+     *
+     * <p>
+     * You can use either a rounding increment or significant digits, but not both at the same time.
+     *
+     * <p>
+     * The rounding increment can be specified in a pattern string. For example, the pattern "#,##0.05" corresponds to a
+     * rounding interval of 0.05 with 1 minimum integer digit and a grouping size of 3.
+     *
+     * @param roundingIncrement
+     *            The interval to which to round.
+     * @return The property bag, for chaining.
+     */
+    public DecimalFormatProperties setRoundingIncrement(BigDecimal roundingIncrement) {
+        this.roundingIncrement = roundingIncrement;
+        return this;
+    }
+
+    /**
+     * Sets the rounding mode, which determines under which conditions extra decimal places are rounded either up or
+     * down. See {@link RoundingMode} for details on the choices of rounding mode. The default if not set explicitly is
+     * {@link RoundingMode#HALF_EVEN}.
+     *
+     * <p>
+     * This setting is ignored if {@link #setMathContext} is used.
+     *
+     * @param roundingMode
+     *            The rounding mode to use when rounding is required.
+     * @return The property bag, for chaining.
+     * @see RoundingMode
+     * @see #setMathContext
+     */
+    public DecimalFormatProperties setRoundingMode(RoundingMode roundingMode) {
+        this.roundingMode = roundingMode;
+        return this;
+    }
+
+    /**
+     * Sets the number of digits between grouping separators higher than the least-significant grouping separator. For
+     * example, the locale <em>hi</em> uses a primary grouping size of 3 and a secondary grouping size of 2, so the
+     * number 1234567 would be formatted as "12,34,567".
+     *
+     * <p>
+     * The two levels of grouping separators can be specified in the pattern string. For example, the <em>hi</em>
+     * locale's default decimal format pattern is "#,##,##0.###".
+     *
+     * @param secondaryGroupingSize
+     *            The secondary grouping size.
+     * @return The property bag, for chaining.
+     */
+    public DecimalFormatProperties setSecondaryGroupingSize(int secondaryGroupingSize) {
+        this.secondaryGroupingSize = secondaryGroupingSize;
+        return this;
+    }
+
+    /**
+     * Sets whether to always display of a plus sign on positive numbers.
+     *
+     * <p>
+     * If the location of the negative sign is specified by the decimal format pattern (or by the negative prefix/suffix
+     * pattern methods), a plus sign is substituted into that location, in accordance with Unicode Technical Standard
+     * #35 (LDML) section 3.2.1. Otherwise, the plus sign is prepended to the number. For example, if the decimal format
+     * pattern <code>#;#-</code> is used, then formatting 123 would result in "123+" in the locale <em>en-US</em>.
+     *
+     * <p>
+     * This method should be used <em>instead of</em> setting the positive prefix/suffix. The behavior is undefined if
+     * alwaysShowPlusSign is set but the positive prefix/suffix already contains a plus sign.
+     *
+     * @param signAlwaysShown
+     *            Whether positive numbers should display a plus sign.
+     * @return The property bag, for chaining.
+     */
+    public DecimalFormatProperties setSignAlwaysShown(boolean signAlwaysShown) {
+        this.signAlwaysShown = signAlwaysShown;
+        return this;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder result = new StringBuilder();
+        result.append("<Properties");
+        toStringBare(result);
+        result.append(">");
+        return result.toString();
+    }
+
+    /**
+     * Appends a string containing properties that differ from the default, but without being surrounded by
+     * &lt;Properties&gt;.
+     */
+    public void toStringBare(StringBuilder result) {
+        Field[] fields = DecimalFormatProperties.class.getDeclaredFields();
+        for (Field field : fields) {
+            Object myValue, defaultValue;
+            try {
+                myValue = field.get(this);
+                defaultValue = field.get(DEFAULT);
+            } catch (IllegalArgumentException e) {
+                e.printStackTrace();
+                continue;
+            } catch (IllegalAccessException e) {
+                e.printStackTrace();
+                continue;
+            }
+            if (myValue == null && defaultValue == null) {
+                continue;
+            } else if (myValue == null || defaultValue == null) {
+                result.append(" " + field.getName() + ":" + myValue);
+            } else if (!myValue.equals(defaultValue)) {
+                result.append(" " + field.getName() + ":" + myValue);
+            }
+        }
+    }
+
+    /**
+     * Custom serialization: save fields along with their name, so that fields can be easily added in the future in any
+     * order. Only save fields that differ from their default value.
+     */
+    private void writeObject(ObjectOutputStream oos) throws IOException {
+        writeObjectImpl(oos);
+    }
+
+    /* package-private */ void writeObjectImpl(ObjectOutputStream oos) throws IOException {
+        oos.defaultWriteObject();
+
+        // Extra int for possible future use
+        oos.writeInt(0);
+
+        ArrayList<Field> fieldsToSerialize = new ArrayList<Field>();
+        ArrayList<Object> valuesToSerialize = new ArrayList<Object>();
+        Field[] fields = DecimalFormatProperties.class.getDeclaredFields();
+        for (Field field : fields) {
+            if (Modifier.isStatic(field.getModifiers())) {
+                continue;
+            }
+            try {
+                Object myValue = field.get(this);
+                if (myValue == null) {
+                    // All *Object* values default to null; no need to serialize.
+                    continue;
+                }
+                Object defaultValue = field.get(DEFAULT);
+                if (!myValue.equals(defaultValue)) {
+                    fieldsToSerialize.add(field);
+                    valuesToSerialize.add(myValue);
+                }
+            } catch (IllegalArgumentException e) {
+                // Should not happen
+                throw new AssertionError(e);
+            } catch (IllegalAccessException e) {
+                // Should not happen
+                throw new AssertionError(e);
+            }
+        }
+
+        // 1) How many fields are to be serialized?
+        int count = fieldsToSerialize.size();
+        oos.writeInt(count);
+
+        // 2) Write each field with its name and value
+        for (int i = 0; i < count; i++) {
+            Field field = fieldsToSerialize.get(i);
+            Object value = valuesToSerialize.get(i);
+            oos.writeObject(field.getName());
+            oos.writeObject(value);
+        }
+    }
 }
index da412a366ca0d14c1614b21f3dc25e5118d86514..320878ff26cc68886c27fe840554e7714d3d5507 100644 (file)
@@ -120,6 +120,7 @@ public class CompactNotation extends Notation {
 
             StandardPlural plural = quantity.getStandardPlural(rules);
             String patternString = data.getPattern(magnitude, plural);
+            @SuppressWarnings("unused") // see #13177
             int numDigits = -1;
             if (patternString == null) {
                 // Use the default (non-compact) modifier.