3 *******************************************************************************
4 * Copyright (C) 1996-2009, International Business Machines Corporation and *
5 * others. All Rights Reserved. *
6 *******************************************************************************
9 package com.ibm.icu.text;
11 import java.io.IOException;
12 import java.io.InvalidObjectException;
13 import java.io.ObjectInputStream;
14 import java.io.ObjectOutputStream;
15 import java.math.BigInteger;
16 import java.text.FieldPosition;
17 import java.text.ParseException;
18 import java.text.ParsePosition;
19 import java.util.Collections;
20 import java.util.Locale;
21 import java.util.MissingResourceException;
23 //#if defined(FOUNDATION10) || defined(J2SE13)
25 import java.text.Format;
28 import com.ibm.icu.impl.ICUResourceBundle;
29 import com.ibm.icu.impl.Utility;
30 import com.ibm.icu.util.Currency;
31 import com.ibm.icu.util.CurrencyAmount;
32 import com.ibm.icu.util.ULocale;
33 import com.ibm.icu.util.UResourceBundle;
35 // this is an enhanced version that is based on the standard version in the JDK
37 * <code>NumberFormat</code> is the abstract base class for all number
38 * formats. This class provides the interface for formatting and parsing
39 * numbers. <code>NumberFormat</code> also provides methods for determining
40 * which locales have number formats, and what their names are.
42 * <code>NumberFormat</code> helps you to format and parse numbers for any locale.
43 * Your code can be completely independent of the locale conventions for
44 * decimal points, thousands-separators, or even the particular decimal
45 * digits used, or whether the number format is even decimal.
48 * To format a number for the current Locale, use one of the factory
52 * myString = NumberFormat.getInstance().format(myNumber);
55 * If you are formatting multiple numbers, it is
56 * more efficient to get the format and use it multiple times so that
57 * the system doesn't have to fetch the information about the local
58 * language and country conventions multiple times.
61 * NumberFormat nf = NumberFormat.getInstance();
62 * for (int i = 0; i < a.length; ++i) {
63 * output.println(nf.format(myNumber[i]) + "; ");
67 * To format a number for a different Locale, specify it in the
68 * call to <code>getInstance</code>.
71 * NumberFormat nf = NumberFormat.getInstance(Locale.FRENCH);
74 * You can also use a <code>NumberFormat</code> to parse numbers:
77 * myNumber = nf.parse(myString);
80 * Use <code>getInstance</code> or <code>getNumberInstance</code> to get the
81 * normal number format. Use <code>getIntegerInstance</code> to get an
82 * integer number format. Use <code>getCurrencyInstance</code> to get the
83 * currency number format. And use <code>getPercentInstance</code> to get a
84 * format for displaying percentages. With this format, a fraction like
85 * 0.53 is displayed as 53%.
88 * Starting from ICU 4.2, you can use getInstance() by passing in a 'style'
89 * as parameter to get the correct instance.
91 * use getInstance(...NUMBERSTYLE) to get the normal number format,
92 * getInstance(...PERCENTSTYLE) to get a format for displaying percentage,
93 * getInstance(...SCIENTIFICSTYLE) to get a format for displaying scientific number,
94 * getInstance(...INTEGERSTYLE) to get an integer number format,
95 * getInstance(...CURRENCYSTYLE) to get the currency number format,
96 * in which the currency is represented by its symbol, for example, "$3.00".
97 * getInstance(...ISOCURRENCYSTYLE) to get the currency number format,
98 * in which the currency is represented by its ISO code, for example "USD3.00".
99 * getInstance(...PLURALCURRENCYSTYLE) to get the currency number format,
100 * in which the currency is represented by its full name in plural format,
101 * for example, "3.00 US dollars" or "1.00 US dollar".
105 * You can also control the display of numbers with such methods as
106 * <code>setMinimumFractionDigits</code>.
107 * If you want even more control over the format or parsing,
108 * or want to give your users more control,
109 * you can try casting the <code>NumberFormat</code> you get from the factory methods
110 * to a <code>DecimalFormat</code>. This will work for the vast majority
111 * of locales; just remember to put it in a <code>try</code> block in case you
112 * encounter an unusual one.
115 * NumberFormat is designed such that some controls
116 * work for formatting and others work for parsing. The following is
117 * the detailed description for each these control methods,
119 * setParseIntegerOnly : only affects parsing, e.g.
120 * if true, "3456.78" -> 3456 (and leaves the parse position just after '6')
121 * if false, "3456.78" -> 3456.78 (and leaves the parse position just after '8')
122 * This is independent of formatting. If you want to not show a decimal point
123 * where there might be no digits after the decimal point, use
124 * setDecimalSeparatorAlwaysShown on DecimalFormat.
126 * You can also use forms of the <code>parse</code> and <code>format</code>
127 * methods with <code>ParsePosition</code> and <code>FieldPosition</code> to
130 * <li> progressively parse through pieces of a string
131 * <li> align the decimal point and other areas
133 * For example, you can align numbers in two ways:
135 * <li> If you are using a monospaced font with spacing for alignment,
136 * you can pass the <code>FieldPosition</code> in your format call, with
137 * <code>field</code> = <code>INTEGER_FIELD</code>. On output,
138 * <code>getEndIndex</code> will be set to the offset between the
139 * last character of the integer and the decimal. Add
140 * (desiredSpaceCount - getEndIndex) spaces at the front of the string.
142 * <li> If you are using proportional fonts,
143 * instead of padding with spaces, measure the width
144 * of the string in pixels from the start to <code>getEndIndex</code>.
145 * Then move the pen by
146 * (desiredPixelWidth - widthToAlignmentPoint) before drawing the text.
147 * It also works where there is no decimal, but possibly additional
148 * characters at the end, e.g., with parentheses in negative
149 * numbers: "(12)" for -12.
152 * <h4>Synchronization</h4>
154 * Number formats are generally not synchronized. It is recommended to create
155 * separate format instances for each thread. If multiple threads access a format
156 * concurrently, it must be synchronized externally.
159 * <h4>DecimalFormat</h4>
160 * <p>DecimalFormat is the concrete implementation of NumberFormat, and the
161 * NumberFormat API is essentially an abstraction from DecimalFormat's API.
162 * Refer to DecimalFormat for more information about this API.</p>
165 * see java.text.ChoiceFormat
167 * @author Helena Shih
171 public abstract class NumberFormat extends UFormat {
174 * Constants to specify normal number style of format.
176 * @provisional This API might change or be removed in a future release.
178 public static final int NUMBERSTYLE = 0;
180 * Constants to specify currency style of format which uses currency symbol
181 * to represent currency, for example: "$3.00".
183 * @provisional This API might change or be removed in a future release.
185 public static final int CURRENCYSTYLE = 1;
187 * Constants to specify a style of format to display percent.
189 * @provisional This API might change or be removed in a future release.
191 public static final int PERCENTSTYLE = 2;
193 * Constants to specify a style of format to display scientific number.
195 * @provisional This API might change or be removed in a future release.
197 public static final int SCIENTIFICSTYLE = 3;
199 * Constants to specify a integer number style format.
201 * @provisional This API might change or be removed in a future release.
203 public static final int INTEGERSTYLE = 4;
205 * Constants to specify currency style of format which uses currency
206 * ISO code to represent currency, for example: "USD3.00".
208 * @provisional This API might change or be removed in a future release.
210 public static final int ISOCURRENCYSTYLE = 5;
212 * Constants to specify currency style of format which uses currency
213 * long name with plural format to represent currency, for example,
216 * @provisional This API might change or be removed in a future release.
218 public static final int PLURALCURRENCYSTYLE = 6;
221 * Field constant used to construct a FieldPosition object. Signifies that
222 * the position of the integer part of a formatted number should be returned.
223 * @see java.text.FieldPosition
226 public static final int INTEGER_FIELD = 0;
229 * Field constant used to construct a FieldPosition object. Signifies that
230 * the position of the fraction part of a formatted number should be returned.
231 * @see java.text.FieldPosition
234 public static final int FRACTION_FIELD = 1;
238 * Format an object. Change: recognizes <code>BigInteger</code>
239 * and <code>BigDecimal</code> objects.
242 public StringBuffer format(Object number,
243 StringBuffer toAppendTo,
246 if (number instanceof Long) {
247 return format(((Long)number).longValue(), toAppendTo, pos);
248 } else if (number instanceof BigInteger) {
249 return format((BigInteger) number, toAppendTo, pos);
250 //#if defined(FOUNDATION10)
252 } else if (number instanceof java.math.BigDecimal) {
253 return format((java.math.BigDecimal) number, toAppendTo, pos);
255 } else if (number instanceof com.ibm.icu.math.BigDecimal) {
256 return format((com.ibm.icu.math.BigDecimal) number, toAppendTo, pos);
257 } else if (number instanceof CurrencyAmount) {
258 return format((CurrencyAmount)number, toAppendTo, pos);
259 } else if (number instanceof Number) {
260 return format(((Number)number).doubleValue(), toAppendTo, pos);
262 throw new IllegalArgumentException("Cannot format given Object as a Number");
269 public final Object parseObject(String source,
270 ParsePosition parsePosition)
272 return parse(source, parsePosition);
276 * Specialization of format.
277 * @see java.text.Format#format(Object)
280 public final String format(double number) {
281 return format(number,new StringBuffer(),
282 new FieldPosition(0)).toString();
286 * Specialization of format.
287 * @see java.text.Format#format(Object)
290 public final String format(long number) {
291 StringBuffer buf = new StringBuffer(19);
292 FieldPosition pos = new FieldPosition(0);
293 format(number, buf, pos);
294 return buf.toString();
299 * Convenience method to format a BigInteger.
302 public final String format(BigInteger number) {
303 return format(number, new StringBuffer(),
304 new FieldPosition(0)).toString();
307 //#if defined(FOUNDATION10)
311 * Convenience method to format a BigDecimal.
314 public final String format(java.math.BigDecimal number) {
315 return format(number, new StringBuffer(),
316 new FieldPosition(0)).toString();
322 * Convenience method to format an ICU BigDecimal.
325 public final String format(com.ibm.icu.math.BigDecimal number) {
326 return format(number, new StringBuffer(),
327 new FieldPosition(0)).toString();
332 * Convenience method to format a CurrencyAmount.
335 public final String format(CurrencyAmount currAmt) {
336 return format(currAmt, new StringBuffer(),
337 new FieldPosition(0)).toString();
341 * Specialization of format.
342 * @see java.text.Format#format(Object, StringBuffer, FieldPosition)
345 public abstract StringBuffer format(double number,
346 StringBuffer toAppendTo,
350 * Specialization of format.
351 * @see java.text.Format#format(Object, StringBuffer, FieldPosition)
354 public abstract StringBuffer format(long number,
355 StringBuffer toAppendTo,
359 * Format a BigInteger.
360 * @see java.text.Format#format(Object, StringBuffer, FieldPosition)
363 public abstract StringBuffer format(BigInteger number,
364 StringBuffer toAppendTo,
366 //#if defined(FOUNDATION10)
371 * Format a BigDecimal.
372 * @see java.text.Format#format(Object, StringBuffer, FieldPosition)
375 public abstract StringBuffer format(java.math.BigDecimal number,
376 StringBuffer toAppendTo,
382 * Format a BigDecimal.
383 * @see java.text.Format#format(Object, StringBuffer, FieldPosition)
386 public abstract StringBuffer format(com.ibm.icu.math.BigDecimal number,
387 StringBuffer toAppendTo,
391 * Format a CurrencyAmount.
392 * @see java.text.Format#format(Object, StringBuffer, FieldPosition)
395 public StringBuffer format(CurrencyAmount currAmt,
396 StringBuffer toAppendTo,
398 // Default implementation -- subclasses may override
399 Currency save = getCurrency(), curr = currAmt.getCurrency();
400 boolean same = curr.equals(save);
401 if (!same) setCurrency(curr);
402 format(currAmt.getNumber(), toAppendTo, pos);
403 if (!same) setCurrency(save);
408 * Returns a Long if possible (e.g., within the range [Long.MIN_VALUE,
409 * Long.MAX_VALUE] and with no decimals), otherwise a Double.
410 * If IntegerOnly is set, will stop at a decimal
411 * point (or equivalent; e.g., for rational numbers "1 2/3", will stop
413 * Does not throw an exception; if no object can be parsed, index is
415 * @see #isParseIntegerOnly
416 * @see java.text.Format#parseObject(String, ParsePosition)
419 public abstract Number parse(String text, ParsePosition parsePosition);
422 * Parses text from the beginning of the given string to produce a number.
423 * The method might not use the entire text of the given string.
425 * @param text A String whose beginning should be parsed.
426 * @return A Number parsed from the string.
427 * @exception ParseException if the beginning of the specified string
432 //Bug 4375399 [Richard/GCL]
433 public Number parse(String text) throws ParseException {
434 ParsePosition parsePosition = new ParsePosition(0);
435 Number result = parse(text, parsePosition);
436 if (parsePosition.getIndex() == 0) {
437 throw new ParseException("Unparseable number: \"" + text + '"',
438 parsePosition.getErrorIndex());
445 * Parses text from the given string as a CurrencyAmount. Unlike
446 * the parse() method, this method will attempt to parse a generic
447 * currency name, searching for a match of this object's locale's
448 * currency display names, or for a 3-letter ISO currency code.
449 * This method will fail if this format is not a currency format,
450 * that is, if it does not contain the currency pattern symbol
451 * (U+00A4) in its prefix or suffix.
453 * @param text the string to parse
454 * @param pos input-output position; on input, the position within
455 * text to match; must have 0 <= pos.getIndex() < text.length();
456 * on output, the position after the last matched character. If
457 * the parse fails, the position in unchanged upon output.
458 * @return a CurrencyAmount, or null upon failure
460 * @deprecated This API is ICU internal only.
462 CurrencyAmount parseCurrency(String text, ParsePosition pos) {
463 // Default implementation only -- subclasses should override
464 Number n = parse(text, pos);
465 return n == null ? null : new CurrencyAmount(n, getEffectiveCurrency());
469 * Returns true if this format will parse numbers as integers only.
470 * For example in the English locale, with ParseIntegerOnly true, the
471 * string "1234." would be parsed as the integer value 1234 and parsing
472 * would stop at the "." character. The decimal separator accepted
473 * by the parse operation is locale-dependent and determined by the
475 * @return true if this will parse integers only
478 public boolean isParseIntegerOnly() {
479 return parseIntegerOnly;
483 * Sets whether or not numbers should be parsed as integers only.
484 * @param value true if this should parse integers only
485 * @see #isParseIntegerOnly
488 public void setParseIntegerOnly(boolean value) {
489 parseIntegerOnly = value;
493 * Sets whether strict parsing is in effect. When this is true, the
494 * following conditions cause a parse failure (examples use the pattern "#,##0.#"):<ul>
495 * <li>Leading zeros<br>
496 * '00', '0123' fail the parse, but '0' and '0.001' pass</li>
497 * <li>Leading or doubled grouping separators<br>
498 * ',123' and '1,,234" fail</li>
499 * <li>Groups of incorrect length when grouping is used<br>
500 * '1,23' and '1234,567' fail, but '1234' passes</li>
501 * <li>Grouping separators used in numbers followed by exponents<br>
502 * '1,234E5' fails, but '1234E5' and '1,234E' pass ('E' is not an exponent when
503 * not followed by a number)</li>
505 * When strict parsing is off, leading zeros and all grouping separators are ignored.
506 * This is the default behavior.
507 * @param value True to enable strict parsing. Default is false.
508 * @see #isParseStrict
511 public void setParseStrict(boolean value) {
516 * Return whether strict parsing is in effect.
517 * @return true if strict parsing is in effect
518 * @see #setParseStrict
521 public boolean isParseStrict() {
525 //============== Locale Stuff =====================
528 * Returns the default number format for the current default locale.
529 * The default format is one of the styles provided by the other
530 * factory methods: getNumberInstance, getIntegerInstance,
531 * getCurrencyInstance or getPercentInstance.
532 * Exactly which one is locale-dependent.
535 //Bug 4408066 [Richard/GCL]
536 public final static NumberFormat getInstance() {
537 return getInstance(ULocale.getDefault(), NUMBERSTYLE);
541 * Returns the default number format for the specified locale.
542 * The default format is one of the styles provided by the other
543 * factory methods: getNumberInstance, getCurrencyInstance or getPercentInstance.
544 * Exactly which one is locale-dependent.
547 public static NumberFormat getInstance(Locale inLocale) {
548 return getInstance(ULocale.forLocale(inLocale), NUMBERSTYLE);
552 * Returns the default number format for the specified locale.
553 * The default format is one of the styles provided by the other
554 * factory methods: getNumberInstance, getCurrencyInstance or getPercentInstance.
555 * Exactly which one is locale-dependent.
558 public static NumberFormat getInstance(ULocale inLocale) {
559 return getInstance(inLocale, NUMBERSTYLE);
563 * Returns a specific style number format for default locale.
564 * @param style number format style
566 * @provisional This API might change or be removed in a future release.
568 public final static NumberFormat getInstance(int style) {
569 return getInstance(ULocale.getDefault(), style);
573 * Returns a specific style number format for a specific locale.
574 * @param inLocale the specific locale.
575 * @param style number format style
577 * @provisional This API might change or be removed in a future release.
579 public static NumberFormat getInstance(Locale inLocale, int style) {
580 return getInstance(ULocale.forLocale(inLocale), style);
585 * Returns a general-purpose number format for the current default locale.
588 public final static NumberFormat getNumberInstance() {
589 return getInstance(ULocale.getDefault(), NUMBERSTYLE);
593 * Returns a general-purpose number format for the specified locale.
596 public static NumberFormat getNumberInstance(Locale inLocale) {
597 return getInstance(ULocale.forLocale(inLocale), NUMBERSTYLE);
601 * Returns a general-purpose number format for the specified locale.
604 public static NumberFormat getNumberInstance(ULocale inLocale) {
605 return getInstance(inLocale, NUMBERSTYLE);
609 * Returns an integer number format for the current default locale. The
610 * returned number format is configured to round floating point numbers
611 * to the nearest integer using IEEE half-even rounding (see {@link
612 * com.ibm.icu.math.BigDecimal#ROUND_HALF_EVEN ROUND_HALF_EVEN}) for formatting,
613 * and to parse only the integer part of an input string (see {@link
614 * #isParseIntegerOnly isParseIntegerOnly}).
616 * @return a number format for integer values
619 //Bug 4408066 [Richard/GCL]
620 public final static NumberFormat getIntegerInstance() {
621 return getInstance(ULocale.getDefault(), INTEGERSTYLE);
625 * Returns an integer number format for the specified locale. The
626 * returned number format is configured to round floating point numbers
627 * to the nearest integer using IEEE half-even rounding (see {@link
628 * com.ibm.icu.math.BigDecimal#ROUND_HALF_EVEN ROUND_HALF_EVEN}) for formatting,
629 * and to parse only the integer part of an input string (see {@link
630 * #isParseIntegerOnly isParseIntegerOnly}).
632 * @param inLocale the locale for which a number format is needed
633 * @return a number format for integer values
636 //Bug 4408066 [Richard/GCL]
637 public static NumberFormat getIntegerInstance(Locale inLocale) {
638 return getInstance(ULocale.forLocale(inLocale), INTEGERSTYLE);
642 * Returns an integer number format for the specified locale. The
643 * returned number format is configured to round floating point numbers
644 * to the nearest integer using IEEE half-even rounding (see {@link
645 * com.ibm.icu.math.BigDecimal#ROUND_HALF_EVEN ROUND_HALF_EVEN}) for formatting,
646 * and to parse only the integer part of an input string (see {@link
647 * #isParseIntegerOnly isParseIntegerOnly}).
649 * @param inLocale the locale for which a number format is needed
650 * @return a number format for integer values
653 public static NumberFormat getIntegerInstance(ULocale inLocale) {
654 return getInstance(inLocale, INTEGERSTYLE);
658 * Returns a currency format for the current default locale.
659 * @return a number format for currency
662 public final static NumberFormat getCurrencyInstance() {
663 return getInstance(ULocale.getDefault(), CURRENCYSTYLE);
667 * Returns a currency format for the specified locale.
668 * @return a number format for currency
671 public static NumberFormat getCurrencyInstance(Locale inLocale) {
672 return getInstance(ULocale.forLocale(inLocale), CURRENCYSTYLE);
676 * Returns a currency format for the specified locale.
677 * @return a number format for currency
680 public static NumberFormat getCurrencyInstance(ULocale inLocale) {
681 return getInstance(inLocale, CURRENCYSTYLE);
685 * Returns a percentage format for the current default locale.
686 * @return a number format for percents
689 public final static NumberFormat getPercentInstance() {
690 return getInstance(ULocale.getDefault(), PERCENTSTYLE);
694 * Returns a percentage format for the specified locale.
695 * @return a number format for percents
698 public static NumberFormat getPercentInstance(Locale inLocale) {
699 return getInstance(ULocale.forLocale(inLocale), PERCENTSTYLE);
703 * Returns a percentage format for the specified locale.
704 * @return a number format for percents
707 public static NumberFormat getPercentInstance(ULocale inLocale) {
708 return getInstance(inLocale, PERCENTSTYLE);
713 * Returns a scientific format for the current default locale.
714 * @return a scientific number format
717 public final static NumberFormat getScientificInstance() {
718 return getInstance(ULocale.getDefault(), SCIENTIFICSTYLE);
723 * Returns a scientific format for the specified locale.
724 * @return a scientific number format
727 public static NumberFormat getScientificInstance(Locale inLocale) {
728 return getInstance(ULocale.forLocale(inLocale), SCIENTIFICSTYLE);
733 * Returns a scientific format for the specified locale.
734 * @return a scientific number format
737 public static NumberFormat getScientificInstance(ULocale inLocale) {
738 return getInstance(inLocale, SCIENTIFICSTYLE);
741 // ===== Factory stuff =====
743 * A NumberFormatFactory is used to register new number formats. The factory
744 * should be able to create any of the predefined formats for each locale it
745 * supports. When registered, the locales it supports extend or override the
746 * locales already supported by ICU.
747 * <p><b>Note:</b> as of ICU4J 3.2, the default API for NumberFormatFactory uses
748 * ULocale instead of Locale. Instead of overriding createFormat(Locale, int),
749 * new implementations should override createFactory(ULocale, int). Note that
750 * one of these two methods <b>MUST</b> be overridden or else an infinite
755 public static abstract class NumberFormatFactory {
757 * Value passed to format requesting a default number format.
760 public static final int FORMAT_NUMBER = NUMBERSTYLE;
763 * Value passed to format requesting a currency format.
766 public static final int FORMAT_CURRENCY = CURRENCYSTYLE;
769 * Value passed to format requesting a percent format.
772 public static final int FORMAT_PERCENT = PERCENTSTYLE;
775 * Value passed to format requesting a scientific format.
778 public static final int FORMAT_SCIENTIFIC = SCIENTIFICSTYLE;
781 * Value passed to format requesting an integer format.
784 public static final int FORMAT_INTEGER = INTEGERSTYLE;
787 * Returns true if this factory is visible. Default is true.
788 * If not visible, the locales supported by this factory will not
789 * be listed by getAvailableLocales. This value must not change.
790 * @return true if the factory is visible.
794 public boolean visible() {
800 * Returns an immutable collection of the locale names directly
801 * supported by this factory.
802 * @return the supported locale names.
805 public abstract Set getSupportedLocaleNames();
808 * Returns a number format of the appropriate type. If the locale
809 * is not supported, return null. If the locale is supported, but
810 * the type is not provided by this service, return null. Otherwise
811 * return an appropriate instance of NumberFormat.
812 * <b>Note:</b> as of ICU4J 3.2, implementations should override
813 * this method instead of createFormat(Locale, int).
814 * @param loc the locale for which to create the format
815 * @param formatType the type of format
816 * @return the NumberFormat, or null.
819 public NumberFormat createFormat(ULocale loc, int formatType) {
820 return createFormat(loc.toLocale(), formatType);
824 * Returns a number format of the appropriate type. If the locale
825 * is not supported, return null. If the locale is supported, but
826 * the type is not provided by this service, return null. Otherwise
827 * return an appropriate instance of NumberFormat.
828 * <b>Note:</b> as of ICU4J 3.2, createFormat(ULocale, int) should be
829 * overridden instead of this method. This method is no longer
830 * abstract and delegates to that method.
831 * @param loc the locale for which to create the format
832 * @param formatType the type of format
833 * @return the NumberFormat, or null.
836 public NumberFormat createFormat(Locale loc, int formatType) {
837 return createFormat(ULocale.forLocale(loc), formatType);
843 protected NumberFormatFactory() {
848 * A NumberFormatFactory that supports a single locale. It can be visible or invisible.
851 public static abstract class SimpleNumberFormatFactory extends NumberFormatFactory {
852 final Set localeNames;
853 final boolean visible;
856 * Constructs a SimpleNumberFormatFactory with the given locale.
859 public SimpleNumberFormatFactory(Locale locale) {
864 * Constructs a SimpleNumberFormatFactory with the given locale and the
868 public SimpleNumberFormatFactory(Locale locale, boolean visible) {
869 localeNames = Collections.singleton(ULocale.forLocale(locale).getBaseName());
870 this.visible = visible;
874 * Constructs a SimpleNumberFormatFactory with the given locale.
877 public SimpleNumberFormatFactory(ULocale locale) {
882 * Constructs a SimpleNumberFormatFactory with the given locale and the
886 public SimpleNumberFormatFactory(ULocale locale, boolean visible) {
887 localeNames = Collections.singleton(locale.getBaseName());
888 this.visible = visible;
895 public final boolean visible() {
903 public final Set getSupportedLocaleNames() {
908 // shim so we can build without service code
909 static abstract class NumberFormatShim {
910 abstract Locale[] getAvailableLocales();
911 abstract ULocale[] getAvailableULocales();
912 abstract Object registerFactory(NumberFormatFactory f);
913 abstract boolean unregister(Object k);
914 abstract NumberFormat createInstance(ULocale l, int k);
917 private static NumberFormatShim shim;
918 private static NumberFormatShim getShim() {
919 // Note: this instantiation is safe on loose-memory-model configurations
920 // despite lack of synchronization, since the shim instance has no state--
921 // it's all in the class init. The worst problem is we might instantiate
922 // two shim instances, but they'll share the same state so that's ok.
925 Class cls = Class.forName("com.ibm.icu.text.NumberFormatServiceShim");
926 shim = (NumberFormatShim)cls.newInstance();
928 catch (MissingResourceException e){
931 catch (Exception e) {
933 // e.printStackTrace();
934 throw new RuntimeException(e.getMessage());
942 * Get the list of Locales for which NumberFormats are available.
943 * @return the available locales
946 public static Locale[] getAvailableLocales() {
948 return ICUResourceBundle.getAvailableLocales(ICUResourceBundle.ICU_BASE_NAME);
950 return getShim().getAvailableLocales();
954 * Get the list of Locales for which NumberFormats are available.
955 * @return the available locales
956 * @draft ICU 3.2 (retain)
957 * @provisional This API might change or be removed in a future release.
959 public static ULocale[] getAvailableULocales() {
961 return ICUResourceBundle.getAvailableULocales(ICUResourceBundle.ICU_BASE_NAME);
963 return getShim().getAvailableULocales();
967 * Registers a new NumberFormatFactory. The factory is adopted by
968 * the service and must not be modified. The returned object is a
969 * key that can be used to unregister this factory.
970 * @param factory the factory to register
971 * @return a key with which to unregister the factory
974 public static Object registerFactory(NumberFormatFactory factory) {
975 if (factory == null) {
976 throw new IllegalArgumentException("factory must not be null");
978 return getShim().registerFactory(factory);
982 * Unregister the factory or instance associated with this key (obtained from
983 * registerInstance or registerFactory).
984 * @param registryKey a key obtained from registerFactory
985 * @return true if the object was successfully unregistered
988 public static boolean unregister(Object registryKey) {
989 if (registryKey == null) {
990 throw new IllegalArgumentException("registryKey must not be null");
997 return shim.unregister(registryKey);
1000 // ===== End of factory stuff =====
1003 * Overrides hashCode
1006 public int hashCode() {
1007 return maximumIntegerDigits * 37 + maxFractionDigits;
1008 // just enough fields for a reasonable distribution
1012 * Overrides equals. Two NumberFormats are equal if they are of the same class
1013 * and the settings (groupingUsed, parseIntegerOnly, maximumIntegerDigits, etc.
1015 * @param obj the object to compare against
1016 * @return true if the object is equal to this.
1019 public boolean equals(Object obj) {
1020 if (obj == null) return false;
1023 if (getClass() != obj.getClass())
1025 NumberFormat other = (NumberFormat) obj;
1026 return maximumIntegerDigits == other.maximumIntegerDigits
1027 && minimumIntegerDigits == other.minimumIntegerDigits
1028 && maximumFractionDigits == other.maximumFractionDigits
1029 && minimumFractionDigits == other.minimumFractionDigits
1030 && groupingUsed == other.groupingUsed
1031 && parseIntegerOnly == other.parseIntegerOnly
1032 && parseStrict == other.parseStrict;
1036 * Overrides Cloneable.
1039 public Object clone()
1041 NumberFormat other = (NumberFormat) super.clone();
1046 * Returns true if grouping is used in this format. For example, in the
1047 * en_US locale, with grouping on, the number 1234567 will be formatted
1048 * as "1,234,567". The grouping separator as well as the size of each group
1049 * is locale-dependent and is determined by subclasses of NumberFormat.
1050 * Grouping affects both parsing and formatting.
1051 * @return true if grouping is used
1052 * @see #setGroupingUsed
1055 public boolean isGroupingUsed() {
1056 return groupingUsed;
1060 * Sets whether or not grouping will be used in this format. Grouping
1061 * affects both parsing and formatting.
1062 * @see #isGroupingUsed
1063 * @param newValue true to use grouping.
1066 public void setGroupingUsed(boolean newValue) {
1067 groupingUsed = newValue;
1071 * Returns the maximum number of digits allowed in the integer portion of a
1072 * number. The default value is 40, which subclasses can override.
1073 * When formatting, the exact behavior when this value is exceeded is
1074 * subclass-specific. When parsing, this has no effect.
1075 * @return the maximum number of integer digits
1076 * @see #setMaximumIntegerDigits
1079 public int getMaximumIntegerDigits() {
1080 return maximumIntegerDigits;
1084 * Sets the maximum number of digits allowed in the integer portion of a
1085 * number. This must be >= minimumIntegerDigits. If the
1086 * new value for maximumIntegerDigits is less than the current value
1087 * of minimumIntegerDigits, then minimumIntegerDigits will also be set to
1089 * @param newValue the maximum number of integer digits to be shown; if
1090 * less than zero, then zero is used. Subclasses might enforce an
1091 * upper limit to this value appropriate to the numeric type being formatted.
1092 * @see #getMaximumIntegerDigits
1095 public void setMaximumIntegerDigits(int newValue) {
1096 maximumIntegerDigits = Math.max(0,newValue);
1097 if (minimumIntegerDigits > maximumIntegerDigits)
1098 minimumIntegerDigits = maximumIntegerDigits;
1102 * Returns the minimum number of digits allowed in the integer portion of a
1103 * number. The default value is 1, which subclasses can override.
1104 * When formatting, if this value is not reached, numbers are padded on the
1105 * left with the locale-specific '0' character to ensure at least this
1106 * number of integer digits. When parsing, this has no effect.
1107 * @return the minimum number of integer digits
1108 * @see #setMinimumIntegerDigits
1111 public int getMinimumIntegerDigits() {
1112 return minimumIntegerDigits;
1116 * Sets the minimum number of digits allowed in the integer portion of a
1117 * number. This must be <= maximumIntegerDigits. If the
1118 * new value for minimumIntegerDigits is more than the current value
1119 * of maximumIntegerDigits, then maximumIntegerDigits will also be set to
1121 * @param newValue the minimum number of integer digits to be shown; if
1122 * less than zero, then zero is used. Subclasses might enforce an
1123 * upper limit to this value appropriate to the numeric type being formatted.
1124 * @see #getMinimumIntegerDigits
1127 public void setMinimumIntegerDigits(int newValue) {
1128 minimumIntegerDigits = Math.max(0,newValue);
1129 if (minimumIntegerDigits > maximumIntegerDigits)
1130 maximumIntegerDigits = minimumIntegerDigits;
1134 * Returns the maximum number of digits allowed in the fraction
1135 * portion of a number. The default value is 3, which subclasses
1136 * can override. When formatting, the exact behavior when this
1137 * value is exceeded is subclass-specific. When parsing, this has
1139 * @return the maximum number of fraction digits
1140 * @see #setMaximumFractionDigits
1143 public int getMaximumFractionDigits() {
1144 return maximumFractionDigits;
1148 * Sets the maximum number of digits allowed in the fraction portion of a
1149 * number. This must be >= minimumFractionDigits. If the
1150 * new value for maximumFractionDigits is less than the current value
1151 * of minimumFractionDigits, then minimumFractionDigits will also be set to
1153 * @param newValue the maximum number of fraction digits to be shown; if
1154 * less than zero, then zero is used. The concrete subclass may enforce an
1155 * upper limit to this value appropriate to the numeric type being formatted.
1156 * @see #getMaximumFractionDigits
1159 public void setMaximumFractionDigits(int newValue) {
1160 maximumFractionDigits = Math.max(0,newValue);
1161 if (maximumFractionDigits < minimumFractionDigits)
1162 minimumFractionDigits = maximumFractionDigits;
1166 * Returns the minimum number of digits allowed in the fraction portion of a
1167 * number. The default value is 0, which subclasses can override.
1168 * When formatting, if this value is not reached, numbers are padded on
1169 * the right with the locale-specific '0' character to ensure at least
1170 * this number of fraction digits. When parsing, this has no effect.
1171 * @return the minimum number of fraction digits
1172 * @see #setMinimumFractionDigits
1175 public int getMinimumFractionDigits() {
1176 return minimumFractionDigits;
1180 * Sets the minimum number of digits allowed in the fraction portion of a
1181 * number. This must be <= maximumFractionDigits. If the
1182 * new value for minimumFractionDigits exceeds the current value
1183 * of maximumFractionDigits, then maximumFractionDigits will also be set to
1185 * @param newValue the minimum number of fraction digits to be shown; if
1186 * less than zero, then zero is used. Subclasses might enforce an
1187 * upper limit to this value appropriate to the numeric type being formatted.
1188 * @see #getMinimumFractionDigits
1191 public void setMinimumFractionDigits(int newValue) {
1192 minimumFractionDigits = Math.max(0,newValue);
1193 if (maximumFractionDigits < minimumFractionDigits)
1194 maximumFractionDigits = minimumFractionDigits;
1198 * Sets the <tt>Currency</tt> object used to display currency
1199 * amounts. This takes effect immediately, if this format is a
1200 * currency format. If this format is not a currency format, then
1201 * the currency object is used if and when this object becomes a
1203 * @param theCurrency new currency object to use. May be null for
1207 public void setCurrency(Currency theCurrency) {
1208 currency = theCurrency;
1212 * Gets the <tt>Currency</tt> object used to display currency
1213 * amounts. This may be null.
1216 public Currency getCurrency() {
1221 * Returns the currency in effect for this formatter. Subclasses
1222 * should override this method as needed. Unlike getCurrency(),
1223 * this method should never return null.
1224 * @return a non-null Currency
1226 * @deprecated This API is ICU internal only.
1228 protected Currency getEffectiveCurrency() {
1229 Currency c = getCurrency();
1231 ULocale uloc = getLocale(ULocale.VALID_LOCALE);
1233 uloc = ULocale.getDefault();
1235 c = Currency.getInstance(uloc);
1241 * Get the rounding mode used in this NumberFormat. The default implementation of
1242 * tis method in NumberFormat always throws <code>UnsupportedOperationException</code>.
1243 * @return A rounding mode, between <code>BigDecimal.ROUND_UP</code>
1244 * and <code>BigDecimal.ROUND_UNNECESSARY</code>.
1245 * @see #setRoundingMode(int)
1248 public int getRoundingMode() {
1249 throw new UnsupportedOperationException("getRoundingMode must be implemented by the subclass implementation.");
1253 * Set the rounding mode used in this NumberFormat. The default implementation of
1254 * tis method in NumberFormat always throws <code>UnsupportedOperationException</code>.
1255 * @param roundingMode A rounding mode, between
1256 * <code>BigDecimal.ROUND_UP</code> and
1257 * <code>BigDecimal.ROUND_UNNECESSARY</code>.
1258 * @see #getRoundingMode()
1261 public void setRoundingMode(int roundingMode) {
1262 throw new UnsupportedOperationException("setRoundingMode must be implemented by the subclass implementation.");
1267 * Returns a specific style number format for a specific locale.
1268 * @param desiredLocale the specific locale.
1269 * @param choice number format style
1270 * @throws IllegalArgumentException if choice is not one of
1271 * NUMBERSTYLE, CURRENCYSTYLE,
1272 * PERCENTSTYLE, SCIENTIFICSTYLE,
1274 * ISOCURRENCYSTYLE, PLURALCURRENCYSTYLE,
1276 * @provisional This API might change or be removed in a future release.
1278 public static NumberFormat getInstance(ULocale desiredLocale, int choice) {
1279 if (choice < NUMBERSTYLE || choice > PLURALCURRENCYSTYLE) {
1280 throw new IllegalArgumentException("choice should be from NUMBERSTYLE to PLURALCURRENCYSTYLE");
1282 // if (shim == null) {
1283 // return createInstance(desiredLocale, choice);
1285 // // TODO: shims must call setLocale() on object they create
1286 // return getShim().createInstance(desiredLocale, choice);
1288 return getShim().createInstance(desiredLocale, choice);
1291 // =======================privates===============================
1294 static NumberFormat createInstance(ULocale desiredLocale, int choice) {
1295 // If the choice is PLURALCURRENCYSTYLE, the pattern is not a single
1296 // pattern, it is a pattern set, so we do not need to get them here.
1297 // If the choice is ISOCURRENCYSTYLE, the pattern is the currrency
1298 // pattern in the locale but by replacing the single currency sign
1299 // with double currency sign.
1300 String pattern = getPattern(desiredLocale, choice);
1301 DecimalFormatSymbols symbols = new DecimalFormatSymbols(desiredLocale);
1303 // Here we assume that the locale passed in is in the canonical
1304 // form, e.g: pt_PT_@currency=PTE not pt_PT_PREEURO
1305 // This style wont work for currency plural format.
1306 // For currency plural format, the pattern is get from
1307 // the locale (from CurrencyUnitPatterns) without override.
1308 if(choice == CURRENCYSTYLE || choice == ISOCURRENCYSTYLE){
1309 String temp = symbols.getCurrencyPattern();
1315 // replace single currency sign in the pattern with double currency sign
1316 // if the choice is ISOCURRENCYSTYLE.
1317 if (choice == ISOCURRENCYSTYLE) {
1318 pattern = Utility.replace(pattern, "\u00A4", doubleCurrencyStr);
1321 NumberingSystem ns = NumberingSystem.getInstance(desiredLocale);
1326 NumberFormat format;
1328 if ( ns != null && ns.isAlgorithmic()) {
1330 String nsRuleSetGroup;
1331 String nsRuleSetName;
1333 int desiredRulesType = RuleBasedNumberFormat.NUMBERING_SYSTEM;
1335 nsDesc = ns.getDescription();
1336 int firstSlash = nsDesc.indexOf("/");
1337 int lastSlash = nsDesc.lastIndexOf("/");
1339 if ( lastSlash > firstSlash ) {
1340 String nsLocID = nsDesc.substring(0,firstSlash);
1341 nsRuleSetGroup = nsDesc.substring(firstSlash+1,lastSlash);
1342 nsRuleSetName = nsDesc.substring(lastSlash+1);
1344 nsLoc = new ULocale(nsLocID);
1345 if ( nsRuleSetGroup.equals("SpelloutRules")) {
1346 desiredRulesType = RuleBasedNumberFormat.SPELLOUT;
1349 nsLoc = desiredLocale;
1350 nsRuleSetName = nsDesc;
1353 RuleBasedNumberFormat r = new RuleBasedNumberFormat(nsLoc,desiredRulesType);
1354 r.setDefaultRuleSet(nsRuleSetName);
1357 DecimalFormat f = new DecimalFormat(pattern, symbols, choice);
1358 // System.out.println("loc: " + desiredLocale + " choice: " + choice + " pat: " + pattern + " sym: " + symbols + " result: " + format);
1361 Add codes for the new method getIntegerInstance() [Richard/GCL]
1363 // TODO: revisit this -- this is almost certainly not the way we want
1364 // to do this. aliu 1/6/2004
1365 if (choice == INTEGERSTYLE) {
1366 f.setMaximumFractionDigits(0);
1367 f.setDecimalSeparatorAlwaysShown(false);
1368 f.setParseIntegerOnly(true);
1372 // TODO: the actual locale of the *pattern* may differ from that
1373 // for the *symbols*. For now, we use the data for the symbols.
1375 ULocale valid = symbols.getLocale(ULocale.VALID_LOCALE);
1376 ULocale actual = symbols.getLocale(ULocale.ACTUAL_LOCALE);
1377 format.setLocale(valid, actual);
1383 * Returns the pattern for the provided locale and choice.
1384 * @param forLocale the locale of the data.
1385 * @param choice the pattern format.
1386 * @return the pattern
1387 * @deprecated ICU 3.4 subclassers should override getPattern(ULocale, int) instead of this method.
1389 protected static String getPattern(Locale forLocale, int choice) {
1390 return getPattern(ULocale.forLocale(forLocale), choice);
1394 * Returns the pattern for the provided locale and choice.
1395 * @param forLocale the locale of the data.
1396 * @param choice the pattern format.
1397 * @return the pattern
1400 protected static String getPattern(ULocale forLocale, int choice) {
1402 /* The following code takes care of a few cases where the
1403 * resource data in the underlying JDK lags the new features
1404 * we have added to ICU4J: scientific notation, rounding, and
1405 * secondary grouping.
1407 * We detect these cases here and return various hard-coded
1408 * resource data. This is the simplest solution for now, but
1409 * it is not a good long-term mechanism.
1411 * We should replace this code with a data-driven mechanism
1412 * that reads the bundle com.ibm.icu.impl.data.LocaleElements
1413 * and parses an exception table that overrides the standard
1414 * data at java.text.resource.LocaleElements*.java.
1415 * Alternatively, we should create our own copy of the
1416 * resource data, and use that exclusively.
1419 // TEMPORARY, until we get scientific patterns into the main
1420 // resources: Retrieve scientific patterns from our resources.
1421 if (choice == SCIENTIFICSTYLE) {
1422 // Temporarily hard code; retrieve from resource later
1423 /*For ICU compatibility [Richard/GCL]*/
1425 // return NumberFormat.getBaseStringArray("NumberPatterns")[SCIENTIFICSTYLE];
1427 // TEMPORARY: Use rounding for Swiss currency
1428 //if (choice == CURRENCYSTYLE &&
1429 // forLocale.getCountry().equals("CH")) {
1430 // return "'Fr. '#,##0.05;'Fr.-'#,##0.05";
1432 // TEMPORARY: Special case IN number format
1433 //if (choice == NUMBERSTYLE &&
1434 // forLocale.getCountry().equals("IN")) {
1435 // return "#,##,##0.###";
1439 ICUResourceBundle rb = (ICUResourceBundle)UResourceBundle.
1440 getBundleInstance(ICUResourceBundle.ICU_BASE_NAME, forLocale);
1441 String[] numberPatterns = rb.getStringArray("NumberPatterns");
1444 // Try the cache first
1445 String[] numberPatterns = (String[]) cachedLocaleData.get(forLocale);
1446 if (numberPatterns == null) {
1447 OverlayBundle resource = new OverlayBundle(new String[]
1448 { "com.ibm.icu.impl.data.LocaleElements", RESOURCE_BASE }, forLocale);
1449 numberPatterns = resource.getStringArray("NumberPatterns");
1451 cachedLocaleData.put(forLocale, numberPatterns);
1456 Add codes for the new method getIntegerInstance() [Richard/GCL]
1458 /* for ISOCURRENCYSTYLE and PLURALCURRENCYSTYLE,
1459 * the pattern is the same as the pattern of CURRENCYSTYLE
1460 * but by replacing the single currency sign with
1461 * double currency sign or triple currency sign.
1463 int entry = (choice == INTEGERSTYLE) ? NUMBERSTYLE :
1464 ((choice == ISOCURRENCYSTYLE || choice == PLURALCURRENCYSTYLE)?
1465 CURRENCYSTYLE : choice); //[Richard/GCL]
1466 return numberPatterns[entry]; //[Richard/GCL]
1470 * First, read in the default serializable data.
1472 * Then, if <code>serialVersionOnStream</code> is less than 1, indicating that
1473 * the stream was written by JDK 1.1,
1474 * set the <code>int</code> fields such as <code>maximumIntegerDigits</code>
1475 * to be equal to the <code>byte</code> fields such as <code>maxIntegerDigits</code>,
1476 * since the <code>int</code> fields were not present in JDK 1.1.
1477 * Finally, set serialVersionOnStream back to the maximum allowed value so that
1478 * default serialization will work properly if this object is streamed out again.
1480 private void readObject(ObjectInputStream stream)
1481 throws IOException, ClassNotFoundException
1483 stream.defaultReadObject();
1485 // we don't have serialization data for this format
1486 if (serialVersionOnStream < 1) {
1487 // Didn't have additional int fields, reassign to use them.
1488 maximumIntegerDigits = maxIntegerDigits;
1489 minimumIntegerDigits = minIntegerDigits;
1490 maximumFractionDigits = maxFractionDigits;
1491 minimumFractionDigits = minFractionDigits;
1495 Validate the min and max fields [Richard/GCL]
1497 if (minimumIntegerDigits > maximumIntegerDigits ||
1498 minimumFractionDigits > maximumFractionDigits ||
1499 minimumIntegerDigits < 0 || minimumFractionDigits < 0) {
1500 throw new InvalidObjectException("Digit count range invalid");
1502 serialVersionOnStream = currentSerialVersion;
1506 * Write out the default serializable data, after first setting
1507 * the <code>byte</code> fields such as <code>maxIntegerDigits</code> to be
1508 * equal to the <code>int</code> fields such as <code>maximumIntegerDigits</code>
1509 * (or to <code>Byte.MAX_VALUE</code>, whichever is smaller), for compatibility
1510 * with the JDK 1.1 version of the stream format.
1512 private void writeObject(ObjectOutputStream stream)
1515 maxIntegerDigits = (maximumIntegerDigits > Byte.MAX_VALUE) ? Byte.MAX_VALUE :
1516 (byte)maximumIntegerDigits;
1517 minIntegerDigits = (minimumIntegerDigits > Byte.MAX_VALUE) ? Byte.MAX_VALUE :
1518 (byte)minimumIntegerDigits;
1519 maxFractionDigits = (maximumFractionDigits > Byte.MAX_VALUE) ? Byte.MAX_VALUE :
1520 (byte)maximumFractionDigits;
1521 minFractionDigits = (minimumFractionDigits > Byte.MAX_VALUE) ? Byte.MAX_VALUE :
1522 (byte)minimumFractionDigits;
1523 stream.defaultWriteObject();
1526 // Unused -- Alan 2003-05
1528 // * Cache to hold the NumberPatterns of a Locale.
1530 // private static final Hashtable cachedLocaleData = new Hashtable(3);
1532 private static final char[] doubleCurrencySign = {0xA4, 0xA4};
1533 private static final String doubleCurrencyStr = new String(doubleCurrencySign);
1536 Add Field for the new method getIntegerInstance() [Richard/GCL]
1540 * True if the the grouping (i.e. thousands) separator is used when
1541 * formatting and parsing numbers.
1544 * @see #isGroupingUsed
1546 private boolean groupingUsed = true;
1549 * The maximum number of digits allowed in the integer portion of a
1550 * number. <code>maxIntegerDigits</code> must be greater than or equal to
1551 * <code>minIntegerDigits</code>.
1553 * <strong>Note:</strong> This field exists only for serialization
1554 * compatibility with JDK 1.1. In JDK 1.2 and higher, the new
1555 * <code>int</code> field <code>maximumIntegerDigits</code> is used instead.
1556 * When writing to a stream, <code>maxIntegerDigits</code> is set to
1557 * <code>maximumIntegerDigits</code> or <code>Byte.MAX_VALUE</code>,
1558 * whichever is smaller. When reading from a stream, this field is used
1559 * only if <code>serialVersionOnStream</code> is less than 1.
1562 * @see #getMaximumIntegerDigits
1564 private byte maxIntegerDigits = 40;
1567 * The minimum number of digits allowed in the integer portion of a
1568 * number. <code>minimumIntegerDigits</code> must be less than or equal to
1569 * <code>maximumIntegerDigits</code>.
1571 * <strong>Note:</strong> This field exists only for serialization
1572 * compatibility with JDK 1.1. In JDK 1.2 and higher, the new
1573 * <code>int</code> field <code>minimumIntegerDigits</code> is used instead.
1574 * When writing to a stream, <code>minIntegerDigits</code> is set to
1575 * <code>minimumIntegerDigits</code> or <code>Byte.MAX_VALUE</code>,
1576 * whichever is smaller. When reading from a stream, this field is used
1577 * only if <code>serialVersionOnStream</code> is less than 1.
1580 * @see #getMinimumIntegerDigits
1582 private byte minIntegerDigits = 1;
1585 * The maximum number of digits allowed in the fractional portion of a
1586 * number. <code>maximumFractionDigits</code> must be greater than or equal to
1587 * <code>minimumFractionDigits</code>.
1589 * <strong>Note:</strong> This field exists only for serialization
1590 * compatibility with JDK 1.1. In JDK 1.2 and higher, the new
1591 * <code>int</code> field <code>maximumFractionDigits</code> is used instead.
1592 * When writing to a stream, <code>maxFractionDigits</code> is set to
1593 * <code>maximumFractionDigits</code> or <code>Byte.MAX_VALUE</code>,
1594 * whichever is smaller. When reading from a stream, this field is used
1595 * only if <code>serialVersionOnStream</code> is less than 1.
1598 * @see #getMaximumFractionDigits
1600 private byte maxFractionDigits = 3; // invariant, >= minFractionDigits
1603 * The minimum number of digits allowed in the fractional portion of a
1604 * number. <code>minimumFractionDigits</code> must be less than or equal to
1605 * <code>maximumFractionDigits</code>.
1607 * <strong>Note:</strong> This field exists only for serialization
1608 * compatibility with JDK 1.1. In JDK 1.2 and higher, the new
1609 * <code>int</code> field <code>minimumFractionDigits</code> is used instead.
1610 * When writing to a stream, <code>minFractionDigits</code> is set to
1611 * <code>minimumFractionDigits</code> or <code>Byte.MAX_VALUE</code>,
1612 * whichever is smaller. When reading from a stream, this field is used
1613 * only if <code>serialVersionOnStream</code> is less than 1.
1616 * @see #getMinimumFractionDigits
1618 private byte minFractionDigits = 0;
1621 * True if this format will parse numbers as integers only.
1624 * @see #isParseIntegerOnly
1626 private boolean parseIntegerOnly = false;
1628 // new fields for 1.2. byte is too small for integer digits.
1631 * The maximum number of digits allowed in the integer portion of a
1632 * number. <code>maximumIntegerDigits</code> must be greater than or equal to
1633 * <code>minimumIntegerDigits</code>.
1636 * @see #getMaximumIntegerDigits
1638 private int maximumIntegerDigits = 40;
1641 * The minimum number of digits allowed in the integer portion of a
1642 * number. <code>minimumIntegerDigits</code> must be less than or equal to
1643 * <code>maximumIntegerDigits</code>.
1646 * @see #getMinimumIntegerDigits
1648 private int minimumIntegerDigits = 1;
1651 * The maximum number of digits allowed in the fractional portion of a
1652 * number. <code>maximumFractionDigits</code> must be greater than or equal to
1653 * <code>minimumFractionDigits</code>.
1656 * @see #getMaximumFractionDigits
1658 private int maximumFractionDigits = 3; // invariant, >= minFractionDigits
1661 * The minimum number of digits allowed in the fractional portion of a
1662 * number. <code>minimumFractionDigits</code> must be less than or equal to
1663 * <code>maximumFractionDigits</code>.
1666 * @see #getMinimumFractionDigits
1668 private int minimumFractionDigits = 0;
1671 * Currency object used to format currencies. Subclasses may
1672 * ignore this if they are not currency formats. This will be
1673 * null unless a subclass sets it to a non-null value.
1676 private Currency currency;
1678 static final int currentSerialVersion = 1;
1681 * Describes the version of <code>NumberFormat</code> present on the stream.
1682 * Possible values are:
1684 * <li><b>0</b> (or uninitialized): the JDK 1.1 version of the stream format.
1685 * In this version, the <code>int</code> fields such as
1686 * <code>maximumIntegerDigits</code> were not present, and the <code>byte</code>
1687 * fields such as <code>maxIntegerDigits</code> are used instead.
1689 * <li><b>1</b>: the JDK 1.2 version of the stream format. The values of the
1690 * <code>byte</code> fields such as <code>maxIntegerDigits</code> are ignored,
1691 * and the <code>int</code> fields such as <code>maximumIntegerDigits</code>
1694 * When streaming out a <code>NumberFormat</code>, the most recent format
1695 * (corresponding to the highest allowable <code>serialVersionOnStream</code>)
1696 * is always written.
1700 private int serialVersionOnStream = currentSerialVersion;
1702 // Removed "implements Cloneable" clause. Needs to update serialization
1703 // ID for backward compatibility.
1704 private static final long serialVersionUID = -2308460125733713944L;
1707 * Empty constructor. Public for compatibily with JDK which lets the
1708 * compiler generate a default public constructor even though this is
1709 * an abstract class.
1712 public NumberFormat() {
1716 private boolean parseStrict;
1718 //#if defined(FOUNDATION10) || defined(J2SE13)
1721 * The instances of this inner class are used as attribute keys and values
1722 * in AttributedCharacterIterator that
1723 * NumberFormat.formatToCharacterIterator() method returns.
1725 * There is no public constructor to this class, the only instances are the
1726 * constants defined here.
1730 public static class Field extends Format.Field {
1731 // generated by serialver from JDK 1.4.1_01
1732 static final long serialVersionUID = -4516273749929385842L;
1737 public static final Field SIGN = new Field("sign");
1742 public static final Field INTEGER = new Field("integer");
1747 public static final Field FRACTION = new Field("fraction");
1752 public static final Field EXPONENT = new Field("exponent");
1757 public static final Field EXPONENT_SIGN = new Field("exponent sign");
1762 public static final Field EXPONENT_SYMBOL = new Field("exponent symbol");
1767 public static final Field DECIMAL_SEPARATOR = new Field("decimal separator");
1771 public static final Field GROUPING_SEPARATOR = new Field("grouping separator");
1776 public static final Field PERCENT = new Field("percent");
1781 public static final Field PERMILLE = new Field("per mille");
1786 public static final Field CURRENCY = new Field("currency");
1789 * Constructs a new instance of NumberFormat.Field with the given field
1793 protected Field(String fieldName) {
1798 * serizalization method resolve instances to the constant
1799 * NumberFormat.Field values
1802 protected Object readResolve() throws InvalidObjectException {
1803 if (this.getName().equals(INTEGER.getName()))
1805 if (this.getName().equals(FRACTION.getName()))
1807 if (this.getName().equals(EXPONENT.getName()))
1809 if (this.getName().equals(EXPONENT_SIGN.getName()))
1810 return EXPONENT_SIGN;
1811 if (this.getName().equals(EXPONENT_SYMBOL.getName()))
1812 return EXPONENT_SYMBOL;
1813 if (this.getName().equals(CURRENCY.getName()))
1815 if (this.getName().equals(DECIMAL_SEPARATOR.getName()))
1816 return DECIMAL_SEPARATOR;
1817 if (this.getName().equals(GROUPING_SEPARATOR.getName()))
1818 return GROUPING_SEPARATOR;
1819 if (this.getName().equals(PERCENT.getName()))
1821 if (this.getName().equals(PERMILLE.getName()))
1823 if (this.getName().equals(SIGN.getName()))
1826 throw new InvalidObjectException("An invalid object.");