• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GENERATED SOURCE. DO NOT MODIFY. */
2 // © 2017 and later: Unicode, Inc. and others.
3 // License & terms of use: http://www.unicode.org/copyright.html#License
4 package ohos.global.icu.impl.number;
5 
6 import java.io.IOException;
7 import java.io.ObjectInputStream;
8 import java.io.ObjectOutputStream;
9 import java.io.Serializable;
10 import java.lang.reflect.Field;
11 import java.lang.reflect.Modifier;
12 import java.math.BigDecimal;
13 import java.math.MathContext;
14 import java.math.RoundingMode;
15 import java.text.ParsePosition;
16 import java.util.ArrayList;
17 import java.util.Map;
18 
19 import ohos.global.icu.impl.number.Padder.PadPosition;
20 import ohos.global.icu.text.CompactDecimalFormat.CompactStyle;
21 import ohos.global.icu.text.CurrencyPluralInfo;
22 import ohos.global.icu.text.PluralRules;
23 import ohos.global.icu.util.Currency;
24 import ohos.global.icu.util.Currency.CurrencyUsage;
25 
26 /**
27  * @hide exposed on OHOS
28  */
29 public class DecimalFormatProperties implements Cloneable, Serializable {
30 
31     private static final DecimalFormatProperties DEFAULT = new DecimalFormatProperties();
32 
33     /** Auto-generated. */
34     private static final long serialVersionUID = 4095518955889349243L;
35 
36     /** Controls the set of rules for parsing a string from the old DecimalFormat API.
37      * @hide exposed on OHOS*/
38     public static enum ParseMode {
39         /**
40          * Lenient mode should be used if you want to accept malformed user input. It will use heuristics
41          * to attempt to parse through typographical errors in the string.
42          */
43         LENIENT,
44 
45         /**
46          * Strict mode should be used if you want to require that the input is well-formed. More
47          * specifically, it differs from lenient mode in the following ways:
48          *
49          * <ul>
50          * <li>Grouping widths must match the grouping settings. For example, "12,3,45" will fail if the
51          * grouping width is 3, as in the pattern "#,##0".
52          * <li>The string must contain a complete prefix and suffix. For example, if the pattern is
53          * "{#};(#)", then "{123}" or "(123)" would match, but "{123", "123}", and "123" would all fail.
54          * (The latter strings would be accepted in lenient mode.)
55          * <li>Whitespace may not appear at arbitrary places in the string. In lenient mode, whitespace
56          * is allowed to occur arbitrarily before and after prefixes and exponent separators.
57          * <li>Leading grouping separators are not allowed, as in ",123".
58          * <li>Minus and plus signs can only appear if specified in the pattern. In lenient mode, a plus
59          * or minus sign can always precede a number.
60          * <li>The set of characters that can be interpreted as a decimal or grouping separator is
61          * smaller.
62          * <li><strong>If currency parsing is enabled,</strong> currencies must only appear where
63          * specified in either the current pattern string or in a valid pattern string for the current
64          * locale. For example, if the pattern is "¤0.00", then "$1.23" would match, but "1.23$" would
65          * fail to match.
66          * </ul>
67          */
68         STRICT,
69 
70         /**
71          * Internal parse mode for increased compatibility with java.text.DecimalFormat.
72          * Used by Android libcore. To enable this feature, java.text.DecimalFormat holds an instance of
73          * ICU4J's DecimalFormat and enable it by calling setParseStrictMode(ParseMode.JAVA_COMPATIBILITY).
74          */
75         JAVA_COMPATIBILITY,
76     }
77 
78     // The setters in this class should NOT have any side-effects or perform any validation. It is
79     // up to the consumer of the property bag to deal with property validation.
80 
81     // The fields are all marked "transient" because custom serialization is being used.
82 
83     /*--------------------------------------------------------------------------------------------+/
84     /| IMPORTANT!                                                                                 |/
85     /| WHEN ADDING A NEW PROPERTY, add it here, in #_clear(), in #_copyFrom(), in #equals(),      |/
86     /| and in #_hashCode().                                                                       |/
87     /|                                                                                            |/
88     /| The unit test PropertiesTest will catch if you forget to add it to #clear(), #copyFrom(),  |/
89     /| or #equals(), but it will NOT catch if you forget to add it to #hashCode().                |/
90     /+--------------------------------------------------------------------------------------------*/
91 
92     private transient Map<String, Map<String, String>> compactCustomData; // ICU4J-only
93     private transient CompactStyle compactStyle;
94     private transient Currency currency;
95     private transient CurrencyPluralInfo currencyPluralInfo;
96     private transient CurrencyUsage currencyUsage;
97     private transient boolean decimalPatternMatchRequired;
98     private transient boolean decimalSeparatorAlwaysShown;
99     private transient boolean exponentSignAlwaysShown;
100     private transient int formatWidth;
101     private transient int groupingSize;
102     private transient boolean groupingUsed;
103     private transient int magnitudeMultiplier;
104     private transient MathContext mathContext; // ICU4J-only
105     private transient int maximumFractionDigits;
106     private transient int maximumIntegerDigits;
107     private transient int maximumSignificantDigits;
108     private transient int minimumExponentDigits;
109     private transient int minimumFractionDigits;
110     private transient int minimumGroupingDigits;
111     private transient int minimumIntegerDigits;
112     private transient int minimumSignificantDigits;
113     private transient BigDecimal multiplier;
114     private transient String negativePrefix;
115     private transient String negativePrefixPattern;
116     private transient String negativeSuffix;
117     private transient String negativeSuffixPattern;
118     private transient PadPosition padPosition;
119     private transient String padString;
120     private transient boolean parseCaseSensitive;
121     private transient boolean parseIntegerOnly;
122     private transient ParseMode parseMode;
123     private transient boolean parseNoExponent;
124     private transient boolean parseToBigDecimal;
125     private transient PluralRules pluralRules;
126     private transient String positivePrefix;
127     private transient String positivePrefixPattern;
128     private transient String positiveSuffix;
129     private transient String positiveSuffixPattern;
130     private transient BigDecimal roundingIncrement;
131     private transient RoundingMode roundingMode;
132     private transient int secondaryGroupingSize;
133     private transient boolean signAlwaysShown;
134 
135     /*--------------------------------------------------------------------------------------------+/
136     /| IMPORTANT!                                                                                 |/
137     /| WHEN ADDING A NEW PROPERTY, add it here, in #_clear(), in #_copyFrom(), in #equals(),      |/
138     /| and in #_hashCode().                                                                       |/
139     /|                                                                                            |/
140     /| The unit test PropertiesTest will catch if you forget to add it to #clear(), #copyFrom(),  |/
141     /| or #equals(), but it will NOT catch if you forget to add it to #hashCode().                |/
142     /+--------------------------------------------------------------------------------------------*/
143 
DecimalFormatProperties()144     public DecimalFormatProperties() {
145         clear();
146     }
147 
148     /**
149      * Sets all properties to their defaults (unset).
150      *
151      * <p>
152      * All integers default to -1 EXCEPT FOR MAGNITUDE MULTIPLIER which has a default of 0 (since
153      * negative numbers are important).
154      *
155      * <p>
156      * All booleans default to false.
157      *
158      * <p>
159      * All non-primitive types default to null.
160      *
161      * @return The property bag, for chaining.
162      */
_clear()163     private DecimalFormatProperties _clear() {
164         compactCustomData = null;
165         compactStyle = null;
166         currency = null;
167         currencyPluralInfo = null;
168         currencyUsage = null;
169         decimalPatternMatchRequired = false;
170         decimalSeparatorAlwaysShown = false;
171         exponentSignAlwaysShown = false;
172         formatWidth = -1;
173         groupingSize = -1;
174         groupingUsed = true;
175         magnitudeMultiplier = 0;
176         mathContext = null;
177         maximumFractionDigits = -1;
178         maximumIntegerDigits = -1;
179         maximumSignificantDigits = -1;
180         minimumExponentDigits = -1;
181         minimumFractionDigits = -1;
182         minimumGroupingDigits = -1;
183         minimumIntegerDigits = -1;
184         minimumSignificantDigits = -1;
185         multiplier = null;
186         negativePrefix = null;
187         negativePrefixPattern = null;
188         negativeSuffix = null;
189         negativeSuffixPattern = null;
190         padPosition = null;
191         padString = null;
192         parseCaseSensitive = false;
193         parseIntegerOnly = false;
194         parseMode = null;
195         parseNoExponent = false;
196         parseToBigDecimal = false;
197         pluralRules = null;
198         positivePrefix = null;
199         positivePrefixPattern = null;
200         positiveSuffix = null;
201         positiveSuffixPattern = null;
202         roundingIncrement = null;
203         roundingMode = null;
204         secondaryGroupingSize = -1;
205         signAlwaysShown = false;
206         return this;
207     }
208 
_copyFrom(DecimalFormatProperties other)209     private DecimalFormatProperties _copyFrom(DecimalFormatProperties other) {
210         compactCustomData = other.compactCustomData;
211         compactStyle = other.compactStyle;
212         currency = other.currency;
213         currencyPluralInfo = other.currencyPluralInfo;
214         currencyUsage = other.currencyUsage;
215         decimalPatternMatchRequired = other.decimalPatternMatchRequired;
216         decimalSeparatorAlwaysShown = other.decimalSeparatorAlwaysShown;
217         exponentSignAlwaysShown = other.exponentSignAlwaysShown;
218         formatWidth = other.formatWidth;
219         groupingSize = other.groupingSize;
220         groupingUsed = other.groupingUsed;
221         magnitudeMultiplier = other.magnitudeMultiplier;
222         mathContext = other.mathContext;
223         maximumFractionDigits = other.maximumFractionDigits;
224         maximumIntegerDigits = other.maximumIntegerDigits;
225         maximumSignificantDigits = other.maximumSignificantDigits;
226         minimumExponentDigits = other.minimumExponentDigits;
227         minimumFractionDigits = other.minimumFractionDigits;
228         minimumGroupingDigits = other.minimumGroupingDigits;
229         minimumIntegerDigits = other.minimumIntegerDigits;
230         minimumSignificantDigits = other.minimumSignificantDigits;
231         multiplier = other.multiplier;
232         negativePrefix = other.negativePrefix;
233         negativePrefixPattern = other.negativePrefixPattern;
234         negativeSuffix = other.negativeSuffix;
235         negativeSuffixPattern = other.negativeSuffixPattern;
236         padPosition = other.padPosition;
237         padString = other.padString;
238         parseCaseSensitive = other.parseCaseSensitive;
239         parseIntegerOnly = other.parseIntegerOnly;
240         parseMode = other.parseMode;
241         parseNoExponent = other.parseNoExponent;
242         parseToBigDecimal = other.parseToBigDecimal;
243         pluralRules = other.pluralRules;
244         positivePrefix = other.positivePrefix;
245         positivePrefixPattern = other.positivePrefixPattern;
246         positiveSuffix = other.positiveSuffix;
247         positiveSuffixPattern = other.positiveSuffixPattern;
248         roundingIncrement = other.roundingIncrement;
249         roundingMode = other.roundingMode;
250         secondaryGroupingSize = other.secondaryGroupingSize;
251         signAlwaysShown = other.signAlwaysShown;
252         return this;
253     }
254 
_equals(DecimalFormatProperties other)255     private boolean _equals(DecimalFormatProperties other) {
256         boolean eq = true;
257         eq = eq && _equalsHelper(compactCustomData, other.compactCustomData);
258         eq = eq && _equalsHelper(compactStyle, other.compactStyle);
259         eq = eq && _equalsHelper(currency, other.currency);
260         eq = eq && _equalsHelper(currencyPluralInfo, other.currencyPluralInfo);
261         eq = eq && _equalsHelper(currencyUsage, other.currencyUsage);
262         eq = eq && _equalsHelper(decimalPatternMatchRequired, other.decimalPatternMatchRequired);
263         eq = eq && _equalsHelper(decimalSeparatorAlwaysShown, other.decimalSeparatorAlwaysShown);
264         eq = eq && _equalsHelper(exponentSignAlwaysShown, other.exponentSignAlwaysShown);
265         eq = eq && _equalsHelper(formatWidth, other.formatWidth);
266         eq = eq && _equalsHelper(groupingSize, other.groupingSize);
267         eq = eq && _equalsHelper(groupingUsed, other.groupingUsed);
268         eq = eq && _equalsHelper(magnitudeMultiplier, other.magnitudeMultiplier);
269         eq = eq && _equalsHelper(mathContext, other.mathContext);
270         eq = eq && _equalsHelper(maximumFractionDigits, other.maximumFractionDigits);
271         eq = eq && _equalsHelper(maximumIntegerDigits, other.maximumIntegerDigits);
272         eq = eq && _equalsHelper(maximumSignificantDigits, other.maximumSignificantDigits);
273         eq = eq && _equalsHelper(minimumExponentDigits, other.minimumExponentDigits);
274         eq = eq && _equalsHelper(minimumFractionDigits, other.minimumFractionDigits);
275         eq = eq && _equalsHelper(minimumGroupingDigits, other.minimumGroupingDigits);
276         eq = eq && _equalsHelper(minimumIntegerDigits, other.minimumIntegerDigits);
277         eq = eq && _equalsHelper(minimumSignificantDigits, other.minimumSignificantDigits);
278         eq = eq && _equalsHelper(multiplier, other.multiplier);
279         eq = eq && _equalsHelper(negativePrefix, other.negativePrefix);
280         eq = eq && _equalsHelper(negativePrefixPattern, other.negativePrefixPattern);
281         eq = eq && _equalsHelper(negativeSuffix, other.negativeSuffix);
282         eq = eq && _equalsHelper(negativeSuffixPattern, other.negativeSuffixPattern);
283         eq = eq && _equalsHelper(padPosition, other.padPosition);
284         eq = eq && _equalsHelper(padString, other.padString);
285         eq = eq && _equalsHelper(parseCaseSensitive, other.parseCaseSensitive);
286         eq = eq && _equalsHelper(parseIntegerOnly, other.parseIntegerOnly);
287         eq = eq && _equalsHelper(parseMode, other.parseMode);
288         eq = eq && _equalsHelper(parseNoExponent, other.parseNoExponent);
289         eq = eq && _equalsHelper(parseToBigDecimal, other.parseToBigDecimal);
290         eq = eq && _equalsHelper(pluralRules, other.pluralRules);
291         eq = eq && _equalsHelper(positivePrefix, other.positivePrefix);
292         eq = eq && _equalsHelper(positivePrefixPattern, other.positivePrefixPattern);
293         eq = eq && _equalsHelper(positiveSuffix, other.positiveSuffix);
294         eq = eq && _equalsHelper(positiveSuffixPattern, other.positiveSuffixPattern);
295         eq = eq && _equalsHelper(roundingIncrement, other.roundingIncrement);
296         eq = eq && _equalsHelper(roundingMode, other.roundingMode);
297         eq = eq && _equalsHelper(secondaryGroupingSize, other.secondaryGroupingSize);
298         eq = eq && _equalsHelper(signAlwaysShown, other.signAlwaysShown);
299         return eq;
300     }
301 
_equalsHelper(boolean mine, boolean theirs)302     private boolean _equalsHelper(boolean mine, boolean theirs) {
303         return mine == theirs;
304     }
305 
_equalsHelper(int mine, int theirs)306     private boolean _equalsHelper(int mine, int theirs) {
307         return mine == theirs;
308     }
309 
_equalsHelper(Object mine, Object theirs)310     private boolean _equalsHelper(Object mine, Object theirs) {
311         if (mine == theirs)
312             return true;
313         if (mine == null)
314             return false;
315         return mine.equals(theirs);
316     }
317 
_hashCode()318     private int _hashCode() {
319         int hashCode = 0;
320         hashCode ^= _hashCodeHelper(compactCustomData);
321         hashCode ^= _hashCodeHelper(compactStyle);
322         hashCode ^= _hashCodeHelper(currency);
323         hashCode ^= _hashCodeHelper(currencyPluralInfo);
324         hashCode ^= _hashCodeHelper(currencyUsage);
325         hashCode ^= _hashCodeHelper(decimalPatternMatchRequired);
326         hashCode ^= _hashCodeHelper(decimalSeparatorAlwaysShown);
327         hashCode ^= _hashCodeHelper(exponentSignAlwaysShown);
328         hashCode ^= _hashCodeHelper(formatWidth);
329         hashCode ^= _hashCodeHelper(groupingSize);
330         hashCode ^= _hashCodeHelper(groupingUsed);
331         hashCode ^= _hashCodeHelper(magnitudeMultiplier);
332         hashCode ^= _hashCodeHelper(mathContext);
333         hashCode ^= _hashCodeHelper(maximumFractionDigits);
334         hashCode ^= _hashCodeHelper(maximumIntegerDigits);
335         hashCode ^= _hashCodeHelper(maximumSignificantDigits);
336         hashCode ^= _hashCodeHelper(minimumExponentDigits);
337         hashCode ^= _hashCodeHelper(minimumFractionDigits);
338         hashCode ^= _hashCodeHelper(minimumGroupingDigits);
339         hashCode ^= _hashCodeHelper(minimumIntegerDigits);
340         hashCode ^= _hashCodeHelper(minimumSignificantDigits);
341         hashCode ^= _hashCodeHelper(multiplier);
342         hashCode ^= _hashCodeHelper(negativePrefix);
343         hashCode ^= _hashCodeHelper(negativePrefixPattern);
344         hashCode ^= _hashCodeHelper(negativeSuffix);
345         hashCode ^= _hashCodeHelper(negativeSuffixPattern);
346         hashCode ^= _hashCodeHelper(padPosition);
347         hashCode ^= _hashCodeHelper(padString);
348         hashCode ^= _hashCodeHelper(parseCaseSensitive);
349         hashCode ^= _hashCodeHelper(parseIntegerOnly);
350         hashCode ^= _hashCodeHelper(parseMode);
351         hashCode ^= _hashCodeHelper(parseNoExponent);
352         hashCode ^= _hashCodeHelper(parseToBigDecimal);
353         hashCode ^= _hashCodeHelper(pluralRules);
354         hashCode ^= _hashCodeHelper(positivePrefix);
355         hashCode ^= _hashCodeHelper(positivePrefixPattern);
356         hashCode ^= _hashCodeHelper(positiveSuffix);
357         hashCode ^= _hashCodeHelper(positiveSuffixPattern);
358         hashCode ^= _hashCodeHelper(roundingIncrement);
359         hashCode ^= _hashCodeHelper(roundingMode);
360         hashCode ^= _hashCodeHelper(secondaryGroupingSize);
361         hashCode ^= _hashCodeHelper(signAlwaysShown);
362         return hashCode;
363     }
364 
_hashCodeHelper(boolean value)365     private int _hashCodeHelper(boolean value) {
366         return value ? 1 : 0;
367     }
368 
_hashCodeHelper(int value)369     private int _hashCodeHelper(int value) {
370         return value * 13;
371     }
372 
_hashCodeHelper(Object value)373     private int _hashCodeHelper(Object value) {
374         if (value == null)
375             return 0;
376         return value.hashCode();
377     }
378 
clear()379     public DecimalFormatProperties clear() {
380         return _clear();
381     }
382 
383     /** Creates and returns a shallow copy of the property bag. */
384     @Override
clone()385     public DecimalFormatProperties clone() {
386         // super.clone() returns a shallow copy.
387         try {
388             return (DecimalFormatProperties) super.clone();
389         } catch (CloneNotSupportedException e) {
390             // Should never happen since super is Object
391             throw new UnsupportedOperationException(e);
392         }
393     }
394 
395     /**
396      * Shallow-copies the properties from the given property bag into this property bag.
397      *
398      * @param other
399      *            The property bag from which to copy and which will not be modified.
400      * @return The current property bag (the one modified by this operation), for chaining.
401      */
copyFrom(DecimalFormatProperties other)402     public DecimalFormatProperties copyFrom(DecimalFormatProperties other) {
403         return _copyFrom(other);
404     }
405 
406     @Override
equals(Object other)407     public boolean equals(Object other) {
408         if (other == null)
409             return false;
410         if (this == other)
411             return true;
412         if (!(other instanceof DecimalFormatProperties))
413             return false;
414         return _equals((DecimalFormatProperties) other);
415     }
416 
417     /// BEGIN GETTERS/SETTERS ///
418 
getCompactCustomData()419     public Map<String, Map<String, String>> getCompactCustomData() {
420         return compactCustomData;
421     }
422 
getCompactStyle()423     public CompactStyle getCompactStyle() {
424         return compactStyle;
425     }
426 
getCurrency()427     public Currency getCurrency() {
428         return currency;
429     }
430 
getCurrencyPluralInfo()431     public CurrencyPluralInfo getCurrencyPluralInfo() {
432         return currencyPluralInfo;
433     }
434 
getCurrencyUsage()435     public CurrencyUsage getCurrencyUsage() {
436         return currencyUsage;
437     }
438 
getDecimalPatternMatchRequired()439     public boolean getDecimalPatternMatchRequired() {
440         return decimalPatternMatchRequired;
441     }
442 
getDecimalSeparatorAlwaysShown()443     public boolean getDecimalSeparatorAlwaysShown() {
444         return decimalSeparatorAlwaysShown;
445     }
446 
getExponentSignAlwaysShown()447     public boolean getExponentSignAlwaysShown() {
448         return exponentSignAlwaysShown;
449     }
450 
getFormatWidth()451     public int getFormatWidth() {
452         return formatWidth;
453     }
454 
getGroupingSize()455     public int getGroupingSize() {
456         return groupingSize;
457     }
458 
getGroupingUsed()459     public boolean getGroupingUsed() {
460         return groupingUsed;
461     }
462 
getMagnitudeMultiplier()463     public int getMagnitudeMultiplier() {
464         return magnitudeMultiplier;
465     }
466 
getMathContext()467     public MathContext getMathContext() {
468         return mathContext;
469     }
470 
getMaximumFractionDigits()471     public int getMaximumFractionDigits() {
472         return maximumFractionDigits;
473     }
474 
getMaximumIntegerDigits()475     public int getMaximumIntegerDigits() {
476         return maximumIntegerDigits;
477     }
478 
getMaximumSignificantDigits()479     public int getMaximumSignificantDigits() {
480         return maximumSignificantDigits;
481     }
482 
getMinimumExponentDigits()483     public int getMinimumExponentDigits() {
484         return minimumExponentDigits;
485     }
486 
getMinimumFractionDigits()487     public int getMinimumFractionDigits() {
488         return minimumFractionDigits;
489     }
490 
getMinimumGroupingDigits()491     public int getMinimumGroupingDigits() {
492         return minimumGroupingDigits;
493     }
494 
getMinimumIntegerDigits()495     public int getMinimumIntegerDigits() {
496         return minimumIntegerDigits;
497     }
498 
getMinimumSignificantDigits()499     public int getMinimumSignificantDigits() {
500         return minimumSignificantDigits;
501     }
502 
getMultiplier()503     public BigDecimal getMultiplier() {
504         return multiplier;
505     }
506 
getNegativePrefix()507     public String getNegativePrefix() {
508         return negativePrefix;
509     }
510 
getNegativePrefixPattern()511     public String getNegativePrefixPattern() {
512         return negativePrefixPattern;
513     }
514 
getNegativeSuffix()515     public String getNegativeSuffix() {
516         return negativeSuffix;
517     }
518 
getNegativeSuffixPattern()519     public String getNegativeSuffixPattern() {
520         return negativeSuffixPattern;
521     }
522 
getPadPosition()523     public PadPosition getPadPosition() {
524         return padPosition;
525     }
526 
getPadString()527     public String getPadString() {
528         return padString;
529     }
530 
getParseCaseSensitive()531     public boolean getParseCaseSensitive() {
532         return parseCaseSensitive;
533     }
534 
getParseIntegerOnly()535     public boolean getParseIntegerOnly() {
536         return parseIntegerOnly;
537     }
538 
getParseMode()539     public ParseMode getParseMode() {
540         return parseMode;
541     }
542 
getParseNoExponent()543     public boolean getParseNoExponent() {
544         return parseNoExponent;
545     }
546 
getParseToBigDecimal()547     public boolean getParseToBigDecimal() {
548         return parseToBigDecimal;
549     }
550 
getPluralRules()551     public PluralRules getPluralRules() {
552         return pluralRules;
553     }
554 
getPositivePrefix()555     public String getPositivePrefix() {
556         return positivePrefix;
557     }
558 
getPositivePrefixPattern()559     public String getPositivePrefixPattern() {
560         return positivePrefixPattern;
561     }
562 
getPositiveSuffix()563     public String getPositiveSuffix() {
564         return positiveSuffix;
565     }
566 
getPositiveSuffixPattern()567     public String getPositiveSuffixPattern() {
568         return positiveSuffixPattern;
569     }
570 
getRoundingIncrement()571     public BigDecimal getRoundingIncrement() {
572         return roundingIncrement;
573     }
574 
getRoundingMode()575     public RoundingMode getRoundingMode() {
576         return roundingMode;
577     }
578 
getSecondaryGroupingSize()579     public int getSecondaryGroupingSize() {
580         return secondaryGroupingSize;
581     }
582 
getSignAlwaysShown()583     public boolean getSignAlwaysShown() {
584         return signAlwaysShown;
585     }
586 
587     @Override
hashCode()588     public int hashCode() {
589         return _hashCode();
590     }
591 
592     /** Custom serialization: re-create object from serialized properties. */
readObject(ObjectInputStream ois)593     private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
594         readObjectImpl(ois);
595     }
596 
readObjectImpl(ObjectInputStream ois)597     /* package-private */ void readObjectImpl(ObjectInputStream ois)
598             throws IOException, ClassNotFoundException {
599         ois.defaultReadObject();
600 
601         // Initialize to empty
602         clear();
603 
604         // Extra int for possible future use
605         ois.readInt();
606 
607         // 1) How many fields were serialized?
608         int count = ois.readInt();
609 
610         // 2) Read each field by its name and value
611         for (int i = 0; i < count; i++) {
612             String name = (String) ois.readObject();
613             Object value = ois.readObject();
614 
615             // Get the field reference
616             Field field = null;
617             try {
618                 field = DecimalFormatProperties.class.getDeclaredField(name);
619             } catch (NoSuchFieldException e) {
620                 // The field name does not exist! Possibly corrupted serialization. Ignore this entry.
621                 continue;
622             } catch (SecurityException e) {
623                 // Should not happen
624                 throw new AssertionError(e);
625             }
626 
627             // NOTE: If the type of a field were changed in the future, this would be the place to check:
628             // If the variable `value` is the old type, perform any conversions necessary.
629 
630             // Save value into the field
631             try {
632                 field.set(this, value);
633             } catch (IllegalArgumentException e) {
634                 // Should not happen
635                 throw new AssertionError(e);
636             } catch (IllegalAccessException e) {
637                 // Should not happen
638                 throw new AssertionError(e);
639             }
640         }
641     }
642 
643     /**
644      * Specifies custom data to be used instead of CLDR data when constructing a CompactDecimalFormat.
645      * The argument should be a map with the following structure:
646      *
647      * <pre>
648      * {
649      *   "1000": {
650      *     "one": "0 thousand",
651      *     "other": "0 thousand"
652      *   },
653      *   "10000": {
654      *     "one": "00 thousand",
655      *     "other": "00 thousand"
656      *   },
657      *   // ...
658      * }
659      * </pre>
660      *
661      * This API endpoint is used by the CLDR Survey Tool.
662      *
663      * @param compactCustomData
664      *            A map with the above structure.
665      * @return The property bag, for chaining.
666      */
setCompactCustomData( Map<String, Map<String, String>> compactCustomData)667     public DecimalFormatProperties setCompactCustomData(
668             Map<String, Map<String, String>> compactCustomData) {
669         // TODO: compactCustomData is not immutable.
670         this.compactCustomData = compactCustomData;
671         return this;
672     }
673 
674     /**
675      * Use compact decimal formatting with the specified {@link CompactStyle}. CompactStyle.SHORT
676      * produces output like "10K" in locale <em>en-US</em>, whereas CompactStyle.LONG produces output
677      * like "10 thousand" in that locale.
678      *
679      * @param compactStyle
680      *            The style of prefixes/suffixes to append.
681      * @return The property bag, for chaining.
682      */
setCompactStyle(CompactStyle compactStyle)683     public DecimalFormatProperties setCompactStyle(CompactStyle compactStyle) {
684         this.compactStyle = compactStyle;
685         return this;
686     }
687 
688     /**
689      * Use the specified currency to substitute currency placeholders ('¤') in the pattern string.
690      *
691      * @param currency
692      *            The currency.
693      * @return The property bag, for chaining.
694      */
setCurrency(Currency currency)695     public DecimalFormatProperties setCurrency(Currency currency) {
696         this.currency = currency;
697         return this;
698     }
699 
700     /**
701      * Use the specified {@link CurrencyPluralInfo} instance when formatting currency long names.
702      *
703      * @param currencyPluralInfo
704      *            The currency plural info object.
705      * @return The property bag, for chaining.
706      */
setCurrencyPluralInfo(CurrencyPluralInfo currencyPluralInfo)707     public DecimalFormatProperties setCurrencyPluralInfo(CurrencyPluralInfo currencyPluralInfo) {
708         // TODO: In order to maintain immutability, we have to perform a clone here.
709         // It would be better to just retire CurrencyPluralInfo entirely.
710         if (currencyPluralInfo != null) {
711             currencyPluralInfo = (CurrencyPluralInfo) currencyPluralInfo.clone();
712         }
713         this.currencyPluralInfo = currencyPluralInfo;
714         return this;
715     }
716 
717     /**
718      * Use the specified {@link CurrencyUsage} instance, which provides default rounding rules for the
719      * currency in two styles, CurrencyUsage.CASH and CurrencyUsage.STANDARD.
720      *
721      * <p>
722      * The CurrencyUsage specified here will not be used unless there is a currency placeholder in the
723      * pattern.
724      *
725      * @param currencyUsage
726      *            The currency usage. Defaults to CurrencyUsage.STANDARD.
727      * @return The property bag, for chaining.
728      */
setCurrencyUsage(CurrencyUsage currencyUsage)729     public DecimalFormatProperties setCurrencyUsage(CurrencyUsage currencyUsage) {
730         this.currencyUsage = currencyUsage;
731         return this;
732     }
733 
734     /**
735      * PARSING: Whether to require that the presence of decimal point matches the pattern. If a decimal
736      * point is not present, but the pattern contained a decimal point, parse will not succeed: null will
737      * be returned from <code>parse()</code>, and an error index will be set in the
738      * {@link ParsePosition}.
739      *
740      * @param decimalPatternMatchRequired
741      *            true to set an error if decimal is not present
742      * @return The property bag, for chaining.
743      */
setDecimalPatternMatchRequired(boolean decimalPatternMatchRequired)744     public DecimalFormatProperties setDecimalPatternMatchRequired(boolean decimalPatternMatchRequired) {
745         this.decimalPatternMatchRequired = decimalPatternMatchRequired;
746         return this;
747     }
748 
749     /**
750      * Sets whether to always show the decimal point, even if the number doesn't require one. For
751      * example, if always show decimal is true, the number 123 would be formatted as "123." in locale
752      * <em>en-US</em>.
753      *
754      * @param alwaysShowDecimal
755      *            Whether to show the decimal point when it is optional.
756      * @return The property bag, for chaining.
757      */
setDecimalSeparatorAlwaysShown(boolean alwaysShowDecimal)758     public DecimalFormatProperties setDecimalSeparatorAlwaysShown(boolean alwaysShowDecimal) {
759         this.decimalSeparatorAlwaysShown = alwaysShowDecimal;
760         return this;
761     }
762 
763     /**
764      * Sets whether to show the plus sign in the exponent part of numbers with a zero or positive
765      * exponent. For example, the number "1200" with the pattern "0.0E0" would be formatted as "1.2E+3"
766      * instead of "1.2E3" in <em>en-US</em>.
767      *
768      * @param exponentSignAlwaysShown
769      *            Whether to show the plus sign in positive exponents.
770      * @return The property bag, for chaining.
771      */
setExponentSignAlwaysShown(boolean exponentSignAlwaysShown)772     public DecimalFormatProperties setExponentSignAlwaysShown(boolean exponentSignAlwaysShown) {
773         this.exponentSignAlwaysShown = exponentSignAlwaysShown;
774         return this;
775     }
776 
777     /**
778      * Sets the minimum width of the string output by the formatting pipeline. For example, if padding is
779      * enabled and paddingWidth is set to 6, formatting the number "3.14159" with the pattern "0.00" will
780      * result in "··3.14" if '·' is your padding string.
781      *
782      * <p>
783      * If the number is longer than your padding width, the number will display as if no padding width
784      * had been specified, which may result in strings longer than the padding width.
785      *
786      * <p>
787      * Width is counted in UTF-16 code units.
788      *
789      * @param paddingWidth
790      *            The output width.
791      * @return The property bag, for chaining.
792      * @see #setPadPosition
793      * @see #setPadString
794      */
setFormatWidth(int paddingWidth)795     public DecimalFormatProperties setFormatWidth(int paddingWidth) {
796         this.formatWidth = paddingWidth;
797         return this;
798     }
799 
800     /**
801      * Sets the number of digits between grouping separators. For example, the <em>en-US</em> locale uses
802      * a grouping size of 3, so the number 1234567 would be formatted as "1,234,567". For locales whose
803      * grouping sizes vary with magnitude, see {@link #setSecondaryGroupingSize(int)}.
804      *
805      * @param groupingSize
806      *            The primary grouping size.
807      * @return The property bag, for chaining.
808      */
setGroupingSize(int groupingSize)809     public DecimalFormatProperties setGroupingSize(int groupingSize) {
810         this.groupingSize = groupingSize;
811         return this;
812     }
813 
814     /**
815      * Sets whether to enable grouping when formatting.
816      *
817      * @param groupingUsed
818      *            true to enable the display of grouping separators; false to disable.
819      * @return The property bag, for chaining.
820      */
setGroupingUsed(boolean groupingUsed)821     public DecimalFormatProperties setGroupingUsed(boolean groupingUsed) {
822         this.groupingUsed = groupingUsed;
823         return this;
824     }
825 
826     /**
827      * Multiply all numbers by this power of ten before formatting. Negative multipliers reduce the
828      * magnitude and make numbers smaller (closer to zero).
829      *
830      * @param magnitudeMultiplier
831      *            The number of powers of ten to scale.
832      * @return The property bag, for chaining.
833      * @see #setMultiplier
834      */
setMagnitudeMultiplier(int magnitudeMultiplier)835     public DecimalFormatProperties setMagnitudeMultiplier(int magnitudeMultiplier) {
836         this.magnitudeMultiplier = magnitudeMultiplier;
837         return this;
838     }
839 
840     /**
841      * Sets the {@link MathContext} to be used during math and rounding operations. A MathContext
842      * encapsulates a RoundingMode and the number of significant digits in the output.
843      *
844      * @param mathContext
845      *            The math context to use when rounding is required.
846      * @return The property bag, for chaining.
847      * @see MathContext
848      * @see #setRoundingMode
849      */
setMathContext(MathContext mathContext)850     public DecimalFormatProperties setMathContext(MathContext mathContext) {
851         this.mathContext = mathContext;
852         return this;
853     }
854 
855     /**
856      * Sets the maximum number of digits to display after the decimal point. If the number has fewer than
857      * this number of digits, the number will be rounded off using the rounding mode specified by
858      * {@link #setRoundingMode(RoundingMode)}. The pattern "#00.0#", for example, corresponds to 2
859      * maximum fraction digits, and the number 456.789 would be formatted as "456.79" in locale
860      * <em>en-US</em> with the default rounding mode. Note that the number 456.999 would be formatted as
861      * "457.0" given the same configurations.
862      *
863      * @param maximumFractionDigits
864      *            The maximum number of fraction digits to output.
865      * @return The property bag, for chaining.
866      */
setMaximumFractionDigits(int maximumFractionDigits)867     public DecimalFormatProperties setMaximumFractionDigits(int maximumFractionDigits) {
868         this.maximumFractionDigits = maximumFractionDigits;
869         return this;
870     }
871 
872     /**
873      * Sets the maximum number of digits to display before the decimal point. If the number has more than
874      * this number of digits, the extra digits will be truncated. For example, if maximum integer digits
875      * is 2, and you attempt to format the number 1970, you will get "70" in locale <em>en-US</em>. It is
876      * not possible to specify the maximum integer digits using a pattern string, except in the special
877      * case of a scientific format pattern.
878      *
879      * @param maximumIntegerDigits
880      *            The maximum number of integer digits to output.
881      * @return The property bag, for chaining.
882      */
setMaximumIntegerDigits(int maximumIntegerDigits)883     public DecimalFormatProperties setMaximumIntegerDigits(int maximumIntegerDigits) {
884         this.maximumIntegerDigits = maximumIntegerDigits;
885         return this;
886     }
887 
888     /**
889      * Sets the maximum number of significant digits to display. The number of significant digits is
890      * equal to the number of digits counted from the leftmost nonzero digit through the rightmost
891      * nonzero digit; for example, the number "2010" has 3 significant digits. If the number has more
892      * significant digits than specified here, the extra significant digits will be rounded off using the
893      * rounding mode specified by {@link #setRoundingMode(RoundingMode)}. For example, if maximum
894      * significant digits is 3, the number 1234.56 will be formatted as "1230" in locale <em>en-US</em>
895      * with the default rounding mode.
896      *
897      * <p>
898      * If both maximum significant digits and maximum integer/fraction digits are set at the same time,
899      * the behavior is undefined.
900      *
901      * <p>
902      * The number of significant digits can be specified in a pattern string using the '@' character. For
903      * example, the pattern "@@#" corresponds to a minimum of 2 and a maximum of 3 significant digits.
904      *
905      * @param maximumSignificantDigits
906      *            The maximum number of significant digits to display.
907      * @return The property bag, for chaining.
908      */
setMaximumSignificantDigits(int maximumSignificantDigits)909     public DecimalFormatProperties setMaximumSignificantDigits(int maximumSignificantDigits) {
910         this.maximumSignificantDigits = maximumSignificantDigits;
911         return this;
912     }
913 
914     /**
915      * Sets the minimum number of digits to display in the exponent. For example, the number "1200" with
916      * the pattern "0.0E00", which has 2 exponent digits, would be formatted as "1.2E03" in
917      * <em>en-US</em>.
918      *
919      * @param minimumExponentDigits
920      *            The minimum number of digits to display in the exponent field.
921      * @return The property bag, for chaining.
922      */
setMinimumExponentDigits(int minimumExponentDigits)923     public DecimalFormatProperties setMinimumExponentDigits(int minimumExponentDigits) {
924         this.minimumExponentDigits = minimumExponentDigits;
925         return this;
926     }
927 
928     /**
929      * Sets the minimum number of digits to display after the decimal point. If the number has fewer than
930      * this number of digits, the number will be padded with zeros. The pattern "#00.0#", for example,
931      * corresponds to 1 minimum fraction digit, and the number 456 would be formatted as "456.0" in
932      * locale <em>en-US</em>.
933      *
934      * @param minimumFractionDigits
935      *            The minimum number of fraction digits to output.
936      * @return The property bag, for chaining.
937      */
setMinimumFractionDigits(int minimumFractionDigits)938     public DecimalFormatProperties setMinimumFractionDigits(int minimumFractionDigits) {
939         this.minimumFractionDigits = minimumFractionDigits;
940         return this;
941     }
942 
943     /**
944      * Sets the minimum number of digits required to be beyond the first grouping separator in order to
945      * enable grouping. For example, if the minimum grouping digits is 2, then 1234 would be formatted as
946      * "1234" but 12345 would be formatted as "12,345" in <em>en-US</em>. Note that 1234567 would still
947      * be formatted as "1,234,567", not "1234,567".
948      *
949      * @param minimumGroupingDigits
950      *            How many digits must appear before a grouping separator before enabling grouping.
951      * @return The property bag, for chaining.
952      */
setMinimumGroupingDigits(int minimumGroupingDigits)953     public DecimalFormatProperties setMinimumGroupingDigits(int minimumGroupingDigits) {
954         this.minimumGroupingDigits = minimumGroupingDigits;
955         return this;
956     }
957 
958     /**
959      * Sets the minimum number of digits to display before the decimal point. If the number has fewer
960      * than this number of digits, the number will be padded with zeros. The pattern "#00.0#", for
961      * example, corresponds to 2 minimum integer digits, and the number 5.3 would be formatted as "05.3"
962      * in locale <em>en-US</em>.
963      *
964      * @param minimumIntegerDigits
965      *            The minimum number of integer digits to output.
966      * @return The property bag, for chaining.
967      */
setMinimumIntegerDigits(int minimumIntegerDigits)968     public DecimalFormatProperties setMinimumIntegerDigits(int minimumIntegerDigits) {
969         this.minimumIntegerDigits = minimumIntegerDigits;
970         return this;
971     }
972 
973     /**
974      * Sets the minimum number of significant digits to display. If, after rounding to the number of
975      * significant digits specified by {@link #setMaximumSignificantDigits}, the number of remaining
976      * significant digits is less than the minimum, the number will be padded with zeros. For example, if
977      * minimum significant digits is 3, the number 5.8 will be formatted as "5.80" in locale
978      * <em>en-US</em>. Note that minimum significant digits is relevant only when numbers have digits
979      * after the decimal point.
980      *
981      * <p>
982      * If both minimum significant digits and minimum integer/fraction digits are set at the same time,
983      * both values will be respected, and the one that results in the greater number of padding zeros
984      * will be used. For example, formatting the number 73 with 3 minimum significant digits and 2
985      * minimum fraction digits will produce "73.00".
986      *
987      * <p>
988      * The number of significant digits can be specified in a pattern string using the '@' character. For
989      * example, the pattern "@@#" corresponds to a minimum of 2 and a maximum of 3 significant digits.
990      *
991      * @param minimumSignificantDigits
992      *            The minimum number of significant digits to display.
993      * @return The property bag, for chaining.
994      */
setMinimumSignificantDigits(int minimumSignificantDigits)995     public DecimalFormatProperties setMinimumSignificantDigits(int minimumSignificantDigits) {
996         this.minimumSignificantDigits = minimumSignificantDigits;
997         return this;
998     }
999 
1000     /**
1001      * Multiply all numbers by this amount before formatting.
1002      *
1003      * @param multiplier
1004      *            The amount to multiply by.
1005      * @return The property bag, for chaining.
1006      * @see #setMagnitudeMultiplier
1007      */
setMultiplier(BigDecimal multiplier)1008     public DecimalFormatProperties setMultiplier(BigDecimal multiplier) {
1009         this.multiplier = multiplier;
1010         return this;
1011     }
1012 
1013     /**
1014      * Sets the prefix to prepend to negative numbers. The prefix will be interpreted literally. For
1015      * example, if you set a negative prefix of <code>n</code>, then the number -123 will be formatted as
1016      * "n123" in the locale <em>en-US</em>. Note that if the negative prefix is left unset, the locale's
1017      * minus sign is used.
1018      *
1019      * <p>
1020      * For more information on prefixes and suffixes, see {@link MutablePatternModifier}.
1021      *
1022      * @param negativePrefix
1023      *            The CharSequence to prepend to negative numbers.
1024      * @return The property bag, for chaining.
1025      * @see #setNegativePrefixPattern
1026      */
setNegativePrefix(String negativePrefix)1027     public DecimalFormatProperties setNegativePrefix(String negativePrefix) {
1028         this.negativePrefix = negativePrefix;
1029         return this;
1030     }
1031 
1032     /**
1033      * Sets the prefix to prepend to negative numbers. Locale-specific symbols will be substituted into
1034      * the string according to Unicode Technical Standard #35 (LDML).
1035      *
1036      * <p>
1037      * For more information on prefixes and suffixes, see {@link MutablePatternModifier}.
1038      *
1039      * @param negativePrefixPattern
1040      *            The CharSequence to prepend to negative numbers after locale symbol substitutions take
1041      *            place.
1042      * @return The property bag, for chaining.
1043      * @see #setNegativePrefix
1044      */
setNegativePrefixPattern(String negativePrefixPattern)1045     public DecimalFormatProperties setNegativePrefixPattern(String negativePrefixPattern) {
1046         this.negativePrefixPattern = negativePrefixPattern;
1047         return this;
1048     }
1049 
1050     /**
1051      * Sets the suffix to append to negative numbers. The suffix will be interpreted literally. For
1052      * example, if you set a suffix prefix of <code>n</code>, then the number -123 will be formatted as
1053      * "-123n" in the locale <em>en-US</em>. Note that the minus sign is prepended by default unless
1054      * otherwise specified in either the pattern string or in one of the {@link #setNegativePrefix}
1055      * methods.
1056      *
1057      * <p>
1058      * For more information on prefixes and suffixes, see {@link MutablePatternModifier}.
1059      *
1060      * @param negativeSuffix
1061      *            The CharSequence to append to negative numbers.
1062      * @return The property bag, for chaining.
1063      * @see #setNegativeSuffixPattern
1064      */
setNegativeSuffix(String negativeSuffix)1065     public DecimalFormatProperties setNegativeSuffix(String negativeSuffix) {
1066         this.negativeSuffix = negativeSuffix;
1067         return this;
1068     }
1069 
1070     /**
1071      * Sets the suffix to append to negative numbers. Locale-specific symbols will be substituted into
1072      * the string according to Unicode Technical Standard #35 (LDML).
1073      *
1074      * <p>
1075      * For more information on prefixes and suffixes, see {@link MutablePatternModifier}.
1076      *
1077      * @param negativeSuffixPattern
1078      *            The CharSequence to append to negative numbers after locale symbol substitutions take
1079      *            place.
1080      * @return The property bag, for chaining.
1081      * @see #setNegativeSuffix
1082      */
setNegativeSuffixPattern(String negativeSuffixPattern)1083     public DecimalFormatProperties setNegativeSuffixPattern(String negativeSuffixPattern) {
1084         this.negativeSuffixPattern = negativeSuffixPattern;
1085         return this;
1086     }
1087 
1088     /**
1089      * Sets the location where the padding string is to be inserted to maintain the padding width: one of
1090      * BEFORE_PREFIX, AFTER_PREFIX, BEFORE_SUFFIX, or AFTER_SUFFIX.
1091      *
1092      * <p>
1093      * Must be used in conjunction with {@link #setFormatWidth}.
1094      *
1095      * @param paddingLocation
1096      *            The output width.
1097      * @return The property bag, for chaining.
1098      * @see #setFormatWidth
1099      */
setPadPosition(PadPosition paddingLocation)1100     public DecimalFormatProperties setPadPosition(PadPosition paddingLocation) {
1101         this.padPosition = paddingLocation;
1102         return this;
1103     }
1104 
1105     /**
1106      * Sets the string used for padding. The string should contain a single character or grapheme
1107      * cluster.
1108      *
1109      * <p>
1110      * Must be used in conjunction with {@link #setFormatWidth}.
1111      *
1112      * @param paddingString
1113      *            The padding string. Defaults to an ASCII space (U+0020).
1114      * @return The property bag, for chaining.
1115      * @see #setFormatWidth
1116      */
setPadString(String paddingString)1117     public DecimalFormatProperties setPadString(String paddingString) {
1118         this.padString = paddingString;
1119         return this;
1120     }
1121 
1122     /**
1123      * Whether to require cases to match when parsing strings; default is true. Case sensitivity applies
1124      * to prefixes, suffixes, the exponent separator, the symbol "NaN", and the infinity symbol. Grouping
1125      * separators, decimal separators, and padding are always case-sensitive. Currencies are always
1126      * case-insensitive.
1127      *
1128      * <p>
1129      * This setting is ignored in fast mode. In fast mode, strings are always compared in a
1130      * case-sensitive way.
1131      *
1132      * @param parseCaseSensitive
1133      *            true to be case-sensitive when parsing; false to allow any case.
1134      * @return The property bag, for chaining.
1135      */
setParseCaseSensitive(boolean parseCaseSensitive)1136     public DecimalFormatProperties setParseCaseSensitive(boolean parseCaseSensitive) {
1137         this.parseCaseSensitive = parseCaseSensitive;
1138         return this;
1139     }
1140 
1141     /**
1142      * Whether to ignore the fractional part of numbers. For example, parses "123.4" to "123" instead of
1143      * "123.4".
1144      *
1145      * @param parseIntegerOnly
1146      *            true to parse integers only; false to parse integers with their fraction parts
1147      * @return The property bag, for chaining.
1148      */
setParseIntegerOnly(boolean parseIntegerOnly)1149     public DecimalFormatProperties setParseIntegerOnly(boolean parseIntegerOnly) {
1150         this.parseIntegerOnly = parseIntegerOnly;
1151         return this;
1152     }
1153 
1154     /**
1155      * Controls certain rules for how strict this parser is when reading strings. See
1156      * {@link ParseMode#LENIENT} and {@link ParseMode#STRICT}.
1157      *
1158      * @param parseMode
1159      *            Either {@link ParseMode#LENIENT} or {@link ParseMode#STRICT}.
1160      * @return The property bag, for chaining.
1161      */
setParseMode(ParseMode parseMode)1162     public DecimalFormatProperties setParseMode(ParseMode parseMode) {
1163         this.parseMode = parseMode;
1164         return this;
1165     }
1166 
1167     /**
1168      * Whether to ignore the exponential part of numbers. For example, parses "123E4" to "123" instead of
1169      * "1230000".
1170      *
1171      * @param parseNoExponent
1172      *            true to ignore exponents; false to parse them.
1173      * @return The property bag, for chaining.
1174      */
setParseNoExponent(boolean parseNoExponent)1175     public DecimalFormatProperties setParseNoExponent(boolean parseNoExponent) {
1176         this.parseNoExponent = parseNoExponent;
1177         return this;
1178     }
1179 
1180     /**
1181      * Whether to always return a BigDecimal from parse methods. By default, a Long or a BigInteger are
1182      * returned when possible.
1183      *
1184      * @param parseToBigDecimal
1185      *            true to always return a BigDecimal; false to return a Long or a BigInteger when
1186      *            possible.
1187      * @return The property bag, for chaining.
1188      */
setParseToBigDecimal(boolean parseToBigDecimal)1189     public DecimalFormatProperties setParseToBigDecimal(boolean parseToBigDecimal) {
1190         this.parseToBigDecimal = parseToBigDecimal;
1191         return this;
1192     }
1193 
1194     /**
1195      * Sets the PluralRules object to use instead of the default for the locale.
1196      *
1197      * @param pluralRules
1198      *            The object to reference.
1199      * @return The property bag, for chaining.
1200      */
setPluralRules(PluralRules pluralRules)1201     public DecimalFormatProperties setPluralRules(PluralRules pluralRules) {
1202         this.pluralRules = pluralRules;
1203         return this;
1204     }
1205 
1206     /**
1207      * Sets the prefix to prepend to positive numbers. The prefix will be interpreted literally. For
1208      * example, if you set a positive prefix of <code>p</code>, then the number 123 will be formatted as
1209      * "p123" in the locale <em>en-US</em>.
1210      *
1211      * <p>
1212      * For more information on prefixes and suffixes, see {@link MutablePatternModifier}.
1213      *
1214      * @param positivePrefix
1215      *            The CharSequence to prepend to positive numbers.
1216      * @return The property bag, for chaining.
1217      * @see #setPositivePrefixPattern
1218      */
setPositivePrefix(String positivePrefix)1219     public DecimalFormatProperties setPositivePrefix(String positivePrefix) {
1220         this.positivePrefix = positivePrefix;
1221         return this;
1222     }
1223 
1224     /**
1225      * Sets the prefix to prepend to positive numbers. Locale-specific symbols will be substituted into
1226      * the string according to Unicode Technical Standard #35 (LDML).
1227      *
1228      * <p>
1229      * For more information on prefixes and suffixes, see {@link MutablePatternModifier}.
1230      *
1231      * @param positivePrefixPattern
1232      *            The CharSequence to prepend to positive numbers after locale symbol substitutions take
1233      *            place.
1234      * @return The property bag, for chaining.
1235      * @see #setPositivePrefix
1236      */
setPositivePrefixPattern(String positivePrefixPattern)1237     public DecimalFormatProperties setPositivePrefixPattern(String positivePrefixPattern) {
1238         this.positivePrefixPattern = positivePrefixPattern;
1239         return this;
1240     }
1241 
1242     /**
1243      * Sets the suffix to append to positive numbers. The suffix will be interpreted literally. For
1244      * example, if you set a positive suffix of <code>p</code>, then the number 123 will be formatted as
1245      * "123p" in the locale <em>en-US</em>.
1246      *
1247      * <p>
1248      * For more information on prefixes and suffixes, see {@link MutablePatternModifier}.
1249      *
1250      * @param positiveSuffix
1251      *            The CharSequence to append to positive numbers.
1252      * @return The property bag, for chaining.
1253      * @see #setPositiveSuffixPattern
1254      */
setPositiveSuffix(String positiveSuffix)1255     public DecimalFormatProperties setPositiveSuffix(String positiveSuffix) {
1256         this.positiveSuffix = positiveSuffix;
1257         return this;
1258     }
1259 
1260     /**
1261      * Sets the suffix to append to positive numbers. Locale-specific symbols will be substituted into
1262      * the string according to Unicode Technical Standard #35 (LDML).
1263      *
1264      * <p>
1265      * For more information on prefixes and suffixes, see {@link MutablePatternModifier}.
1266      *
1267      * @param positiveSuffixPattern
1268      *            The CharSequence to append to positive numbers after locale symbol substitutions take
1269      *            place.
1270      * @return The property bag, for chaining.
1271      * @see #setPositiveSuffix
1272      */
setPositiveSuffixPattern(String positiveSuffixPattern)1273     public DecimalFormatProperties setPositiveSuffixPattern(String positiveSuffixPattern) {
1274         this.positiveSuffixPattern = positiveSuffixPattern;
1275         return this;
1276     }
1277 
1278     /**
1279      * Sets the increment to which to round numbers. For example, with a rounding interval of 0.05, the
1280      * number 11.17 would be formatted as "11.15" in locale <em>en-US</em> with the default rounding
1281      * mode.
1282      *
1283      * <p>
1284      * You can use either a rounding increment or significant digits, but not both at the same time.
1285      *
1286      * <p>
1287      * The rounding increment can be specified in a pattern string. For example, the pattern "#,##0.05"
1288      * corresponds to a rounding interval of 0.05 with 1 minimum integer digit and a grouping size of 3.
1289      *
1290      * @param roundingIncrement
1291      *            The interval to which to round.
1292      * @return The property bag, for chaining.
1293      */
setRoundingIncrement(BigDecimal roundingIncrement)1294     public DecimalFormatProperties setRoundingIncrement(BigDecimal roundingIncrement) {
1295         this.roundingIncrement = roundingIncrement;
1296         return this;
1297     }
1298 
1299     /**
1300      * Sets the rounding mode, which determines under which conditions extra decimal places are rounded
1301      * either up or down. See {@link RoundingMode} for details on the choices of rounding mode. The
1302      * default if not set explicitly is {@link RoundingMode#HALF_EVEN}.
1303      *
1304      * <p>
1305      * This setting is ignored if {@link #setMathContext} is used.
1306      *
1307      * @param roundingMode
1308      *            The rounding mode to use when rounding is required.
1309      * @return The property bag, for chaining.
1310      * @see RoundingMode
1311      * @see #setMathContext
1312      */
setRoundingMode(RoundingMode roundingMode)1313     public DecimalFormatProperties setRoundingMode(RoundingMode roundingMode) {
1314         this.roundingMode = roundingMode;
1315         return this;
1316     }
1317 
1318     /**
1319      * Sets the number of digits between grouping separators higher than the least-significant grouping
1320      * separator. For example, the locale <em>hi</em> uses a primary grouping size of 3 and a secondary
1321      * grouping size of 2, so the number 1234567 would be formatted as "12,34,567".
1322      *
1323      * <p>
1324      * The two levels of grouping separators can be specified in the pattern string. For example, the
1325      * <em>hi</em> locale's default decimal format pattern is "#,##,##0.###".
1326      *
1327      * @param secondaryGroupingSize
1328      *            The secondary grouping size.
1329      * @return The property bag, for chaining.
1330      */
setSecondaryGroupingSize(int secondaryGroupingSize)1331     public DecimalFormatProperties setSecondaryGroupingSize(int secondaryGroupingSize) {
1332         this.secondaryGroupingSize = secondaryGroupingSize;
1333         return this;
1334     }
1335 
1336     /**
1337      * Sets whether to always display of a plus sign on positive numbers.
1338      *
1339      * <p>
1340      * If the location of the negative sign is specified by the decimal format pattern (or by the
1341      * negative prefix/suffix pattern methods), a plus sign is substituted into that location, in
1342      * accordance with Unicode Technical Standard #35 (LDML) section 3.2.1. Otherwise, the plus sign is
1343      * prepended to the number. For example, if the decimal format pattern <code>#;#-</code> is used,
1344      * then formatting 123 would result in "123+" in the locale <em>en-US</em>.
1345      *
1346      * <p>
1347      * This method should be used <em>instead of</em> setting the positive prefix/suffix. The behavior is
1348      * undefined if alwaysShowPlusSign is set but the positive prefix/suffix already contains a plus
1349      * sign.
1350      *
1351      * @param signAlwaysShown
1352      *            Whether positive numbers should display a plus sign.
1353      * @return The property bag, for chaining.
1354      */
setSignAlwaysShown(boolean signAlwaysShown)1355     public DecimalFormatProperties setSignAlwaysShown(boolean signAlwaysShown) {
1356         this.signAlwaysShown = signAlwaysShown;
1357         return this;
1358     }
1359 
1360     @Override
toString()1361     public String toString() {
1362         StringBuilder result = new StringBuilder();
1363         result.append("<Properties");
1364         toStringBare(result);
1365         result.append(">");
1366         return result.toString();
1367     }
1368 
1369     /**
1370      * Appends a string containing properties that differ from the default, but without being surrounded
1371      * by &lt;Properties&gt;.
1372      */
toStringBare(StringBuilder result)1373     public void toStringBare(StringBuilder result) {
1374         Field[] fields = DecimalFormatProperties.class.getDeclaredFields();
1375         for (Field field : fields) {
1376             Object myValue, defaultValue;
1377             try {
1378                 myValue = field.get(this);
1379                 defaultValue = field.get(DEFAULT);
1380             } catch (IllegalArgumentException e) {
1381                 e.printStackTrace();
1382                 continue;
1383             } catch (IllegalAccessException e) {
1384                 e.printStackTrace();
1385                 continue;
1386             }
1387             if (myValue == null && defaultValue == null) {
1388                 continue;
1389             } else if (myValue == null || defaultValue == null) {
1390                 result.append(" " + field.getName() + ":" + myValue);
1391             } else if (!myValue.equals(defaultValue)) {
1392                 result.append(" " + field.getName() + ":" + myValue);
1393             }
1394         }
1395     }
1396 
1397     /**
1398      * Custom serialization: save fields along with their name, so that fields can be easily added in the
1399      * future in any order. Only save fields that differ from their default value.
1400      */
writeObject(ObjectOutputStream oos)1401     private void writeObject(ObjectOutputStream oos) throws IOException {
1402         writeObjectImpl(oos);
1403     }
1404 
writeObjectImpl(ObjectOutputStream oos)1405     /* package-private */ void writeObjectImpl(ObjectOutputStream oos) throws IOException {
1406         oos.defaultWriteObject();
1407 
1408         // Extra int for possible future use
1409         oos.writeInt(0);
1410 
1411         ArrayList<Field> fieldsToSerialize = new ArrayList<>();
1412         ArrayList<Object> valuesToSerialize = new ArrayList<>();
1413         Field[] fields = DecimalFormatProperties.class.getDeclaredFields();
1414         for (Field field : fields) {
1415             if (Modifier.isStatic(field.getModifiers())) {
1416                 continue;
1417             }
1418             try {
1419                 Object myValue = field.get(this);
1420                 if (myValue == null) {
1421                     // All *Object* values default to null; no need to serialize.
1422                     continue;
1423                 }
1424                 Object defaultValue = field.get(DEFAULT);
1425                 if (!myValue.equals(defaultValue)) {
1426                     fieldsToSerialize.add(field);
1427                     valuesToSerialize.add(myValue);
1428                 }
1429             } catch (IllegalArgumentException e) {
1430                 // Should not happen
1431                 throw new AssertionError(e);
1432             } catch (IllegalAccessException e) {
1433                 // Should not happen
1434                 throw new AssertionError(e);
1435             }
1436         }
1437 
1438         // 1) How many fields are to be serialized?
1439         int count = fieldsToSerialize.size();
1440         oos.writeInt(count);
1441 
1442         // 2) Write each field with its name and value
1443         for (int i = 0; i < count; i++) {
1444             Field field = fieldsToSerialize.get(i);
1445             Object value = valuesToSerialize.get(i);
1446             oos.writeObject(field.getName());
1447             oos.writeObject(value);
1448         }
1449     }
1450 }
1451