1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This code is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License version 2 only, as
8  * published by the Free Software Foundation.  Oracle designates this
9  * particular file as subject to the "Classpath" exception as provided
10  * by Oracle in the LICENSE file that accompanied this code.
11  *
12  * This code is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15  * version 2 for more details (a copy is included in the LICENSE file that
16  * accompanied this code).
17  *
18  * You should have received a copy of the GNU General Public License version
19  * 2 along with this work; if not, write to the Free Software Foundation,
20  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21  *
22  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23  * or visit www.oracle.com if you need additional information or have any
24  * questions.
25  */
26 
27 /*
28  * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
29  * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
30  *
31  *   The original version of this source code and documentation is copyrighted
32  * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
33  * materials are provided under terms of a License Agreement between Taligent
34  * and Sun. This technology is protected by multiple US and International
35  * patents. This notice and attribution to Taligent may not be removed.
36  *   Taligent is a registered trademark of Taligent, Inc.
37  *
38  */
39 
40 package java.text;
41 
42 import java.io.IOException;
43 import java.io.ObjectInputStream;
44 import java.io.ObjectOutputStream;
45 import java.io.ObjectStreamField;
46 import java.math.BigDecimal;
47 import java.math.BigInteger;
48 import java.math.RoundingMode;
49 import java.util.Currency;
50 import java.util.Locale;
51 import java.util.concurrent.ConcurrentHashMap;
52 import java.util.concurrent.ConcurrentMap;
53 import java.util.concurrent.atomic.AtomicInteger;
54 import java.util.concurrent.atomic.AtomicLong;
55 import libcore.icu.LocaleData;
56 
57 import android.icu.math.MathContext;
58 
59 /**
60  * <code>DecimalFormat</code> is a concrete subclass of
61  * <code>NumberFormat</code> that formats decimal numbers. It has a variety of
62  * features designed to make it possible to parse and format numbers in any
63  * locale, including support for Western, Arabic, and Indic digits.  It also
64  * supports different kinds of numbers, including integers (123), fixed-point
65  * numbers (123.4), scientific notation (1.23E4), percentages (12%), and
66  * currency amounts ($123).  All of these can be localized.
67  *
68  * <p>To obtain a <code>NumberFormat</code> for a specific locale, including the
69  * default locale, call one of <code>NumberFormat</code>'s factory methods, such
70  * as <code>getInstance()</code>.  In general, do not call the
71  * <code>DecimalFormat</code> constructors directly, since the
72  * <code>NumberFormat</code> factory methods may return subclasses other than
73  * <code>DecimalFormat</code>. If you need to customize the format object, do
74  * something like this:
75  *
76  * <blockquote><pre>
77  * NumberFormat f = NumberFormat.getInstance(loc);
78  * if (f instanceof DecimalFormat) {
79  *     ((DecimalFormat) f).setDecimalSeparatorAlwaysShown(true);
80  * }
81  * </pre></blockquote>
82  *
83  * <p>A <code>DecimalFormat</code> comprises a <em>pattern</em> and a set of
84  * <em>symbols</em>.  The pattern may be set directly using
85  * <code>applyPattern()</code>, or indirectly using the API methods.  The
86  * symbols are stored in a <code>DecimalFormatSymbols</code> object.  When using
87  * the <code>NumberFormat</code> factory methods, the pattern and symbols are
88  * read from localized <code>ResourceBundle</code>s.
89  *
90  * <h3>Patterns</h3>
91  *
92  * <code>DecimalFormat</code> patterns have the following syntax:
93  * <blockquote><pre>
94  * <i>Pattern:</i>
95  *         <i>PositivePattern</i>
96  *         <i>PositivePattern</i> ; <i>NegativePattern</i>
97  * <i>PositivePattern:</i>
98  *         <i>Prefix<sub>opt</sub></i> <i>Number</i> <i>Suffix<sub>opt</sub></i>
99  * <i>NegativePattern:</i>
100  *         <i>Prefix<sub>opt</sub></i> <i>Number</i> <i>Suffix<sub>opt</sub></i>
101  * <i>Prefix:</i>
102  *         any Unicode characters except &#92;uFFFE, &#92;uFFFF, and special characters
103  * <i>Suffix:</i>
104  *         any Unicode characters except &#92;uFFFE, &#92;uFFFF, and special characters
105  * <i>Number:</i>
106  *         <i>Integer</i> <i>Exponent<sub>opt</sub></i>
107  *         <i>Integer</i> . <i>Fraction</i> <i>Exponent<sub>opt</sub></i>
108  * <i>Integer:</i>
109  *         <i>MinimumInteger</i>
110  *         #
111  *         # <i>Integer</i>
112  *         # , <i>Integer</i>
113  * <i>MinimumInteger:</i>
114  *         0
115  *         0 <i>MinimumInteger</i>
116  *         0 , <i>MinimumInteger</i>
117  * <i>Fraction:</i>
118  *         <i>MinimumFraction<sub>opt</sub></i> <i>OptionalFraction<sub>opt</sub></i>
119  * <i>MinimumFraction:</i>
120  *         0 <i>MinimumFraction<sub>opt</sub></i>
121  * <i>OptionalFraction:</i>
122  *         # <i>OptionalFraction<sub>opt</sub></i>
123  * <i>Exponent:</i>
124  *         E <i>MinimumExponent</i>
125  * <i>MinimumExponent:</i>
126  *         0 <i>MinimumExponent<sub>opt</sub></i>
127  * </pre></blockquote>
128  *
129  * <p>A <code>DecimalFormat</code> pattern contains a positive and negative
130  * subpattern, for example, <code>"#,##0.00;(#,##0.00)"</code>.  Each
131  * subpattern has a prefix, numeric part, and suffix. The negative subpattern
132  * is optional; if absent, then the positive subpattern prefixed with the
133  * localized minus sign (<code>'-'</code> in most locales) is used as the
134  * negative subpattern. That is, <code>"0.00"</code> alone is equivalent to
135  * <code>"0.00;-0.00"</code>.  If there is an explicit negative subpattern, it
136  * serves only to specify the negative prefix and suffix; the number of digits,
137  * minimal digits, and other characteristics are all the same as the positive
138  * pattern. That means that <code>"#,##0.0#;(#)"</code> produces precisely
139  * the same behavior as <code>"#,##0.0#;(#,##0.0#)"</code>.
140  *
141  * <p>The prefixes, suffixes, and various symbols used for infinity, digits,
142  * thousands separators, decimal separators, etc. may be set to arbitrary
143  * values, and they will appear properly during formatting.  However, care must
144  * be taken that the symbols and strings do not conflict, or parsing will be
145  * unreliable.  For example, either the positive and negative prefixes or the
146  * suffixes must be distinct for <code>DecimalFormat.parse()</code> to be able
147  * to distinguish positive from negative values.  (If they are identical, then
148  * <code>DecimalFormat</code> will behave as if no negative subpattern was
149  * specified.)  Another example is that the decimal separator and thousands
150  * separator should be distinct characters, or parsing will be impossible.
151  *
152  * <p>The grouping separator is commonly used for thousands, but in some
153  * countries it separates ten-thousands. The grouping size is a constant number
154  * of digits between the grouping characters, such as 3 for 100,000,000 or 4 for
155  * 1,0000,0000.  If you supply a pattern with multiple grouping characters, the
156  * interval between the last one and the end of the integer is the one that is
157  * used. So <code>"#,##,###,####"</code> == <code>"######,####"</code> ==
158  * <code>"##,####,####"</code>.
159  *
160  * <h4>Special Pattern Characters</h4>
161  *
162  * <p>Many characters in a pattern are taken literally; they are matched during
163  * parsing and output unchanged during formatting.  Special characters, on the
164  * other hand, stand for other characters, strings, or classes of characters.
165  * They must be quoted, unless noted otherwise, if they are to appear in the
166  * prefix or suffix as literals.
167  *
168  * <p>The characters listed here are used in non-localized patterns.  Localized
169  * patterns use the corresponding characters taken from this formatter's
170  * <code>DecimalFormatSymbols</code> object instead, and these characters lose
171  * their special status.  Two exceptions are the currency sign and quote, which
172  * are not localized.
173  *
174  * <blockquote>
175  * <table border=0 cellspacing=3 cellpadding=0 summary="Chart showing symbol,
176  *  location, localized, and meaning.">
177  *     <tr style="background-color: rgb(204, 204, 255);">
178  *          <th align=left>Symbol
179  *          <th align=left>Location
180  *          <th align=left>Localized?
181  *          <th align=left>Meaning
182  *     <tr valign=top>
183  *          <td><code>0</code>
184  *          <td>Number
185  *          <td>Yes
186  *          <td>Digit
187  *     <tr style="vertical-align: top; background-color: rgb(238, 238, 255);">
188  *          <td><code>#</code>
189  *          <td>Number
190  *          <td>Yes
191  *          <td>Digit, zero shows as absent
192  *     <tr valign=top>
193  *          <td><code>.</code>
194  *          <td>Number
195  *          <td>Yes
196  *          <td>Decimal separator or monetary decimal separator
197  *     <tr style="vertical-align: top; background-color: rgb(238, 238, 255);">
198  *          <td><code>-</code>
199  *          <td>Number
200  *          <td>Yes
201  *          <td>Minus sign
202  *     <tr valign=top>
203  *          <td><code>,</code>
204  *          <td>Number
205  *          <td>Yes
206  *          <td>Grouping separator
207  *     <tr style="vertical-align: top; background-color: rgb(238, 238, 255);">
208  *          <td><code>E</code>
209  *          <td>Number
210  *          <td>Yes
211  *          <td>Separates mantissa and exponent in scientific notation.
212  *              <em>Need not be quoted in prefix or suffix.</em>
213  *     <tr valign=top>
214  *          <td><code>;</code>
215  *          <td>Subpattern boundary
216  *          <td>Yes
217  *          <td>Separates positive and negative subpatterns
218  *     <tr style="vertical-align: top; background-color: rgb(238, 238, 255);">
219  *          <td><code>%</code>
220  *          <td>Prefix or suffix
221  *          <td>Yes
222  *          <td>Multiply by 100 and show as percentage
223  *     <tr valign=top>
224  *          <td><code>&#92;u2030</code>
225  *          <td>Prefix or suffix
226  *          <td>Yes
227  *          <td>Multiply by 1000 and show as per mille value
228  *     <tr style="vertical-align: top; background-color: rgb(238, 238, 255);">
229  *          <td><code>&#164;</code> (<code>&#92;u00A4</code>)
230  *          <td>Prefix or suffix
231  *          <td>No
232  *          <td>Currency sign, replaced by currency symbol.  If
233  *              doubled, replaced by international currency symbol.
234  *              If present in a pattern, the monetary decimal separator
235  *              is used instead of the decimal separator.
236  *     <tr valign=top>
237  *          <td><code>'</code>
238  *          <td>Prefix or suffix
239  *          <td>No
240  *          <td>Used to quote special characters in a prefix or suffix,
241  *              for example, <code>"'#'#"</code> formats 123 to
242  *              <code>"#123"</code>.  To create a single quote
243  *              itself, use two in a row: <code>"# o''clock"</code>.
244  * </table>
245  * </blockquote>
246  *
247  * <h4>Scientific Notation</h4>
248  *
249  * <p>Numbers in scientific notation are expressed as the product of a mantissa
250  * and a power of ten, for example, 1234 can be expressed as 1.234 x 10^3.  The
251  * mantissa is often in the range 1.0 &le; x {@literal <} 10.0, but it need not
252  * be.
253  * <code>DecimalFormat</code> can be instructed to format and parse scientific
254  * notation <em>only via a pattern</em>; there is currently no factory method
255  * that creates a scientific notation format.  In a pattern, the exponent
256  * character immediately followed by one or more digit characters indicates
257  * scientific notation.  Example: <code>"0.###E0"</code> formats the number
258  * 1234 as <code>"1.234E3"</code>.
259  *
260  * <ul>
261  * <li>The number of digit characters after the exponent character gives the
262  * minimum exponent digit count.  There is no maximum.  Negative exponents are
263  * formatted using the localized minus sign, <em>not</em> the prefix and suffix
264  * from the pattern.  This allows patterns such as <code>"0.###E0 m/s"</code>.
265  *
266  * <li>The minimum and maximum number of integer digits are interpreted
267  * together:
268  *
269  * <ul>
270  * <li>If the maximum number of integer digits is greater than their minimum number
271  * and greater than 1, it forces the exponent to be a multiple of the maximum
272  * number of integer digits, and the minimum number of integer digits to be
273  * interpreted as 1.  The most common use of this is to generate
274  * <em>engineering notation</em>, in which the exponent is a multiple of three,
275  * e.g., <code>"##0.#####E0"</code>. Using this pattern, the number 12345
276  * formats to <code>"12.345E3"</code>, and 123456 formats to
277  * <code>"123.456E3"</code>.
278  *
279  * <li>Otherwise, the minimum number of integer digits is achieved by adjusting the
280  * exponent.  Example: 0.00123 formatted with <code>"00.###E0"</code> yields
281  * <code>"12.3E-4"</code>.
282  * </ul>
283  *
284  * <li>The number of significant digits in the mantissa is the sum of the
285  * <em>minimum integer</em> and <em>maximum fraction</em> digits, and is
286  * unaffected by the maximum integer digits.  For example, 12345 formatted with
287  * <code>"##0.##E0"</code> is <code>"12.3E3"</code>. To show all digits, set
288  * the significant digits count to zero.  The number of significant digits
289  * does not affect parsing.
290  *
291  * <li>Exponential patterns may not contain grouping separators.
292  * </ul>
293  *
294  * <h4>Rounding</h4>
295  *
296  * <code>DecimalFormat</code> provides rounding modes defined in
297  * {@link java.math.RoundingMode} for formatting.  By default, it uses
298  * {@link java.math.RoundingMode#HALF_EVEN RoundingMode.HALF_EVEN}.
299  *
300  * <h4>Digits</h4>
301  *
302  * For formatting, <code>DecimalFormat</code> uses the ten consecutive
303  * characters starting with the localized zero digit defined in the
304  * <code>DecimalFormatSymbols</code> object as digits. For parsing, these
305  * digits as well as all Unicode decimal digits, as defined by
306  * {@link Character#digit Character.digit}, are recognized.
307  *
308  * <h4>Special Values</h4>
309  *
310  * <p><code>NaN</code> is formatted as a string, which typically has a single character
311  * <code>&#92;uFFFD</code>.  This string is determined by the
312  * <code>DecimalFormatSymbols</code> object.  This is the only value for which
313  * the prefixes and suffixes are not used.
314  *
315  * <p>Infinity is formatted as a string, which typically has a single character
316  * <code>&#92;u221E</code>, with the positive or negative prefixes and suffixes
317  * applied.  The infinity string is determined by the
318  * <code>DecimalFormatSymbols</code> object.
319  *
320  * <p>Negative zero (<code>"-0"</code>) parses to
321  * <ul>
322  * <li><code>BigDecimal(0)</code> if <code>isParseBigDecimal()</code> is
323  * true,
324  * <li><code>Long(0)</code> if <code>isParseBigDecimal()</code> is false
325  *     and <code>isParseIntegerOnly()</code> is true,
326  * <li><code>Double(-0.0)</code> if both <code>isParseBigDecimal()</code>
327  * and <code>isParseIntegerOnly()</code> are false.
328  * </ul>
329  *
330  * <h4><a name="synchronization">Synchronization</a></h4>
331  *
332  * <p>
333  * Decimal formats are generally not synchronized.
334  * It is recommended to create separate format instances for each thread.
335  * If multiple threads access a format concurrently, it must be synchronized
336  * externally.
337  *
338  * <h4>Example</h4>
339  *
340  * <blockquote><pre>{@code
341  * <strong>// Print out a number using the localized number, integer, currency,
342  * // and percent format for each locale</strong>
343  * Locale[] locales = NumberFormat.getAvailableLocales();
344  * double myNumber = -1234.56;
345  * NumberFormat form;
346  * for (int j = 0; j < 4; ++j) {
347  *     System.out.println("FORMAT");
348  *     for (int i = 0; i < locales.length; ++i) {
349  *         if (locales[i].getCountry().length() == 0) {
350  *            continue; // Skip language-only locales
351  *         }
352  *         System.out.print(locales[i].getDisplayName());
353  *         switch (j) {
354  *         case 0:
355  *             form = NumberFormat.getInstance(locales[i]); break;
356  *         case 1:
357  *             form = NumberFormat.getIntegerInstance(locales[i]); break;
358  *         case 2:
359  *             form = NumberFormat.getCurrencyInstance(locales[i]); break;
360  *         default:
361  *             form = NumberFormat.getPercentInstance(locales[i]); break;
362  *         }
363  *         if (form instanceof DecimalFormat) {
364  *             System.out.print(": " + ((DecimalFormat) form).toPattern());
365  *         }
366  *         System.out.print(" -> " + form.format(myNumber));
367  *         try {
368  *             System.out.println(" -> " + form.parse(form.format(myNumber)));
369  *         } catch (ParseException e) {}
370  *     }
371  * }
372  * }</pre></blockquote>
373  *
374  * @see          <a href="https://docs.oracle.com/javase/tutorial/i18n/format/decimalFormat.html">Java Tutorial</a>
375  * @see          NumberFormat
376  * @see          DecimalFormatSymbols
377  * @see          ParsePosition
378  * @author       Mark Davis
379  * @author       Alan Liu
380  */
381 public class DecimalFormat extends NumberFormat {
382 
383     private transient android.icu.text.DecimalFormat icuDecimalFormat;
384 
385     /**
386      * Creates a DecimalFormat using the default pattern and symbols
387      * for the default {@link java.util.Locale.Category#FORMAT FORMAT} locale.
388      * This is a convenient way to obtain a
389      * DecimalFormat when internationalization is not the main concern.
390      * <p>
391      * To obtain standard formats for a given locale, use the factory methods
392      * on NumberFormat such as getNumberInstance. These factories will
393      * return the most appropriate sub-class of NumberFormat for a given
394      * locale.
395      *
396      * @see java.text.NumberFormat#getInstance
397      * @see java.text.NumberFormat#getNumberInstance
398      * @see java.text.NumberFormat#getCurrencyInstance
399      * @see java.text.NumberFormat#getPercentInstance
400      */
DecimalFormat()401     public DecimalFormat() {
402         // Get the pattern for the default locale.
403         Locale def = Locale.getDefault(Locale.Category.FORMAT);
404         // try to get the pattern from the cache
405         String pattern = cachedLocaleData.get(def);
406         if (pattern == null) {  /* cache miss */
407             // Get the pattern for the default locale.
408             pattern = LocaleData.get(def).numberPattern;
409             /* update cache */
410             cachedLocaleData.putIfAbsent(def, pattern);
411         }
412         this.symbols = new DecimalFormatSymbols(def);
413         init(pattern);
414     }
415 
416 
417     /**
418      * Creates a DecimalFormat using the given pattern and the symbols
419      * for the default {@link java.util.Locale.Category#FORMAT FORMAT} locale.
420      * This is a convenient way to obtain a
421      * DecimalFormat when internationalization is not the main concern.
422      * <p>
423      * To obtain standard formats for a given locale, use the factory methods
424      * on NumberFormat such as getNumberInstance. These factories will
425      * return the most appropriate sub-class of NumberFormat for a given
426      * locale.
427      *
428      * @param pattern a non-localized pattern string.
429      * @exception NullPointerException if <code>pattern</code> is null
430      * @exception IllegalArgumentException if the given pattern is invalid.
431      * @see java.text.NumberFormat#getInstance
432      * @see java.text.NumberFormat#getNumberInstance
433      * @see java.text.NumberFormat#getCurrencyInstance
434      * @see java.text.NumberFormat#getPercentInstance
435      */
DecimalFormat(String pattern)436     public DecimalFormat(String pattern) {
437         this.symbols = new DecimalFormatSymbols(Locale.getDefault(Locale.Category.FORMAT));
438         init(pattern);
439     }
440 
441 
442     /**
443      * Creates a DecimalFormat using the given pattern and symbols.
444      * Use this constructor when you need to completely customize the
445      * behavior of the format.
446      * <p>
447      * To obtain standard formats for a given
448      * locale, use the factory methods on NumberFormat such as
449      * getInstance or getCurrencyInstance. If you need only minor adjustments
450      * to a standard format, you can modify the format returned by
451      * a NumberFormat factory method.
452      *
453      * @param pattern a non-localized pattern string
454      * @param symbols the set of symbols to be used
455      * @exception NullPointerException if any of the given arguments is null
456      * @exception IllegalArgumentException if the given pattern is invalid
457      * @see java.text.NumberFormat#getInstance
458      * @see java.text.NumberFormat#getNumberInstance
459      * @see java.text.NumberFormat#getCurrencyInstance
460      * @see java.text.NumberFormat#getPercentInstance
461      * @see java.text.DecimalFormatSymbols
462      */
DecimalFormat(String pattern, DecimalFormatSymbols symbols)463     public DecimalFormat (String pattern, DecimalFormatSymbols symbols) {
464         // Always applyPattern after the symbols are set
465         this.symbols = (DecimalFormatSymbols)symbols.clone();
466         init(pattern);
467     }
468 
init(String pattern)469     private void init(String pattern) {
470         this.icuDecimalFormat =  new android.icu.text.DecimalFormat(pattern,
471                 symbols.getIcuDecimalFormatSymbols());
472         updateFieldsFromIcu();
473     }
474 
475     /**
476      * Converts between field positions used by Java/ICU.
477      * @param fp The java.text.NumberFormat.Field field position
478      * @return The android.icu.text.NumberFormat.Field field position
479      */
getIcuFieldPosition(FieldPosition fp)480     private static FieldPosition getIcuFieldPosition(FieldPosition fp) {
481         if (fp.getFieldAttribute() == null) return fp;
482 
483         android.icu.text.NumberFormat.Field attribute;
484         if (fp.getFieldAttribute() == Field.INTEGER) {
485             attribute = android.icu.text.NumberFormat.Field.INTEGER;
486         } else if (fp.getFieldAttribute() == Field.FRACTION) {
487             attribute = android.icu.text.NumberFormat.Field.FRACTION;
488         } else if (fp.getFieldAttribute() == Field.DECIMAL_SEPARATOR) {
489             attribute = android.icu.text.NumberFormat.Field.DECIMAL_SEPARATOR;
490         } else if (fp.getFieldAttribute() == Field.EXPONENT_SYMBOL) {
491             attribute = android.icu.text.NumberFormat.Field.EXPONENT_SYMBOL;
492         } else if (fp.getFieldAttribute() == Field.EXPONENT_SIGN) {
493             attribute = android.icu.text.NumberFormat.Field.EXPONENT_SIGN;
494         } else if (fp.getFieldAttribute() == Field.EXPONENT) {
495             attribute = android.icu.text.NumberFormat.Field.EXPONENT;
496         } else if (fp.getFieldAttribute() == Field.GROUPING_SEPARATOR) {
497             attribute = android.icu.text.NumberFormat.Field.GROUPING_SEPARATOR;
498         } else if (fp.getFieldAttribute() == Field.CURRENCY) {
499             attribute = android.icu.text.NumberFormat.Field.CURRENCY;
500         } else if (fp.getFieldAttribute() == Field.PERCENT) {
501             attribute = android.icu.text.NumberFormat.Field.PERCENT;
502         } else if (fp.getFieldAttribute() == Field.PERMILLE) {
503             attribute = android.icu.text.NumberFormat.Field.PERMILLE;
504         } else if (fp.getFieldAttribute() == Field.SIGN) {
505             attribute = android.icu.text.NumberFormat.Field.SIGN;
506         } else {
507             throw new IllegalArgumentException("Unexpected field position attribute type.");
508         }
509 
510         FieldPosition icuFieldPosition = new FieldPosition(attribute);
511         icuFieldPosition.setBeginIndex(fp.getBeginIndex());
512         icuFieldPosition.setEndIndex(fp.getEndIndex());
513         return icuFieldPosition;
514     }
515 
516     /**
517      * Converts the Attribute that ICU returns in its AttributedCharacterIterator
518      * responses to the type that java uses.
519      * @param icuAttribute The AttributedCharacterIterator.Attribute field.
520      * @return Field converted to a java.text.NumberFormat.Field field.
521      */
toJavaFieldAttribute(AttributedCharacterIterator.Attribute icuAttribute)522     private static Field toJavaFieldAttribute(AttributedCharacterIterator.Attribute icuAttribute) {
523         if (icuAttribute.getName().equals(Field.INTEGER.getName())) {
524             return Field.INTEGER;
525         }
526         if (icuAttribute.getName().equals(Field.CURRENCY.getName())) {
527             return Field.CURRENCY;
528         }
529         if (icuAttribute.getName().equals(Field.DECIMAL_SEPARATOR.getName())) {
530             return Field.DECIMAL_SEPARATOR;
531         }
532         if (icuAttribute.getName().equals(Field.EXPONENT.getName())) {
533             return Field.EXPONENT;
534         }
535         if (icuAttribute.getName().equals(Field.EXPONENT_SIGN.getName())) {
536             return Field.EXPONENT_SIGN;
537         }
538         if (icuAttribute.getName().equals(Field.EXPONENT_SYMBOL.getName())) {
539             return Field.EXPONENT_SYMBOL;
540         }
541         if (icuAttribute.getName().equals(Field.FRACTION.getName())) {
542             return Field.FRACTION;
543         }
544         if (icuAttribute.getName().equals(Field.GROUPING_SEPARATOR.getName())) {
545             return Field.GROUPING_SEPARATOR;
546         }
547         if (icuAttribute.getName().equals(Field.SIGN.getName())) {
548             return Field.SIGN;
549         }
550         if (icuAttribute.getName().equals(Field.PERCENT.getName())) {
551             return Field.PERCENT;
552         }
553         if (icuAttribute.getName().equals(Field.PERMILLE.getName())) {
554             return Field.PERMILLE;
555         }
556         throw new IllegalArgumentException("Unrecognized attribute: " + icuAttribute.getName());
557    }
558 
559     // Overrides
560     /**
561      * Formats a number and appends the resulting text to the given string
562      * buffer.
563      * The number can be of any subclass of {@link java.lang.Number}.
564      * <p>
565      * This implementation uses the maximum precision permitted.
566      * @param number     the number to format
567      * @param toAppendTo the <code>StringBuffer</code> to which the formatted
568      *                   text is to be appended
569      * @param pos        On input: an alignment field, if desired.
570      *                   On output: the offsets of the alignment field.
571      * @return           the value passed in as <code>toAppendTo</code>
572      * @exception        IllegalArgumentException if <code>number</code> is
573      *                   null or not an instance of <code>Number</code>.
574      * @exception        NullPointerException if <code>toAppendTo</code> or
575      *                   <code>pos</code> is null
576      * @exception        ArithmeticException if rounding is needed with rounding
577      *                   mode being set to RoundingMode.UNNECESSARY
578      * @see              java.text.FieldPosition
579      */
580     @Override
format(Object number, StringBuffer toAppendTo, FieldPosition pos)581     public final StringBuffer format(Object number,
582                                      StringBuffer toAppendTo,
583                                      FieldPosition pos) {
584         if (number instanceof Long || number instanceof Integer ||
585                    number instanceof Short || number instanceof Byte ||
586                    number instanceof AtomicInteger ||
587                    number instanceof AtomicLong ||
588                    (number instanceof BigInteger &&
589                     ((BigInteger)number).bitLength () < 64)) {
590             return format(((Number)number).longValue(), toAppendTo, pos);
591         } else if (number instanceof BigDecimal) {
592             return format((BigDecimal)number, toAppendTo, pos);
593         } else if (number instanceof BigInteger) {
594             return format((BigInteger)number, toAppendTo, pos);
595         } else if (number instanceof Number) {
596             return format(((Number)number).doubleValue(), toAppendTo, pos);
597         } else {
598             throw new IllegalArgumentException("Cannot format given Object as a Number");
599         }
600     }
601 
602     /**
603      * Formats a double to produce a string.
604      * @param number    The double to format
605      * @param result    where the text is to be appended
606      * @param fieldPosition    On input: an alignment field, if desired.
607      * On output: the offsets of the alignment field.
608      * @exception ArithmeticException if rounding is needed with rounding
609      *            mode being set to RoundingMode.UNNECESSARY
610      * @return The formatted number string
611      * @see java.text.FieldPosition
612      */
613     @Override
format(double number, StringBuffer result, FieldPosition fieldPosition)614     public StringBuffer format(double number, StringBuffer result,
615                                FieldPosition fieldPosition) {
616         FieldPosition icuFieldPosition = getIcuFieldPosition(fieldPosition);
617         icuDecimalFormat.format(number, result, icuFieldPosition);
618         fieldPosition.setBeginIndex(icuFieldPosition.getBeginIndex());
619         fieldPosition.setEndIndex(icuFieldPosition.getEndIndex());
620         return result;
621     }
622 
623     /**
624      * Format a long to produce a string.
625      * @param number    The long to format
626      * @param result    where the text is to be appended
627      * @param fieldPosition    On input: an alignment field, if desired.
628      * On output: the offsets of the alignment field.
629      * @exception       ArithmeticException if rounding is needed with rounding
630      *                  mode being set to RoundingMode.UNNECESSARY
631      * @return The formatted number string
632      * @see java.text.FieldPosition
633      */
634     @Override
format(long number, StringBuffer result, FieldPosition fieldPosition)635     public StringBuffer format(long number, StringBuffer result,
636                                FieldPosition fieldPosition) {
637         FieldPosition icuFieldPosition = getIcuFieldPosition(fieldPosition);
638         icuDecimalFormat.format(number, result, icuFieldPosition);
639         fieldPosition.setBeginIndex(icuFieldPosition.getBeginIndex());
640         fieldPosition.setEndIndex(icuFieldPosition.getEndIndex());
641         return result;
642     }
643 
644     /**
645      * Formats a BigDecimal to produce a string.
646      * @param number    The BigDecimal to format
647      * @param result    where the text is to be appended
648      * @param fieldPosition    On input: an alignment field, if desired.
649      * On output: the offsets of the alignment field.
650      * @return The formatted number string
651      * @exception        ArithmeticException if rounding is needed with rounding
652      *                   mode being set to RoundingMode.UNNECESSARY
653      * @see java.text.FieldPosition
654      */
format(BigDecimal number, StringBuffer result, FieldPosition fieldPosition)655     private StringBuffer format(BigDecimal number, StringBuffer result,
656                                 FieldPosition fieldPosition) {
657         FieldPosition icuFieldPosition = getIcuFieldPosition(fieldPosition);
658         icuDecimalFormat.format(number, result, fieldPosition);
659         fieldPosition.setBeginIndex(icuFieldPosition.getBeginIndex());
660         fieldPosition.setEndIndex(icuFieldPosition.getEndIndex());
661         return result;
662     }
663 
664     /**
665      * Format a BigInteger to produce a string.
666      * @param number    The BigInteger to format
667      * @param result    where the text is to be appended
668      * @param fieldPosition    On input: an alignment field, if desired.
669      * On output: the offsets of the alignment field.
670      * @return The formatted number string
671      * @exception        ArithmeticException if rounding is needed with rounding
672      *                   mode being set to RoundingMode.UNNECESSARY
673      * @see java.text.FieldPosition
674      */
format(BigInteger number, StringBuffer result, FieldPosition fieldPosition)675     private StringBuffer format(BigInteger number, StringBuffer result,
676                                FieldPosition fieldPosition) {
677         FieldPosition icuFieldPosition = getIcuFieldPosition(fieldPosition);
678         icuDecimalFormat.format(number, result, fieldPosition);
679         fieldPosition.setBeginIndex(icuFieldPosition.getBeginIndex());
680         fieldPosition.setEndIndex(icuFieldPosition.getEndIndex());
681         return result;
682     }
683 
684     /**
685      * Formats an Object producing an <code>AttributedCharacterIterator</code>.
686      * You can use the returned <code>AttributedCharacterIterator</code>
687      * to build the resulting String, as well as to determine information
688      * about the resulting String.
689      * <p>
690      * Each attribute key of the AttributedCharacterIterator will be of type
691      * <code>NumberFormat.Field</code>, with the attribute value being the
692      * same as the attribute key.
693      *
694      * @exception NullPointerException if obj is null.
695      * @exception IllegalArgumentException when the Format cannot format the
696      *            given object.
697      * @exception        ArithmeticException if rounding is needed with rounding
698      *                   mode being set to RoundingMode.UNNECESSARY
699      * @param obj The object to format
700      * @return AttributedCharacterIterator describing the formatted value.
701      * @since 1.4
702      */
703     @Override
formatToCharacterIterator(Object obj)704     public AttributedCharacterIterator formatToCharacterIterator(Object obj) {
705         if (obj == null) {
706             throw new NullPointerException("object == null");
707         }
708         // Note: formatToCharacterIterator cannot be used directly because it returns attributes
709         // in terms of its own class: icu.text.NumberFormat instead of java.text.NumberFormat.
710         // http://bugs.icu-project.org/trac/ticket/11931 Proposes to use the NumberFormat constants.
711 
712         AttributedCharacterIterator original = icuDecimalFormat.formatToCharacterIterator(obj);
713 
714         // Extract the text out of the ICU iterator.
715         StringBuilder textBuilder = new StringBuilder(
716                 original.getEndIndex() - original.getBeginIndex());
717 
718         for (int i = original.getBeginIndex(); i < original.getEndIndex(); i++) {
719             textBuilder.append(original.current());
720             original.next();
721         }
722 
723         AttributedString result = new AttributedString(textBuilder.toString());
724 
725         for (int i = original.getBeginIndex(); i < original.getEndIndex(); i++) {
726             original.setIndex(i);
727 
728             for (AttributedCharacterIterator.Attribute attribute
729                     : original.getAttributes().keySet()) {
730                     int start = original.getRunStart();
731                     int end = original.getRunLimit();
732                     Field javaAttr = toJavaFieldAttribute(attribute);
733                     result.addAttribute(javaAttr, javaAttr, start, end);
734             }
735         }
736 
737         return result.getIterator();
738     }
739 
740     /**
741      * Parses text from a string to produce a <code>Number</code>.
742      * <p>
743      * The method attempts to parse text starting at the index given by
744      * <code>pos</code>.
745      * If parsing succeeds, then the index of <code>pos</code> is updated
746      * to the index after the last character used (parsing does not necessarily
747      * use all characters up to the end of the string), and the parsed
748      * number is returned. The updated <code>pos</code> can be used to
749      * indicate the starting point for the next call to this method.
750      * If an error occurs, then the index of <code>pos</code> is not
751      * changed, the error index of <code>pos</code> is set to the index of
752      * the character where the error occurred, and null is returned.
753      * <p>
754      * The subclass returned depends on the value of {@link #isParseBigDecimal}
755      * as well as on the string being parsed.
756      * <ul>
757      *   <li>If <code>isParseBigDecimal()</code> is false (the default),
758      *       most integer values are returned as <code>Long</code>
759      *       objects, no matter how they are written: <code>"17"</code> and
760      *       <code>"17.000"</code> both parse to <code>Long(17)</code>.
761      *       Values that cannot fit into a <code>Long</code> are returned as
762      *       <code>Double</code>s. This includes values with a fractional part,
763      *       infinite values, <code>NaN</code>, and the value -0.0.
764      *       <code>DecimalFormat</code> does <em>not</em> decide whether to
765      *       return a <code>Double</code> or a <code>Long</code> based on the
766      *       presence of a decimal separator in the source string. Doing so
767      *       would prevent integers that overflow the mantissa of a double,
768      *       such as <code>"-9,223,372,036,854,775,808.00"</code>, from being
769      *       parsed accurately.
770      *       <p>
771      *       Callers may use the <code>Number</code> methods
772      *       <code>doubleValue</code>, <code>longValue</code>, etc., to obtain
773      *       the type they want.
774      *   <li>If <code>isParseBigDecimal()</code> is true, values are returned
775      *       as <code>BigDecimal</code> objects. The values are the ones
776      *       constructed by {@link java.math.BigDecimal#BigDecimal(String)}
777      *       for corresponding strings in locale-independent format. The
778      *       special cases negative and positive infinity and NaN are returned
779      *       as <code>Double</code> instances holding the values of the
780      *       corresponding <code>Double</code> constants.
781      * </ul>
782      * <p>
783      * <code>DecimalFormat</code> parses all Unicode characters that represent
784      * decimal digits, as defined by <code>Character.digit()</code>. In
785      * addition, <code>DecimalFormat</code> also recognizes as digits the ten
786      * consecutive characters starting with the localized zero digit defined in
787      * the <code>DecimalFormatSymbols</code> object.
788      *
789      * @param text the string to be parsed
790      * @param pos  A <code>ParsePosition</code> object with index and error
791      *             index information as described above.
792      * @return     the parsed value, or <code>null</code> if the parse fails
793      * @exception  NullPointerException if <code>text</code> or
794      *             <code>pos</code> is null.
795      */
796     @Override
parse(String text, ParsePosition pos)797     public Number parse(String text, ParsePosition pos) {
798         // Return early if the parse position is bogus.
799         if (pos.index < 0 || pos.index >= text.length()) {
800             return null;
801         }
802 
803         // This might return android.icu.math.BigDecimal, java.math.BigInteger or a primitive type.
804         Number number = icuDecimalFormat.parse(text, pos);
805         if (number == null) {
806             return null;
807         }
808         if (isParseBigDecimal()) {
809             if (number instanceof Long) {
810                 return new BigDecimal(number.longValue());
811             }
812             if ((number instanceof Double) && !((Double) number).isInfinite()
813                     && !((Double) number).isNaN()) {
814                 return new BigDecimal(number.toString());
815             }
816             if ((number instanceof Double) &&
817                     (((Double) number).isNaN() || ((Double) number).isInfinite())) {
818                 return number;
819             }
820             if (number instanceof android.icu.math.BigDecimal) {
821                 return ((android.icu.math.BigDecimal) number).toBigDecimal();
822             }
823         }
824         if ((number instanceof android.icu.math.BigDecimal) || (number instanceof BigInteger)) {
825             return number.doubleValue();
826         }
827         if (isParseIntegerOnly() && number.equals(new Double(-0.0))) {
828             return 0L;
829         }
830         return number;
831     }
832 
833     /**
834      * Returns a copy of the decimal format symbols, which is generally not
835      * changed by the programmer or user.
836      * @return a copy of the desired DecimalFormatSymbols
837      * @see java.text.DecimalFormatSymbols
838      */
getDecimalFormatSymbols()839     public DecimalFormatSymbols getDecimalFormatSymbols() {
840         return DecimalFormatSymbols.fromIcuInstance(icuDecimalFormat.getDecimalFormatSymbols());
841     }
842 
843 
844     /**
845      * Sets the decimal format symbols, which is generally not changed
846      * by the programmer or user.
847      * @param newSymbols desired DecimalFormatSymbols
848      * @see java.text.DecimalFormatSymbols
849      */
setDecimalFormatSymbols(DecimalFormatSymbols newSymbols)850     public void setDecimalFormatSymbols(DecimalFormatSymbols newSymbols) {
851         try {
852             // don't allow multiple references
853             symbols = (DecimalFormatSymbols) newSymbols.clone();
854             icuDecimalFormat.setDecimalFormatSymbols(symbols.getIcuDecimalFormatSymbols());
855         } catch (Exception foo) {
856             // should never happen
857         }
858     }
859 
860     /**
861      * Get the positive prefix.
862      * <P>Examples: +123, $123, sFr123
863      *
864      * @return the positive prefix
865      */
getPositivePrefix()866     public String getPositivePrefix () {
867         return icuDecimalFormat.getPositivePrefix();
868     }
869 
870     /**
871      * Set the positive prefix.
872      * <P>Examples: +123, $123, sFr123
873      *
874      * @param newValue the new positive prefix
875      */
setPositivePrefix(String newValue)876     public void setPositivePrefix (String newValue) {
877         icuDecimalFormat.setPositivePrefix(newValue);
878     }
879 
880     /**
881      * Get the  prefix.
882      * <P>Examples: -123, ($123) (with negative suffix), sFr-123
883      *
884      * @return the negative prefix
885      */
getNegativePrefix()886     public String getNegativePrefix () {
887         return icuDecimalFormat.getNegativePrefix();
888     }
889 
890     /**
891      * Set the negative prefix.
892      * <P>Examples: -123, ($123) (with negative suffix), sFr-123
893      *
894      * @param newValue the new negative prefix
895      */
setNegativePrefix(String newValue)896     public void setNegativePrefix (String newValue) {
897         icuDecimalFormat.setNegativePrefix(newValue);
898     }
899 
900     /**
901      * Get the positive suffix.
902      * <P>Example: 123%
903      *
904      * @return the positive suffix
905      */
getPositiveSuffix()906     public String getPositiveSuffix () {
907         return icuDecimalFormat.getPositiveSuffix();
908     }
909 
910     /**
911      * Set the positive suffix.
912      * <P>Example: 123%
913      *
914      * @param newValue the new positive suffix
915      */
setPositiveSuffix(String newValue)916     public void setPositiveSuffix (String newValue) {
917         icuDecimalFormat.setPositiveSuffix(newValue);
918     }
919 
920     /**
921      * Get the negative suffix.
922      * <P>Examples: -123%, ($123) (with positive suffixes)
923      *
924      * @return the negative suffix
925      */
getNegativeSuffix()926     public String getNegativeSuffix () {
927         return icuDecimalFormat.getNegativeSuffix();
928     }
929 
930     /**
931      * Set the negative suffix.
932      * <P>Examples: 123%
933      *
934      * @param newValue the new negative suffix
935      */
setNegativeSuffix(String newValue)936     public void setNegativeSuffix (String newValue) {
937         icuDecimalFormat.setNegativeSuffix(newValue);
938     }
939 
940     /**
941      * Gets the multiplier for use in percent, per mille, and similar
942      * formats.
943      *
944      * @return the multiplier
945      * @see #setMultiplier(int)
946      */
getMultiplier()947     public int getMultiplier () {
948         return icuDecimalFormat.getMultiplier();
949     }
950 
951     /**
952      * Sets the multiplier for use in percent, per mille, and similar
953      * formats.
954      * For a percent format, set the multiplier to 100 and the suffixes to
955      * have '%' (for Arabic, use the Arabic percent sign).
956      * For a per mille format, set the multiplier to 1000 and the suffixes to
957      * have '&#92;u2030'.
958      *
959      * <P>Example: with multiplier 100, 1.23 is formatted as "123", and
960      * "123" is parsed into 1.23.
961      *
962      * @param newValue the new multiplier
963      * @see #getMultiplier
964      */
setMultiplier(int newValue)965     public void setMultiplier (int newValue) {
966         icuDecimalFormat.setMultiplier(newValue);
967     }
968 
969     /**
970      * Return the grouping size. Grouping size is the number of digits between
971      * grouping separators in the integer portion of a number.  For example,
972      * in the number "123,456.78", the grouping size is 3.
973      *
974      * @return the grouping size
975      * @see #setGroupingSize
976      * @see java.text.NumberFormat#isGroupingUsed
977      * @see java.text.DecimalFormatSymbols#getGroupingSeparator
978      */
getGroupingSize()979     public int getGroupingSize () {
980         return icuDecimalFormat.getGroupingSize();
981     }
982 
983     /**
984      * Set the grouping size. Grouping size is the number of digits between
985      * grouping separators in the integer portion of a number.  For example,
986      * in the number "123,456.78", the grouping size is 3.
987      * <br>
988      * The value passed in is converted to a byte, which may lose information.
989      *
990      * @param newValue the new grouping size
991      * @see #getGroupingSize
992      * @see java.text.NumberFormat#setGroupingUsed
993      * @see java.text.DecimalFormatSymbols#setGroupingSeparator
994      */
setGroupingSize(int newValue)995     public void setGroupingSize (int newValue) {
996         icuDecimalFormat.setGroupingSize(newValue);
997     }
998 
999     /**
1000      * Returns true if grouping is used in this format. For example, in the
1001      * English locale, with grouping on, the number 1234567 might be formatted
1002      * as "1,234,567". The grouping separator as well as the size of each group
1003      * is locale dependant and is determined by sub-classes of NumberFormat.
1004      * @see #setGroupingUsed
1005      */
isGroupingUsed()1006     public boolean isGroupingUsed() {
1007         return icuDecimalFormat.isGroupingUsed();
1008     }
1009 
1010     /**
1011      * Set whether or not grouping will be used in this format.
1012      * @see #isGroupingUsed
1013      */
setGroupingUsed(boolean newValue)1014     public void setGroupingUsed(boolean newValue) {
1015         icuDecimalFormat.setGroupingUsed(newValue);
1016     }
1017 
1018     /**
1019      * Allows you to get the behavior of the decimal separator with integers.
1020      * (The decimal separator will always appear with decimals.)
1021      * <P>Example: Decimal ON: 12345 &rarr; 12345.; OFF: 12345 &rarr; 12345
1022      *
1023      * @return {@code true} if the decimal separator is always shown;
1024      *         {@code false} otherwise
1025      */
isDecimalSeparatorAlwaysShown()1026     public boolean isDecimalSeparatorAlwaysShown() {
1027         return icuDecimalFormat.isDecimalSeparatorAlwaysShown();
1028     }
1029 
1030     /**
1031      * Allows you to set the behavior of the decimal separator with integers.
1032      * (The decimal separator will always appear with decimals.)
1033      * <P>Example: Decimal ON: 12345 &rarr; 12345.; OFF: 12345 &rarr; 12345
1034      *
1035      * @param newValue {@code true} if the decimal separator is always shown;
1036      *                 {@code false} otherwise
1037      */
setDecimalSeparatorAlwaysShown(boolean newValue)1038     public void setDecimalSeparatorAlwaysShown(boolean newValue) {
1039         icuDecimalFormat.setDecimalSeparatorAlwaysShown(newValue);
1040     }
1041 
1042     /**
1043      * Returns whether the {@link #parse(java.lang.String, java.text.ParsePosition)}
1044      * method returns <code>BigDecimal</code>. The default value is false.
1045      *
1046      * @return {@code true} if the parse method returns BigDecimal;
1047      *         {@code false} otherwise
1048      * @see #setParseBigDecimal
1049      * @since 1.5
1050      */
isParseBigDecimal()1051     public boolean isParseBigDecimal() {
1052         return icuDecimalFormat.isParseBigDecimal();
1053     }
1054 
1055     /**
1056      * Sets whether the {@link #parse(java.lang.String, java.text.ParsePosition)}
1057      * method returns <code>BigDecimal</code>.
1058      *
1059      * @param newValue {@code true} if the parse method returns BigDecimal;
1060      *                 {@code false} otherwise
1061      * @see #isParseBigDecimal
1062      * @since 1.5
1063      */
setParseBigDecimal(boolean newValue)1064     public void setParseBigDecimal(boolean newValue) {
1065         icuDecimalFormat.setParseBigDecimal(newValue);
1066     }
1067 
1068     /**
1069      * Sets whether or not numbers should be parsed as integers only.
1070      * @see #isParseIntegerOnly
1071      */
setParseIntegerOnly(boolean value)1072     public void setParseIntegerOnly(boolean value) {
1073         super.setParseIntegerOnly(value);
1074         icuDecimalFormat.setParseIntegerOnly(value);
1075     }
1076 
1077     /**
1078      * Returns true if this format will parse numbers as integers only.
1079      * For example in the English locale, with ParseIntegerOnly true, the
1080      * string "1234." would be parsed as the integer value 1234 and parsing
1081      * would stop at the "." character.  Of course, the exact format accepted
1082      * by the parse operation is locale dependant and determined by sub-classes
1083      * of NumberFormat.
1084      */
isParseIntegerOnly()1085     public boolean isParseIntegerOnly() {
1086         return icuDecimalFormat.isParseIntegerOnly();
1087     }
1088 
1089     /**
1090      * Standard override; no change in semantics.
1091      */
1092     @Override
clone()1093     public Object clone() {
1094         try {
1095             DecimalFormat other = (DecimalFormat) super.clone();
1096             other.icuDecimalFormat = (android.icu.text.DecimalFormat) icuDecimalFormat.clone();
1097             other.symbols = (DecimalFormatSymbols) symbols.clone();
1098             return other;
1099         } catch (Exception e) {
1100             throw new InternalError();
1101         }
1102     }
1103 
1104     /**
1105      * Overrides equals
1106      */
1107     @Override
equals(Object obj)1108     public boolean equals(Object obj)
1109     {
1110         if (obj == null) {
1111             return false;
1112         }
1113         if (this == obj) {
1114             return true;
1115         }
1116         if (!(obj instanceof DecimalFormat)) {
1117             return false;
1118         }
1119         DecimalFormat other = (DecimalFormat) obj;
1120         return icuDecimalFormat.equals(other.icuDecimalFormat)
1121             && compareIcuRoundingIncrement(other.icuDecimalFormat);
1122     }
1123 
compareIcuRoundingIncrement(android.icu.text.DecimalFormat other)1124     private boolean compareIcuRoundingIncrement(android.icu.text.DecimalFormat other) {
1125         BigDecimal increment = this.icuDecimalFormat.getRoundingIncrement();
1126         if (increment != null) {
1127             return (other.getRoundingIncrement() != null)
1128                 && increment.equals(other.getRoundingIncrement());
1129         }
1130         return other.getRoundingIncrement() == null;
1131     }
1132 
1133     /**
1134      * Overrides hashCode
1135      */
1136     @Override
hashCode()1137     public int hashCode() {
1138         return super.hashCode() * 37 + getPositivePrefix().hashCode();
1139         // just enough fields for a reasonable distribution
1140     }
1141 
1142     /**
1143      * Synthesizes a pattern string that represents the current state
1144      * of this Format object.
1145      *
1146      * @return a pattern string
1147      * @see #applyPattern
1148      */
toPattern()1149     public String toPattern() {
1150         return icuDecimalFormat.toPattern();
1151     }
1152 
1153     /**
1154      * Synthesizes a localized pattern string that represents the current
1155      * state of this Format object.
1156      *
1157      * @return a localized pattern string
1158      * @see #applyPattern
1159      */
toLocalizedPattern()1160     public String toLocalizedPattern() {
1161         return icuDecimalFormat.toLocalizedPattern();
1162     }
1163 
1164     /**
1165      * Apply the given pattern to this Format object.  A pattern is a
1166      * short-hand specification for the various formatting properties.
1167      * These properties can also be changed individually through the
1168      * various setter methods.
1169      * <p>
1170      * There is no limit to integer digits set
1171      * by this routine, since that is the typical end-user desire;
1172      * use setMaximumInteger if you want to set a real value.
1173      * For negative numbers, use a second pattern, separated by a semicolon
1174      * <P>Example <code>"#,#00.0#"</code> &rarr; 1,234.56
1175      * <P>This means a minimum of 2 integer digits, 1 fraction digit, and
1176      * a maximum of 2 fraction digits.
1177      * <p>Example: <code>"#,#00.0#;(#,#00.0#)"</code> for negatives in
1178      * parentheses.
1179      * <p>In negative patterns, the minimum and maximum counts are ignored;
1180      * these are presumed to be set in the positive pattern.
1181      *
1182      * @param pattern a new pattern
1183      * @exception NullPointerException if <code>pattern</code> is null
1184      * @exception IllegalArgumentException if the given pattern is invalid.
1185      */
applyPattern(String pattern)1186     public void applyPattern(String pattern) {
1187         icuDecimalFormat.applyPattern(pattern);
1188         updateFieldsFromIcu();
1189     }
1190 
1191 
1192     /**
1193      * Apply the given pattern to this Format object.  The pattern
1194      * is assumed to be in a localized notation. A pattern is a
1195      * short-hand specification for the various formatting properties.
1196      * These properties can also be changed individually through the
1197      * various setter methods.
1198      * <p>
1199      * There is no limit to integer digits set
1200      * by this routine, since that is the typical end-user desire;
1201      * use setMaximumInteger if you want to set a real value.
1202      * For negative numbers, use a second pattern, separated by a semicolon
1203      * <P>Example <code>"#,#00.0#"</code> &rarr; 1,234.56
1204      * <P>This means a minimum of 2 integer digits, 1 fraction digit, and
1205      * a maximum of 2 fraction digits.
1206      * <p>Example: <code>"#,#00.0#;(#,#00.0#)"</code> for negatives in
1207      * parentheses.
1208      * <p>In negative patterns, the minimum and maximum counts are ignored;
1209      * these are presumed to be set in the positive pattern.
1210      *
1211      * @param pattern a new pattern
1212      * @exception NullPointerException if <code>pattern</code> is null
1213      * @exception IllegalArgumentException if the given pattern is invalid.
1214      */
applyLocalizedPattern(String pattern)1215     public void applyLocalizedPattern(String pattern) {
1216         icuDecimalFormat.applyLocalizedPattern(pattern);
1217         updateFieldsFromIcu();
1218     }
1219 
updateFieldsFromIcu()1220     private void updateFieldsFromIcu() {
1221         // Imitate behaviour of ICU4C NumberFormat that Android used up to M.
1222         // If the pattern doesn't enforce a different value (some exponential
1223         // patterns do), then set the maximum integer digits to 2 billion.
1224         if (icuDecimalFormat.getMaximumIntegerDigits() == DOUBLE_INTEGER_DIGITS) {
1225             icuDecimalFormat.setMaximumIntegerDigits(2000000000);
1226         }
1227         maximumIntegerDigits = icuDecimalFormat.getMaximumIntegerDigits();
1228         minimumIntegerDigits = icuDecimalFormat.getMinimumIntegerDigits();
1229         maximumFractionDigits = icuDecimalFormat.getMaximumFractionDigits();
1230         minimumFractionDigits = icuDecimalFormat.getMinimumFractionDigits();
1231     }
1232 
1233     /**
1234      * Sets the maximum number of digits allowed in the integer portion of a
1235      * number.
1236      * For formatting numbers other than <code>BigInteger</code> and
1237      * <code>BigDecimal</code> objects, the lower of <code>newValue</code> and
1238      * 309 is used. Negative input values are replaced with 0.
1239      * @see NumberFormat#setMaximumIntegerDigits
1240      */
1241     @Override
setMaximumIntegerDigits(int newValue)1242     public void setMaximumIntegerDigits(int newValue) {
1243         maximumIntegerDigits = Math.min(Math.max(0, newValue), MAXIMUM_INTEGER_DIGITS);
1244         super.setMaximumIntegerDigits((maximumIntegerDigits > DOUBLE_INTEGER_DIGITS) ?
1245             DOUBLE_INTEGER_DIGITS : maximumIntegerDigits);
1246         if (minimumIntegerDigits > maximumIntegerDigits) {
1247             minimumIntegerDigits = maximumIntegerDigits;
1248             super.setMinimumIntegerDigits((minimumIntegerDigits > DOUBLE_INTEGER_DIGITS) ?
1249                 DOUBLE_INTEGER_DIGITS : minimumIntegerDigits);
1250         }
1251         icuDecimalFormat.setMaximumIntegerDigits(getMaximumIntegerDigits());
1252     }
1253 
1254     /**
1255      * Sets the minimum number of digits allowed in the integer portion of a
1256      * number.
1257      * For formatting numbers other than <code>BigInteger</code> and
1258      * <code>BigDecimal</code> objects, the lower of <code>newValue</code> and
1259      * 309 is used. Negative input values are replaced with 0.
1260      * @see NumberFormat#setMinimumIntegerDigits
1261      */
1262     @Override
setMinimumIntegerDigits(int newValue)1263     public void setMinimumIntegerDigits(int newValue) {
1264         minimumIntegerDigits = Math.min(Math.max(0, newValue), MAXIMUM_INTEGER_DIGITS);
1265         super.setMinimumIntegerDigits((minimumIntegerDigits > DOUBLE_INTEGER_DIGITS) ?
1266             DOUBLE_INTEGER_DIGITS : minimumIntegerDigits);
1267         if (minimumIntegerDigits > maximumIntegerDigits) {
1268             maximumIntegerDigits = minimumIntegerDigits;
1269             super.setMaximumIntegerDigits((maximumIntegerDigits > DOUBLE_INTEGER_DIGITS) ?
1270                 DOUBLE_INTEGER_DIGITS : maximumIntegerDigits);
1271         }
1272         icuDecimalFormat.setMinimumIntegerDigits(getMinimumIntegerDigits());
1273     }
1274 
1275     /**
1276      * Sets the maximum number of digits allowed in the fraction portion of a
1277      * number.
1278      * For formatting numbers other than <code>BigInteger</code> and
1279      * <code>BigDecimal</code> objects, the lower of <code>newValue</code> and
1280      * 340 is used. Negative input values are replaced with 0.
1281      * @see NumberFormat#setMaximumFractionDigits
1282      */
1283     @Override
setMaximumFractionDigits(int newValue)1284     public void setMaximumFractionDigits(int newValue) {
1285         maximumFractionDigits = Math.min(Math.max(0, newValue), MAXIMUM_FRACTION_DIGITS);
1286         super.setMaximumFractionDigits((maximumFractionDigits > DOUBLE_FRACTION_DIGITS) ?
1287             DOUBLE_FRACTION_DIGITS : maximumFractionDigits);
1288         if (minimumFractionDigits > maximumFractionDigits) {
1289             minimumFractionDigits = maximumFractionDigits;
1290             super.setMinimumFractionDigits((minimumFractionDigits > DOUBLE_FRACTION_DIGITS) ?
1291                 DOUBLE_FRACTION_DIGITS : minimumFractionDigits);
1292         }
1293         icuDecimalFormat.setMaximumFractionDigits(getMaximumFractionDigits());
1294     }
1295 
1296     /**
1297      * Sets the minimum number of digits allowed in the fraction portion of a
1298      * number.
1299      * For formatting numbers other than <code>BigInteger</code> and
1300      * <code>BigDecimal</code> objects, the lower of <code>newValue</code> and
1301      * 340 is used. Negative input values are replaced with 0.
1302      * @see NumberFormat#setMinimumFractionDigits
1303      */
1304     @Override
setMinimumFractionDigits(int newValue)1305     public void setMinimumFractionDigits(int newValue) {
1306         minimumFractionDigits = Math.min(Math.max(0, newValue), MAXIMUM_FRACTION_DIGITS);
1307         super.setMinimumFractionDigits((minimumFractionDigits > DOUBLE_FRACTION_DIGITS) ?
1308             DOUBLE_FRACTION_DIGITS : minimumFractionDigits);
1309         if (minimumFractionDigits > maximumFractionDigits) {
1310             maximumFractionDigits = minimumFractionDigits;
1311             super.setMaximumFractionDigits((maximumFractionDigits > DOUBLE_FRACTION_DIGITS) ?
1312                 DOUBLE_FRACTION_DIGITS : maximumFractionDigits);
1313         }
1314         icuDecimalFormat.setMinimumFractionDigits(getMinimumFractionDigits());
1315     }
1316 
1317     /**
1318      * Gets the maximum number of digits allowed in the integer portion of a
1319      * number.
1320      * For formatting numbers other than <code>BigInteger</code> and
1321      * <code>BigDecimal</code> objects, the lower of the return value and
1322      * 309 is used.
1323      * @see #setMaximumIntegerDigits
1324      */
1325     @Override
getMaximumIntegerDigits()1326     public int getMaximumIntegerDigits() {
1327         return maximumIntegerDigits;
1328     }
1329 
1330     /**
1331      * Gets the minimum number of digits allowed in the integer portion of a
1332      * number.
1333      * For formatting numbers other than <code>BigInteger</code> and
1334      * <code>BigDecimal</code> objects, the lower of the return value and
1335      * 309 is used.
1336      * @see #setMinimumIntegerDigits
1337      */
1338     @Override
getMinimumIntegerDigits()1339     public int getMinimumIntegerDigits() {
1340         return minimumIntegerDigits;
1341     }
1342 
1343     /**
1344      * Gets the maximum number of digits allowed in the fraction portion of a
1345      * number.
1346      * For formatting numbers other than <code>BigInteger</code> and
1347      * <code>BigDecimal</code> objects, the lower of the return value and
1348      * 340 is used.
1349      * @see #setMaximumFractionDigits
1350      */
1351     @Override
getMaximumFractionDigits()1352     public int getMaximumFractionDigits() {
1353         return maximumFractionDigits;
1354     }
1355 
1356     /**
1357      * Gets the minimum number of digits allowed in the fraction portion of a
1358      * number.
1359      * For formatting numbers other than <code>BigInteger</code> and
1360      * <code>BigDecimal</code> objects, the lower of the return value and
1361      * 340 is used.
1362      * @see #setMinimumFractionDigits
1363      */
1364     @Override
getMinimumFractionDigits()1365     public int getMinimumFractionDigits() {
1366         return minimumFractionDigits;
1367     }
1368 
1369     /**
1370      * Gets the currency used by this decimal format when formatting
1371      * currency values.
1372      * The currency is obtained by calling
1373      * {@link DecimalFormatSymbols#getCurrency DecimalFormatSymbols.getCurrency}
1374      * on this number format's symbols.
1375      *
1376      * @return the currency used by this decimal format, or <code>null</code>
1377      * @since 1.4
1378      */
1379     @Override
getCurrency()1380     public Currency getCurrency() {
1381         return symbols.getCurrency();
1382     }
1383 
1384     /**
1385      * Sets the currency used by this number format when formatting
1386      * currency values. This does not update the minimum or maximum
1387      * number of fraction digits used by the number format.
1388      * The currency is set by calling
1389      * {@link DecimalFormatSymbols#setCurrency DecimalFormatSymbols.setCurrency}
1390      * on this number format's symbols.
1391      *
1392      * @param currency the new currency to be used by this decimal format
1393      * @exception NullPointerException if <code>currency</code> is null
1394      * @since 1.4
1395      */
1396     @Override
setCurrency(Currency currency)1397     public void setCurrency(Currency currency) {
1398         // Set the international currency symbol, and currency symbol on the DecimalFormatSymbols
1399         // object and tell ICU to use that.
1400         if (currency != symbols.getCurrency()
1401             || !currency.getSymbol().equals(symbols.getCurrencySymbol())) {
1402             symbols.setCurrency(currency);
1403             icuDecimalFormat.setDecimalFormatSymbols(symbols.getIcuDecimalFormatSymbols());
1404             // Giving the icuDecimalFormat a new currency will cause the fractional digits to be
1405             // updated. This class is specified to not touch the fraction digits, so we re-set them.
1406             icuDecimalFormat.setMinimumFractionDigits(minimumFractionDigits);
1407             icuDecimalFormat.setMaximumFractionDigits(maximumFractionDigits);
1408         }
1409     }
1410 
1411     /**
1412      * Gets the {@link java.math.RoundingMode} used in this DecimalFormat.
1413      *
1414      * @return The <code>RoundingMode</code> used for this DecimalFormat.
1415      * @see #setRoundingMode(RoundingMode)
1416      * @since 1.6
1417      */
1418     @Override
getRoundingMode()1419     public RoundingMode getRoundingMode() {
1420         return roundingMode;
1421     }
1422 
convertRoundingMode(RoundingMode rm)1423     private static int convertRoundingMode(RoundingMode rm) {
1424         switch (rm) {
1425         case UP:
1426             return MathContext.ROUND_UP;
1427         case DOWN:
1428             return MathContext.ROUND_DOWN;
1429         case CEILING:
1430             return MathContext.ROUND_CEILING;
1431         case FLOOR:
1432             return MathContext.ROUND_FLOOR;
1433         case HALF_UP:
1434             return MathContext.ROUND_HALF_UP;
1435         case HALF_DOWN:
1436             return MathContext.ROUND_HALF_DOWN;
1437         case HALF_EVEN:
1438             return MathContext.ROUND_HALF_EVEN;
1439         case UNNECESSARY:
1440             return MathContext.ROUND_UNNECESSARY;
1441         }
1442         throw new IllegalArgumentException("Invalid rounding mode specified");
1443     }
1444 
1445     /**
1446      * Sets the {@link java.math.RoundingMode} used in this DecimalFormat.
1447      *
1448      * @param roundingMode The <code>RoundingMode</code> to be used
1449      * @see #getRoundingMode()
1450      * @exception NullPointerException if <code>roundingMode</code> is null.
1451      * @since 1.6
1452      */
1453     @Override
setRoundingMode(RoundingMode roundingMode)1454     public void setRoundingMode(RoundingMode roundingMode) {
1455         if (roundingMode == null) {
1456             throw new NullPointerException();
1457         }
1458 
1459         this.roundingMode = roundingMode;
1460 
1461         icuDecimalFormat.setRoundingMode(convertRoundingMode(roundingMode));
1462     }
1463 
1464     /**
1465      * Adjusts the minimum and maximum fraction digits to values that
1466      * are reasonable for the currency's default fraction digits.
1467      */
adjustForCurrencyDefaultFractionDigits()1468     void adjustForCurrencyDefaultFractionDigits() {
1469         Currency currency = symbols.getCurrency();
1470         if (currency == null) {
1471             try {
1472                 currency = Currency.getInstance(symbols.getInternationalCurrencySymbol());
1473             } catch (IllegalArgumentException e) {
1474             }
1475         }
1476         if (currency != null) {
1477             int digits = currency.getDefaultFractionDigits();
1478             if (digits != -1) {
1479                 int oldMinDigits = getMinimumFractionDigits();
1480                 // Common patterns are "#.##", "#.00", "#".
1481                 // Try to adjust all of them in a reasonable way.
1482                 if (oldMinDigits == getMaximumFractionDigits()) {
1483                     setMinimumFractionDigits(digits);
1484                     setMaximumFractionDigits(digits);
1485                 } else {
1486                     setMinimumFractionDigits(Math.min(digits, oldMinDigits));
1487                     setMaximumFractionDigits(digits);
1488                 }
1489             }
1490         }
1491     }
1492 
1493     private static final int currentSerialVersion = 4;
1494 
1495     // the fields list to be serialized
1496     private static final ObjectStreamField[] serialPersistentFields = {
1497             new ObjectStreamField("positivePrefix", String.class),
1498             new ObjectStreamField("positiveSuffix", String.class),
1499             new ObjectStreamField("negativePrefix", String.class),
1500             new ObjectStreamField("negativeSuffix", String.class),
1501             new ObjectStreamField("posPrefixPattern", String.class),
1502             new ObjectStreamField("posSuffixPattern", String.class),
1503             new ObjectStreamField("negPrefixPattern", String.class),
1504             new ObjectStreamField("negSuffixPattern", String.class),
1505             new ObjectStreamField("multiplier", int.class),
1506             new ObjectStreamField("groupingSize", byte.class),
1507             new ObjectStreamField("groupingUsed", boolean.class),
1508             new ObjectStreamField("decimalSeparatorAlwaysShown", boolean.class),
1509             new ObjectStreamField("parseBigDecimal", boolean.class),
1510             new ObjectStreamField("roundingMode", RoundingMode.class),
1511             new ObjectStreamField("symbols", DecimalFormatSymbols.class),
1512             new ObjectStreamField("useExponentialNotation", boolean.class),
1513             new ObjectStreamField("minExponentDigits", byte.class),
1514             new ObjectStreamField("maximumIntegerDigits", int.class),
1515             new ObjectStreamField("minimumIntegerDigits", int.class),
1516             new ObjectStreamField("maximumFractionDigits", int.class),
1517             new ObjectStreamField("minimumFractionDigits", int.class),
1518             new ObjectStreamField("serialVersionOnStream", int.class),
1519     };
1520 
writeObject(ObjectOutputStream stream)1521     private void writeObject(ObjectOutputStream stream) throws IOException, ClassNotFoundException {
1522         ObjectOutputStream.PutField fields = stream.putFields();
1523         fields.put("positivePrefix", icuDecimalFormat.getPositivePrefix());
1524         fields.put("positiveSuffix", icuDecimalFormat.getPositiveSuffix());
1525         fields.put("negativePrefix", icuDecimalFormat.getNegativePrefix());
1526         fields.put("negativeSuffix", icuDecimalFormat.getNegativeSuffix());
1527         fields.put("posPrefixPattern", (String) null);
1528         fields.put("posSuffixPattern", (String) null);
1529         fields.put("negPrefixPattern", (String) null);
1530         fields.put("negSuffixPattern", (String) null);
1531         fields.put("multiplier", icuDecimalFormat.getMultiplier());
1532         fields.put("groupingSize", (byte) icuDecimalFormat.getGroupingSize());
1533         fields.put("groupingUsed", icuDecimalFormat.isGroupingUsed());
1534         fields.put("decimalSeparatorAlwaysShown", icuDecimalFormat.isDecimalSeparatorAlwaysShown());
1535         fields.put("parseBigDecimal", icuDecimalFormat.isParseBigDecimal());
1536         fields.put("roundingMode", roundingMode);
1537         fields.put("symbols", symbols);
1538         fields.put("useExponentialNotation", false);
1539         fields.put("minExponentDigits", (byte) 0);
1540         fields.put("maximumIntegerDigits", icuDecimalFormat.getMaximumIntegerDigits());
1541         fields.put("minimumIntegerDigits", icuDecimalFormat.getMinimumIntegerDigits());
1542         fields.put("maximumFractionDigits", icuDecimalFormat.getMaximumFractionDigits());
1543         fields.put("minimumFractionDigits", icuDecimalFormat.getMinimumFractionDigits());
1544         fields.put("serialVersionOnStream", currentSerialVersion);
1545         stream.writeFields();
1546     }
1547 
1548     /**
1549      * Reads the default serializable fields from the stream and performs
1550      * validations and adjustments for older serialized versions. The
1551      * validations and adjustments are:
1552      * <ol>
1553      * <li>
1554      * Verify that the superclass's digit count fields correctly reflect
1555      * the limits imposed on formatting numbers other than
1556      * <code>BigInteger</code> and <code>BigDecimal</code> objects. These
1557      * limits are stored in the superclass for serialization compatibility
1558      * with older versions, while the limits for <code>BigInteger</code> and
1559      * <code>BigDecimal</code> objects are kept in this class.
1560      * If, in the superclass, the minimum or maximum integer digit count is
1561      * larger than <code>DOUBLE_INTEGER_DIGITS</code> or if the minimum or
1562      * maximum fraction digit count is larger than
1563      * <code>DOUBLE_FRACTION_DIGITS</code>, then the stream data is invalid
1564      * and this method throws an <code>InvalidObjectException</code>.
1565      * <li>
1566      * If <code>serialVersionOnStream</code> is less than 4, initialize
1567      * <code>roundingMode</code> to {@link java.math.RoundingMode#HALF_EVEN
1568      * RoundingMode.HALF_EVEN}.  This field is new with version 4.
1569      * <li>
1570      * If <code>serialVersionOnStream</code> is less than 3, then call
1571      * the setters for the minimum and maximum integer and fraction digits with
1572      * the values of the corresponding superclass getters to initialize the
1573      * fields in this class. The fields in this class are new with version 3.
1574      * <li>
1575      * If <code>serialVersionOnStream</code> is less than 1, indicating that
1576      * the stream was written by JDK 1.1, initialize
1577      * <code>useExponentialNotation</code>
1578      * to false, since it was not present in JDK 1.1.
1579      * <li>
1580      * Set <code>serialVersionOnStream</code> to the maximum allowed value so
1581      * that default serialization will work properly if this object is streamed
1582      * out again.
1583      * </ol>
1584      *
1585      * <p>Stream versions older than 2 will not have the affix pattern variables
1586      * <code>posPrefixPattern</code> etc.  As a result, they will be initialized
1587      * to <code>null</code>, which means the affix strings will be taken as
1588      * literal values.  This is exactly what we want, since that corresponds to
1589      * the pre-version-2 behavior.
1590      */
readObject(ObjectInputStream stream)1591     private void readObject(ObjectInputStream stream)
1592             throws IOException, ClassNotFoundException {
1593         ObjectInputStream.GetField fields = stream.readFields();
1594         this.symbols = (DecimalFormatSymbols) fields.get("symbols", null);
1595 
1596         init("");
1597 
1598         icuDecimalFormat.setPositivePrefix((String) fields.get("positivePrefix", ""));
1599         icuDecimalFormat.setPositiveSuffix((String) fields.get("positiveSuffix", ""));
1600         icuDecimalFormat.setNegativePrefix((String) fields.get("negativePrefix", "-"));
1601         icuDecimalFormat.setNegativeSuffix((String) fields.get("negativeSuffix", ""));
1602         icuDecimalFormat.setMultiplier(fields.get("multiplier", 1));
1603         icuDecimalFormat.setGroupingSize(fields.get("groupingSize", (byte) 3));
1604         icuDecimalFormat.setGroupingUsed(fields.get("groupingUsed", true));
1605         icuDecimalFormat.setDecimalSeparatorAlwaysShown(fields.get("decimalSeparatorAlwaysShown",
1606                 false));
1607 
1608         setRoundingMode((RoundingMode) fields.get("roundingMode", RoundingMode.HALF_EVEN));
1609 
1610         final int maximumIntegerDigits = fields.get("maximumIntegerDigits", 309);
1611         final int minimumIntegerDigits = fields.get("minimumIntegerDigits", 309);
1612         final int maximumFractionDigits = fields.get("maximumFractionDigits", 340);
1613         final int minimumFractionDigits = fields.get("minimumFractionDigits", 340);
1614         // Tell ICU what we want, then ask it what we can have, and then
1615         // set that in our Java object. This isn't RI-compatible, but then very little of our
1616         // behavior in this area is, and it's not obvious how we can second-guess ICU (or tell
1617         // it to just do exactly what we ask). We only need to do this with maximumIntegerDigits
1618         // because ICU doesn't seem to have its own ideas about the other options.
1619         icuDecimalFormat.setMaximumIntegerDigits(maximumIntegerDigits);
1620         super.setMaximumIntegerDigits(icuDecimalFormat.getMaximumIntegerDigits());
1621 
1622         setMinimumIntegerDigits(minimumIntegerDigits);
1623         setMinimumFractionDigits(minimumFractionDigits);
1624         setMaximumFractionDigits(maximumFractionDigits);
1625         setParseBigDecimal(fields.get("parseBigDecimal", false));
1626 
1627         if (fields.get("serialVersionOnStream", 0) < 3) {
1628             setMaximumIntegerDigits(super.getMaximumIntegerDigits());
1629             setMinimumIntegerDigits(super.getMinimumIntegerDigits());
1630             setMaximumFractionDigits(super.getMaximumFractionDigits());
1631             setMinimumFractionDigits(super.getMinimumFractionDigits());
1632         }
1633     }
1634 
1635     //----------------------------------------------------------------------
1636     // INSTANCE VARIABLES
1637     //----------------------------------------------------------------------
1638 
1639     /**
1640      * The <code>DecimalFormatSymbols</code> object used by this format.
1641      * It contains the symbols used to format numbers, e.g. the grouping separator,
1642      * decimal separator, and so on.
1643      *
1644      * @serial
1645      * @see #setDecimalFormatSymbols
1646      * @see java.text.DecimalFormatSymbols
1647      */
1648     private DecimalFormatSymbols symbols;
1649 
1650     /**
1651      * The maximum number of digits allowed in the integer portion of a
1652      * <code>BigInteger</code> or <code>BigDecimal</code> number.
1653      * <code>maximumIntegerDigits</code> must be greater than or equal to
1654      * <code>minimumIntegerDigits</code>.
1655      *
1656      * @serial
1657      * @see #getMaximumIntegerDigits
1658      * @since 1.5
1659      */
1660     private int    maximumIntegerDigits;
1661 
1662     /**
1663      * The minimum number of digits allowed in the integer portion of a
1664      * <code>BigInteger</code> or <code>BigDecimal</code> number.
1665      * <code>minimumIntegerDigits</code> must be less than or equal to
1666      * <code>maximumIntegerDigits</code>.
1667      *
1668      * @serial
1669      * @see #getMinimumIntegerDigits
1670      * @since 1.5
1671      */
1672     private int    minimumIntegerDigits;
1673 
1674     /**
1675      * The maximum number of digits allowed in the fractional portion of a
1676      * <code>BigInteger</code> or <code>BigDecimal</code> number.
1677      * <code>maximumFractionDigits</code> must be greater than or equal to
1678      * <code>minimumFractionDigits</code>.
1679      *
1680      * @serial
1681      * @see #getMaximumFractionDigits
1682      * @since 1.5
1683      */
1684     private int    maximumFractionDigits;
1685 
1686     /**
1687      * The minimum number of digits allowed in the fractional portion of a
1688      * <code>BigInteger</code> or <code>BigDecimal</code> number.
1689      * <code>minimumFractionDigits</code> must be less than or equal to
1690      * <code>maximumFractionDigits</code>.
1691      *
1692      * @serial
1693      * @see #getMinimumFractionDigits
1694      * @since 1.5
1695      */
1696     private int    minimumFractionDigits;
1697 
1698     /**
1699      * The {@link java.math.RoundingMode} used in this DecimalFormat.
1700      *
1701      * @serial
1702      * @since 1.6
1703      */
1704     private RoundingMode roundingMode = RoundingMode.HALF_EVEN;
1705 
1706 
1707 
1708     //----------------------------------------------------------------------
1709     // CONSTANTS
1710     //----------------------------------------------------------------------
1711 
1712     // Upper limit on integer and fraction digits for a Java double
1713     static final int DOUBLE_INTEGER_DIGITS  = 309;
1714     static final int DOUBLE_FRACTION_DIGITS = 340;
1715 
1716     // Upper limit on integer and fraction digits for BigDecimal and BigInteger
1717     static final int MAXIMUM_INTEGER_DIGITS  = Integer.MAX_VALUE;
1718     static final int MAXIMUM_FRACTION_DIGITS = Integer.MAX_VALUE;
1719 
1720     // Proclaim JDK 1.1 serial compatibility.
1721     static final long serialVersionUID = 864413376551465018L;
1722 
1723     /**
1724      * Cache to hold the NumberPattern of a Locale.
1725      */
1726     private static final ConcurrentMap<Locale, String> cachedLocaleData
1727         = new ConcurrentHashMap<Locale, String>(3);
1728 }
1729