History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/java/text/NumberFormat.java (1 of 18352 files). Show all

Unified · Split

java/pkg/java/text/NumberFormat.java+1162−0
@@ -0,0 +1,1162 @@
1+/*
2+ * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+/*
27+ * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
28+ * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
29+ *
30+ * The original version of this source code and documentation is copyrighted
31+ * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
32+ * materials are provided under terms of a License Agreement between Taligent
33+ * and Sun. This technology is protected by multiple US and International
34+ * patents. This notice and attribution to Taligent may not be removed.
35+ * Taligent is a registered trademark of Taligent, Inc.
36+ *
37+ */
38+
39+package java.text;
40+
41+import java.io.InvalidObjectException;
42+import java.io.IOException;
43+import java.io.ObjectInputStream;
44+import java.io.ObjectOutputStream;
45+import java.math.BigInteger;
46+import java.math.RoundingMode;
47+import java.text.spi.NumberFormatProvider;
48+import java.util.Currency;
49+import java.util.HashMap;
50+import java.util.Hashtable;
51+import java.util.Locale;
52+import java.util.Map;
53+import java.util.ResourceBundle;
54+import java.util.concurrent.atomic.AtomicInteger;
55+import java.util.concurrent.atomic.AtomicLong;
56+import java.util.spi.LocaleServiceProvider;
57+import sun.util.LocaleServiceProviderPool;
58+import sun.util.resources.LocaleData;
59+
60+/**
61+ * <code>NumberFormat</code> is the abstract base class for all number
62+ * formats. This class provides the interface for formatting and parsing
63+ * numbers. <code>NumberFormat</code> also provides methods for determining
64+ * which locales have number formats, and what their names are.
65+ *
66+ * <p>
67+ * <code>NumberFormat</code> helps you to format and parse numbers for any locale.
68+ * Your code can be completely independent of the locale conventions for
69+ * decimal points, thousands-separators, or even the particular decimal
70+ * digits used, or whether the number format is even decimal.
71+ *
72+ * <p>
73+ * To format a number for the current Locale, use one of the factory
74+ * class methods:
75+ * <blockquote>
76+ * <pre>
77+ * myString = NumberFormat.getInstance().format(myNumber);
78+ * </pre>
79+ * </blockquote>
80+ * If you are formatting multiple numbers, it is
81+ * more efficient to get the format and use it multiple times so that
82+ * the system doesn't have to fetch the information about the local
83+ * language and country conventions multiple times.
84+ * <blockquote>
85+ * <pre>
86+ * NumberFormat nf = NumberFormat.getInstance();
87+ * for (int i = 0; i < myNumber.length; ++i) {
88+ * output.println(nf.format(myNumber[i]) + "; ");
89+ * }
90+ * </pre>
91+ * </blockquote>
92+ * To format a number for a different Locale, specify it in the
93+ * call to <code>getInstance</code>.
94+ * <blockquote>
95+ * <pre>
96+ * NumberFormat nf = NumberFormat.getInstance(Locale.FRENCH);
97+ * </pre>
98+ * </blockquote>
99+ * You can also use a <code>NumberFormat</code> to parse numbers:
100+ * <blockquote>
101+ * <pre>
102+ * myNumber = nf.parse(myString);
103+ * </pre>
104+ * </blockquote>
105+ * Use <code>getInstance</code> or <code>getNumberInstance</code> to get the
106+ * normal number format. Use <code>getIntegerInstance</code> to get an
107+ * integer number format. Use <code>getCurrencyInstance</code> to get the
108+ * currency number format. And use <code>getPercentInstance</code> to get a
109+ * format for displaying percentages. With this format, a fraction like
110+ * 0.53 is displayed as 53%.
111+ *
112+ * <p>
113+ * You can also control the display of numbers with such methods as
114+ * <code>setMinimumFractionDigits</code>.
115+ * If you want even more control over the format or parsing,
116+ * or want to give your users more control,
117+ * you can try casting the <code>NumberFormat</code> you get from the factory methods
118+ * to a <code>DecimalFormat</code>. This will work for the vast majority
119+ * of locales; just remember to put it in a <code>try</code> block in case you
120+ * encounter an unusual one.
121+ *
122+ * <p>
123+ * NumberFormat and DecimalFormat are designed such that some controls
124+ * work for formatting and others work for parsing. The following is
125+ * the detailed description for each these control methods,
126+ * <p>
127+ * setParseIntegerOnly : only affects parsing, e.g.
128+ * if true, "3456.78" -> 3456 (and leaves the parse position just after index 6)
129+ * if false, "3456.78" -> 3456.78 (and leaves the parse position just after index 8)
130+ * This is independent of formatting. If you want to not show a decimal point
131+ * where there might be no digits after the decimal point, use
132+ * setDecimalSeparatorAlwaysShown.
133+ * <p>
134+ * setDecimalSeparatorAlwaysShown : only affects formatting, and only where
135+ * there might be no digits after the decimal point, such as with a pattern
136+ * like "#,##0.##", e.g.,
137+ * if true, 3456.00 -> "3,456."
138+ * if false, 3456.00 -> "3456"
139+ * This is independent of parsing. If you want parsing to stop at the decimal
140+ * point, use setParseIntegerOnly.
141+ *
142+ * <p>
143+ * You can also use forms of the <code>parse</code> and <code>format</code>
144+ * methods with <code>ParsePosition</code> and <code>FieldPosition</code> to
145+ * allow you to:
146+ * <ul>
147+ * <li> progressively parse through pieces of a string
148+ * <li> align the decimal point and other areas
149+ * </ul>
150+ * For example, you can align numbers in two ways:
151+ * <ol>
152+ * <li> If you are using a monospaced font with spacing for alignment,
153+ * you can pass the <code>FieldPosition</code> in your format call, with
154+ * <code>field</code> = <code>INTEGER_FIELD</code>. On output,
155+ * <code>getEndIndex</code> will be set to the offset between the
156+ * last character of the integer and the decimal. Add
157+ * (desiredSpaceCount - getEndIndex) spaces at the front of the string.
158+ *
159+ * <li> If you are using proportional fonts,
160+ * instead of padding with spaces, measure the width
161+ * of the string in pixels from the start to <code>getEndIndex</code>.
162+ * Then move the pen by
163+ * (desiredPixelWidth - widthToAlignmentPoint) before drawing the text.
164+ * It also works where there is no decimal, but possibly additional
165+ * characters at the end, e.g., with parentheses in negative
166+ * numbers: "(12)" for -12.
167+ * </ol>
168+ *
169+ * <h4><a name="synchronization">Synchronization</a></h4>
170+ *
171+ * <p>
172+ * Number formats are generally not synchronized.
173+ * It is recommended to create separate format instances for each thread.
174+ * If multiple threads access a format concurrently, it must be synchronized
175+ * externally.
176+ *
177+ * @see DecimalFormat
178+ * @see ChoiceFormat
179+ * @author Mark Davis
180+ * @author Helena Shih
181+ */
182+public abstract class NumberFormat extends Format {
183+
184+ /**
185+ * Field constant used to construct a FieldPosition object. Signifies that
186+ * the position of the integer part of a formatted number should be returned.
187+ * @see java.text.FieldPosition
188+ */
189+ public static final int INTEGER_FIELD = 0;
190+
191+ /**
192+ * Field constant used to construct a FieldPosition object. Signifies that
193+ * the position of the fraction part of a formatted number should be returned.
194+ * @see java.text.FieldPosition
195+ */
196+ public static final int FRACTION_FIELD = 1;
197+
198+ /**
199+ * Sole constructor. (For invocation by subclass constructors, typically
200+ * implicit.)
201+ */
202+ protected NumberFormat() {
203+ }
204+
205+ /**
206+ * Formats a number and appends the resulting text to the given string
207+ * buffer.
208+ * The number can be of any subclass of {@link java.lang.Number}.
209+ * <p>
210+ * This implementation extracts the number's value using
211+ * {@link java.lang.Number#longValue()} for all integral type values that
212+ * can be converted to <code>long</code> without loss of information,
213+ * including <code>BigInteger</code> values with a
214+ * {@link java.math.BigInteger#bitLength() bit length} of less than 64,
215+ * and {@link java.lang.Number#doubleValue()} for all other types. It
216+ * then calls
217+ * {@link #format(long,java.lang.StringBuffer,java.text.FieldPosition)}
218+ * or {@link #format(double,java.lang.StringBuffer,java.text.FieldPosition)}.
219+ * This may result in loss of magnitude information and precision for
220+ * <code>BigInteger</code> and <code>BigDecimal</code> values.
221+ * @param number the number to format
222+ * @param toAppendTo the <code>StringBuffer</code> to which the formatted
223+ * text is to be appended
224+ * @param pos On input: an alignment field, if desired.
225+ * On output: the offsets of the alignment field.
226+ * @return the value passed in as <code>toAppendTo</code>
227+ * @exception IllegalArgumentException if <code>number</code> is
228+ * null or not an instance of <code>Number</code>.
229+ * @exception NullPointerException if <code>toAppendTo</code> or
230+ * <code>pos</code> is null
231+ * @exception ArithmeticException if rounding is needed with rounding
232+ * mode being set to RoundingMode.UNNECESSARY
233+ * @see java.text.FieldPosition
234+ */
235+ public StringBuffer format(Object number,
236+ StringBuffer toAppendTo,
237+ FieldPosition pos) {
238+ if (number instanceof Long || number instanceof Integer ||
239+ number instanceof Short || number instanceof Byte ||
240+ number instanceof AtomicInteger || number instanceof AtomicLong ||
241+ (number instanceof BigInteger &&
242+ ((BigInteger)number).bitLength() < 64)) {
243+ return format(((Number)number).longValue(), toAppendTo, pos);
244+ } else if (number instanceof Number) {
245+ return format(((Number)number).doubleValue(), toAppendTo, pos);
246+ } else {
247+ throw new IllegalArgumentException("Cannot format given Object as a Number");
248+ }
249+ }
250+
251+ /**
252+ * Parses text from a string to produce a <code>Number</code>.
253+ * <p>
254+ * The method attempts to parse text starting at the index given by
255+ * <code>pos</code>.
256+ * If parsing succeeds, then the index of <code>pos</code> is updated
257+ * to the index after the last character used (parsing does not necessarily
258+ * use all characters up to the end of the string), and the parsed
259+ * number is returned. The updated <code>pos</code> can be used to
260+ * indicate the starting point for the next call to this method.
261+ * If an error occurs, then the index of <code>pos</code> is not
262+ * changed, the error index of <code>pos</code> is set to the index of
263+ * the character where the error occurred, and null is returned.
264+ * <p>
265+ * See the {@link #parse(String, ParsePosition)} method for more information
266+ * on number parsing.
267+ *
268+ * @param source A <code>String</code>, part of which should be parsed.
269+ * @param pos A <code>ParsePosition</code> object with index and error
270+ * index information as described above.
271+ * @return A <code>Number</code> parsed from the string. In case of
272+ * error, returns null.
273+ * @exception NullPointerException if <code>pos</code> is null.
274+ */
275+ public final Object parseObject(String source, ParsePosition pos) {
276+ return parse(source, pos);
277+ }
278+
279+ /**
280+ * Specialization of format.
281+ * @exception ArithmeticException if rounding is needed with rounding
282+ * mode being set to RoundingMode.UNNECESSARY
283+ * @see java.text.Format#format
284+ */
285+ public final String format(double number) {
286+ return format(number, new StringBuffer(),
287+ DontCareFieldPosition.INSTANCE).toString();
288+ }
289+
290+ /**
291+ * Specialization of format.
292+ * @exception ArithmeticException if rounding is needed with rounding
293+ * mode being set to RoundingMode.UNNECESSARY
294+ * @see java.text.Format#format
295+ */
296+ public final String format(long number) {
297+ return format(number, new StringBuffer(),
298+ DontCareFieldPosition.INSTANCE).toString();
299+ }
300+
301+ /**
302+ * Specialization of format.
303+ * @exception ArithmeticException if rounding is needed with rounding
304+ * mode being set to RoundingMode.UNNECESSARY
305+ * @see java.text.Format#format
306+ */
307+ public abstract StringBuffer format(double number,
308+ StringBuffer toAppendTo,
309+ FieldPosition pos);
310+
311+ /**
312+ * Specialization of format.
313+ * @exception ArithmeticException if rounding is needed with rounding
314+ * mode being set to RoundingMode.UNNECESSARY
315+ * @see java.text.Format#format
316+ */
317+ public abstract StringBuffer format(long number,
318+ StringBuffer toAppendTo,
319+ FieldPosition pos);
320+
321+ /**
322+ * Returns a Long if possible (e.g., within the range [Long.MIN_VALUE,
323+ * Long.MAX_VALUE] and with no decimals), otherwise a Double.
324+ * If IntegerOnly is set, will stop at a decimal
325+ * point (or equivalent; e.g., for rational numbers "1 2/3", will stop
326+ * after the 1).
327+ * Does not throw an exception; if no object can be parsed, index is
328+ * unchanged!
329+ * @see java.text.NumberFormat#isParseIntegerOnly
330+ * @see java.text.Format#parseObject
331+ */
332+ public abstract Number parse(String source, ParsePosition parsePosition);
333+
334+ /**
335+ * Parses text from the beginning of the given string to produce a number.
336+ * The method may not use the entire text of the given string.
337+ * <p>
338+ * See the {@link #parse(String, ParsePosition)} method for more information
339+ * on number parsing.
340+ *
341+ * @param source A <code>String</code> whose beginning should be parsed.
342+ * @return A <code>Number</code> parsed from the string.
343+ * @exception ParseException if the beginning of the specified string
344+ * cannot be parsed.
345+ */
346+ public Number parse(String source) throws ParseException {
347+ ParsePosition parsePosition = new ParsePosition(0);
348+ Number result = parse(source, parsePosition);
349+ if (parsePosition.index == 0) {
350+ throw new ParseException("Unparseable number: \"" + source + "\"",
351+ parsePosition.errorIndex);
352+ }
353+ return result;
354+ }
355+
356+ /**
357+ * Returns true if this format will parse numbers as integers only.
358+ * For example in the English locale, with ParseIntegerOnly true, the
359+ * string "1234." would be parsed as the integer value 1234 and parsing
360+ * would stop at the "." character. Of course, the exact format accepted
361+ * by the parse operation is locale dependant and determined by sub-classes
362+ * of NumberFormat.
363+ */
364+ public boolean isParseIntegerOnly() {
365+ return parseIntegerOnly;
366+ }
367+
368+ /**
369+ * Sets whether or not numbers should be parsed as integers only.
370+ * @see #isParseIntegerOnly
371+ */
372+ public void setParseIntegerOnly(boolean value) {
373+ parseIntegerOnly = value;
374+ }
375+
376+ //============== Locale Stuff =====================
377+
378+ /**
379+ * Returns a general-purpose number format for the current default locale.
380+ * This is the same as calling
381+ * {@link #getNumberInstance() getNumberInstance()}.
382+ */
383+ public final static NumberFormat getInstance() {
384+ return getInstance(Locale.getDefault(Locale.Category.FORMAT), NUMBERSTYLE);
385+ }
386+
387+ /**
388+ * Returns a general-purpose number format for the specified locale.
389+ * This is the same as calling
390+ * {@link #getNumberInstance(java.util.Locale) getNumberInstance(inLocale)}.
391+ */
392+ public static NumberFormat getInstance(Locale inLocale) {
393+ return getInstance(inLocale, NUMBERSTYLE);
394+ }
395+
396+ /**
397+ * Returns a general-purpose number format for the current default locale.
398+ */
399+ public final static NumberFormat getNumberInstance() {
400+ return getInstance(Locale.getDefault(Locale.Category.FORMAT), NUMBERSTYLE);
401+ }
402+
403+ /**
404+ * Returns a general-purpose number format for the specified locale.
405+ */
406+ public static NumberFormat getNumberInstance(Locale inLocale) {
407+ return getInstance(inLocale, NUMBERSTYLE);
408+ }
409+
410+ /**
411+ * Returns an integer number format for the current default locale. The
412+ * returned number format is configured to round floating point numbers
413+ * to the nearest integer using half-even rounding (see {@link
414+ * java.math.RoundingMode#HALF_EVEN RoundingMode.HALF_EVEN}) for formatting,
415+ * and to parse only the integer part of an input string (see {@link
416+ * #isParseIntegerOnly isParseIntegerOnly}).
417+ *
418+ * @see #getRoundingMode()
419+ * @return a number format for integer values
420+ * @since 1.4
421+ */
422+ public final static NumberFormat getIntegerInstance() {
423+ return getInstance(Locale.getDefault(Locale.Category.FORMAT), INTEGERSTYLE);
424+ }
425+
426+ /**
427+ * Returns an integer number format for the specified locale. The
428+ * returned number format is configured to round floating point numbers
429+ * to the nearest integer using half-even rounding (see {@link
430+ * java.math.RoundingMode#HALF_EVEN RoundingMode.HALF_EVEN}) for formatting,
431+ * and to parse only the integer part of an input string (see {@link
432+ * #isParseIntegerOnly isParseIntegerOnly}).
433+ *
434+ * @see #getRoundingMode()
435+ * @return a number format for integer values
436+ * @since 1.4
437+ */
438+ public static NumberFormat getIntegerInstance(Locale inLocale) {
439+ return getInstance(inLocale, INTEGERSTYLE);
440+ }
441+
442+ /**
443+ * Returns a currency format for the current default locale.
444+ */
445+ public final static NumberFormat getCurrencyInstance() {
446+ return getInstance(Locale.getDefault(Locale.Category.FORMAT), CURRENCYSTYLE);
447+ }
448+
449+ /**
450+ * Returns a currency format for the specified locale.
451+ */
452+ public static NumberFormat getCurrencyInstance(Locale inLocale) {
453+ return getInstance(inLocale, CURRENCYSTYLE);
454+ }
455+
456+ /**
457+ * Returns a percentage format for the current default locale.
458+ */
459+ public final static NumberFormat getPercentInstance() {
460+ return getInstance(Locale.getDefault(Locale.Category.FORMAT), PERCENTSTYLE);
461+ }
462+
463+ /**
464+ * Returns a percentage format for the specified locale.
465+ */
466+ public static NumberFormat getPercentInstance(Locale inLocale) {
467+ return getInstance(inLocale, PERCENTSTYLE);
468+ }
469+
470+ /**
471+ * Returns a scientific format for the current default locale.
472+ */
473+ /*public*/ final static NumberFormat getScientificInstance() {
474+ return getInstance(Locale.getDefault(Locale.Category.FORMAT), SCIENTIFICSTYLE);
475+ }
476+
477+ /**
478+ * Returns a scientific format for the specified locale.
479+ */
480+ /*public*/ static NumberFormat getScientificInstance(Locale inLocale) {
481+ return getInstance(inLocale, SCIENTIFICSTYLE);
482+ }
483+
484+ /**
485+ * Returns an array of all locales for which the
486+ * <code>get*Instance</code> methods of this class can return
487+ * localized instances.
488+ * The returned array represents the union of locales supported by the Java
489+ * runtime and by installed
490+ * {@link java.text.spi.NumberFormatProvider NumberFormatProvider} implementations.
491+ * It must contain at least a <code>Locale</code> instance equal to
492+ * {@link java.util.Locale#US Locale.US}.
493+ *
494+ * @return An array of locales for which localized
495+ * <code>NumberFormat</code> instances are available.
496+ */
497+ public static Locale[] getAvailableLocales() {
498+ LocaleServiceProviderPool pool =
499+ LocaleServiceProviderPool.getPool(NumberFormatProvider.class);
500+ return pool.getAvailableLocales();
501+ }
502+
503+ /**
504+ * Overrides hashCode
505+ */
506+ public int hashCode() {
507+ return maximumIntegerDigits * 37 + maxFractionDigits;
508+ // just enough fields for a reasonable distribution
509+ }
510+
511+ /**
512+ * Overrides equals
513+ */
514+ public boolean equals(Object obj) {
515+ if (obj == null) {
516+ return false;
517+ }
518+ if (this == obj) {
519+ return true;
520+ }
521+ if (getClass() != obj.getClass()) {
522+ return false;
523+ }
524+ NumberFormat other = (NumberFormat) obj;
525+ return (maximumIntegerDigits == other.maximumIntegerDigits
526+ && minimumIntegerDigits == other.minimumIntegerDigits
527+ && maximumFractionDigits == other.maximumFractionDigits
528+ && minimumFractionDigits == other.minimumFractionDigits
529+ && groupingUsed == other.groupingUsed
530+ && parseIntegerOnly == other.parseIntegerOnly);
531+ }
532+
533+ /**
534+ * Overrides Cloneable
535+ */
536+ public Object clone() {
537+ NumberFormat other = (NumberFormat) super.clone();
538+ return other;
539+ }
540+
541+ /**
542+ * Returns true if grouping is used in this format. For example, in the
543+ * English locale, with grouping on, the number 1234567 might be formatted
544+ * as "1,234,567". The grouping separator as well as the size of each group
545+ * is locale dependant and is determined by sub-classes of NumberFormat.
546+ * @see #setGroupingUsed
547+ */
548+ public boolean isGroupingUsed() {
549+ return groupingUsed;
550+ }
551+
552+ /**
553+ * Set whether or not grouping will be used in this format.
554+ * @see #isGroupingUsed
555+ */
556+ public void setGroupingUsed(boolean newValue) {
557+ groupingUsed = newValue;
558+ }
559+
560+ /**
561+ * Returns the maximum number of digits allowed in the integer portion of a
562+ * number.
563+ * @see #setMaximumIntegerDigits
564+ */
565+ public int getMaximumIntegerDigits() {
566+ return maximumIntegerDigits;
567+ }
568+
569+ /**
570+ * Sets the maximum number of digits allowed in the integer portion of a
571+ * number. maximumIntegerDigits must be >= minimumIntegerDigits. If the
572+ * new value for maximumIntegerDigits is less than the current value
573+ * of minimumIntegerDigits, then minimumIntegerDigits will also be set to
574+ * the new value.
575+ * @param newValue the maximum number of integer digits to be shown; if
576+ * less than zero, then zero is used. The concrete subclass may enforce an
577+ * upper limit to this value appropriate to the numeric type being formatted.
578+ * @see #getMaximumIntegerDigits
579+ */
580+ public void setMaximumIntegerDigits(int newValue) {
581+ maximumIntegerDigits = Math.max(0,newValue);
582+ if (minimumIntegerDigits > maximumIntegerDigits) {
583+ minimumIntegerDigits = maximumIntegerDigits;
584+ }
585+ }
586+
587+ /**
588+ * Returns the minimum number of digits allowed in the integer portion of a
589+ * number.
590+ * @see #setMinimumIntegerDigits
591+ */
592+ public int getMinimumIntegerDigits() {
593+ return minimumIntegerDigits;
594+ }
595+
596+ /**
597+ * Sets the minimum number of digits allowed in the integer portion of a
598+ * number. minimumIntegerDigits must be <= maximumIntegerDigits. If the
599+ * new value for minimumIntegerDigits exceeds the current value
600+ * of maximumIntegerDigits, then maximumIntegerDigits will also be set to
601+ * the new value
602+ * @param newValue the minimum number of integer digits to be shown; if
603+ * less than zero, then zero is used. The concrete subclass may enforce an
604+ * upper limit to this value appropriate to the numeric type being formatted.
605+ * @see #getMinimumIntegerDigits
606+ */
607+ public void setMinimumIntegerDigits(int newValue) {
608+ minimumIntegerDigits = Math.max(0,newValue);
609+ if (minimumIntegerDigits > maximumIntegerDigits) {
610+ maximumIntegerDigits = minimumIntegerDigits;
611+ }
612+ }
613+
614+ /**
615+ * Returns the maximum number of digits allowed in the fraction portion of a
616+ * number.
617+ * @see #setMaximumFractionDigits
618+ */
619+ public int getMaximumFractionDigits() {
620+ return maximumFractionDigits;
621+ }
622+
623+ /**
624+ * Sets the maximum number of digits allowed in the fraction portion of a
625+ * number. maximumFractionDigits must be >= minimumFractionDigits. If the
626+ * new value for maximumFractionDigits is less than the current value
627+ * of minimumFractionDigits, then minimumFractionDigits will also be set to
628+ * the new value.
629+ * @param newValue the maximum number of fraction digits to be shown; if
630+ * less than zero, then zero is used. The concrete subclass may enforce an
631+ * upper limit to this value appropriate to the numeric type being formatted.
632+ * @see #getMaximumFractionDigits
633+ */
634+ public void setMaximumFractionDigits(int newValue) {
635+ maximumFractionDigits = Math.max(0,newValue);
636+ if (maximumFractionDigits < minimumFractionDigits) {
637+ minimumFractionDigits = maximumFractionDigits;
638+ }
639+ }
640+
641+ /**
642+ * Returns the minimum number of digits allowed in the fraction portion of a
643+ * number.
644+ * @see #setMinimumFractionDigits
645+ */
646+ public int getMinimumFractionDigits() {
647+ return minimumFractionDigits;
648+ }
649+
650+ /**
651+ * Sets the minimum number of digits allowed in the fraction portion of a
652+ * number. minimumFractionDigits must be <= maximumFractionDigits. If the
653+ * new value for minimumFractionDigits exceeds the current value
654+ * of maximumFractionDigits, then maximumIntegerDigits will also be set to
655+ * the new value
656+ * @param newValue the minimum number of fraction digits to be shown; if
657+ * less than zero, then zero is used. The concrete subclass may enforce an
658+ * upper limit to this value appropriate to the numeric type being formatted.
659+ * @see #getMinimumFractionDigits
660+ */
661+ public void setMinimumFractionDigits(int newValue) {
662+ minimumFractionDigits = Math.max(0,newValue);
663+ if (maximumFractionDigits < minimumFractionDigits) {
664+ maximumFractionDigits = minimumFractionDigits;
665+ }
666+ }
667+
668+ /**
669+ * Gets the currency used by this number format when formatting
670+ * currency values. The initial value is derived in a locale dependent
671+ * way. The returned value may be null if no valid
672+ * currency could be determined and no currency has been set using
673+ * {@link #setCurrency(java.util.Currency) setCurrency}.
674+ * <p>
675+ * The default implementation throws
676+ * <code>UnsupportedOperationException</code>.
677+ *
678+ * @return the currency used by this number format, or <code>null</code>
679+ * @exception UnsupportedOperationException if the number format class
680+ * doesn't implement currency formatting
681+ * @since 1.4
682+ */
683+ public Currency getCurrency() {
684+ throw new UnsupportedOperationException();
685+ }
686+
687+ /**
688+ * Sets the currency used by this number format when formatting
689+ * currency values. This does not update the minimum or maximum
690+ * number of fraction digits used by the number format.
691+ * <p>
692+ * The default implementation throws
693+ * <code>UnsupportedOperationException</code>.
694+ *
695+ * @param currency the new currency to be used by this number format
696+ * @exception UnsupportedOperationException if the number format class
697+ * doesn't implement currency formatting
698+ * @exception NullPointerException if <code>currency</code> is null
699+ * @since 1.4
700+ */
701+ public void setCurrency(Currency currency) {
702+ throw new UnsupportedOperationException();
703+ }
704+
705+ /**
706+ * Gets the {@link java.math.RoundingMode} used in this NumberFormat.
707+ * The default implementation of this method in NumberFormat
708+ * always throws {@link java.lang.UnsupportedOperationException}.
709+ * Subclasses which handle different rounding modes should override
710+ * this method.
711+ *
712+ * @exception UnsupportedOperationException The default implementation
713+ * always throws this exception
714+ * @return The <code>RoundingMode</code> used for this NumberFormat.
715+ * @see #setRoundingMode(RoundingMode)
716+ * @since 1.6
717+ */
718+ public RoundingMode getRoundingMode() {
719+ throw new UnsupportedOperationException();
720+ }
721+
722+ /**
723+ * Sets the {@link java.math.RoundingMode} used in this NumberFormat.
724+ * The default implementation of this method in NumberFormat always
725+ * throws {@link java.lang.UnsupportedOperationException}.
726+ * Subclasses which handle different rounding modes should override
727+ * this method.
728+ *
729+ * @exception UnsupportedOperationException The default implementation
730+ * always throws this exception
731+ * @exception NullPointerException if <code>roundingMode</code> is null
732+ * @param roundingMode The <code>RoundingMode</code> to be used
733+ * @see #getRoundingMode()
734+ * @since 1.6
735+ */
736+ public void setRoundingMode(RoundingMode roundingMode) {
737+ throw new UnsupportedOperationException();
738+ }
739+
740+ // =======================privates===============================
741+
742+ private static NumberFormat getInstance(Locale desiredLocale,
743+ int choice) {
744+ // Check whether a provider can provide an implementation that's closer
745+ // to the requested locale than what the Java runtime itself can provide.
746+ LocaleServiceProviderPool pool =
747+ LocaleServiceProviderPool.getPool(NumberFormatProvider.class);
748+ if (pool.hasProviders()) {
749+ NumberFormat providersInstance = pool.getLocalizedObject(
750+ NumberFormatGetter.INSTANCE,
751+ desiredLocale,
752+ choice);
753+ if (providersInstance != null) {
754+ return providersInstance;
755+ }
756+ }
757+
758+ /* try the cache first */
759+ String[] numberPatterns = (String[])cachedLocaleData.get(desiredLocale);
760+ if (numberPatterns == null) { /* cache miss */
761+ ResourceBundle resource = LocaleData.getNumberFormatData(desiredLocale);
762+ numberPatterns = resource.getStringArray("NumberPatterns");
763+ /* update cache */
764+ cachedLocaleData.put(desiredLocale, numberPatterns);
765+ }
766+
767+ DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(desiredLocale);
768+ int entry = (choice == INTEGERSTYLE) ? NUMBERSTYLE : choice;
769+ DecimalFormat format = new DecimalFormat(numberPatterns[entry], symbols);
770+
771+ if (choice == INTEGERSTYLE) {
772+ format.setMaximumFractionDigits(0);
773+ format.setDecimalSeparatorAlwaysShown(false);
774+ format.setParseIntegerOnly(true);
775+ } else if (choice == CURRENCYSTYLE) {
776+ format.adjustForCurrencyDefaultFractionDigits();
777+ }
778+
779+ return format;
780+ }
781+
782+ /**
783+ * First, read in the default serializable data.
784+ *
785+ * Then, if <code>serialVersionOnStream</code> is less than 1, indicating that
786+ * the stream was written by JDK 1.1,
787+ * set the <code>int</code> fields such as <code>maximumIntegerDigits</code>
788+ * to be equal to the <code>byte</code> fields such as <code>maxIntegerDigits</code>,
789+ * since the <code>int</code> fields were not present in JDK 1.1.
790+ * Finally, set serialVersionOnStream back to the maximum allowed value so that
791+ * default serialization will work properly if this object is streamed out again.
792+ *
793+ * <p>If <code>minimumIntegerDigits</code> is greater than
794+ * <code>maximumIntegerDigits</code> or <code>minimumFractionDigits</code>
795+ * is greater than <code>maximumFractionDigits</code>, then the stream data
796+ * is invalid and this method throws an <code>InvalidObjectException</code>.
797+ * In addition, if any of these values is negative, then this method throws
798+ * an <code>InvalidObjectException</code>.
799+ *
800+ * @since 1.2
801+ */
802+ private void readObject(ObjectInputStream stream)
803+ throws IOException, ClassNotFoundException
804+ {
805+ stream.defaultReadObject();
806+ if (serialVersionOnStream < 1) {
807+ // Didn't have additional int fields, reassign to use them.
808+ maximumIntegerDigits = maxIntegerDigits;
809+ minimumIntegerDigits = minIntegerDigits;
810+ maximumFractionDigits = maxFractionDigits;
811+ minimumFractionDigits = minFractionDigits;
812+ }
813+ if (minimumIntegerDigits > maximumIntegerDigits ||
814+ minimumFractionDigits > maximumFractionDigits ||
815+ minimumIntegerDigits < 0 || minimumFractionDigits < 0) {
816+ throw new InvalidObjectException("Digit count range invalid");
817+ }
818+ serialVersionOnStream = currentSerialVersion;
819+ }
820+
821+ /**
822+ * Write out the default serializable data, after first setting
823+ * the <code>byte</code> fields such as <code>maxIntegerDigits</code> to be
824+ * equal to the <code>int</code> fields such as <code>maximumIntegerDigits</code>
825+ * (or to <code>Byte.MAX_VALUE</code>, whichever is smaller), for compatibility
826+ * with the JDK 1.1 version of the stream format.
827+ *
828+ * @since 1.2
829+ */
830+ private void writeObject(ObjectOutputStream stream)
831+ throws IOException
832+ {
833+ maxIntegerDigits = (maximumIntegerDigits > Byte.MAX_VALUE) ?
834+ Byte.MAX_VALUE : (byte)maximumIntegerDigits;
835+ minIntegerDigits = (minimumIntegerDigits > Byte.MAX_VALUE) ?
836+ Byte.MAX_VALUE : (byte)minimumIntegerDigits;
837+ maxFractionDigits = (maximumFractionDigits > Byte.MAX_VALUE) ?
838+ Byte.MAX_VALUE : (byte)maximumFractionDigits;
839+ minFractionDigits = (minimumFractionDigits > Byte.MAX_VALUE) ?
840+ Byte.MAX_VALUE : (byte)minimumFractionDigits;
841+ stream.defaultWriteObject();
842+ }
843+
844+ /**
845+ * Cache to hold the NumberPatterns of a Locale.
846+ */
847+ private static final Hashtable cachedLocaleData = new Hashtable(3);
848+
849+ // Constants used by factory methods to specify a style of format.
850+ private static final int NUMBERSTYLE = 0;
851+ private static final int CURRENCYSTYLE = 1;
852+ private static final int PERCENTSTYLE = 2;
853+ private static final int SCIENTIFICSTYLE = 3;
854+ private static final int INTEGERSTYLE = 4;
855+
856+ /**
857+ * True if the grouping (i.e. thousands) separator is used when
858+ * formatting and parsing numbers.
859+ *
860+ * @serial
861+ * @see #isGroupingUsed
862+ */
863+ private boolean groupingUsed = true;
864+
865+ /**
866+ * The maximum number of digits allowed in the integer portion of a
867+ * number. <code>maxIntegerDigits</code> must be greater than or equal to
868+ * <code>minIntegerDigits</code>.
869+ * <p>
870+ * <strong>Note:</strong> This field exists only for serialization
871+ * compatibility with JDK 1.1. In Java platform 2 v1.2 and higher, the new
872+ * <code>int</code> field <code>maximumIntegerDigits</code> is used instead.
873+ * When writing to a stream, <code>maxIntegerDigits</code> is set to
874+ * <code>maximumIntegerDigits</code> or <code>Byte.MAX_VALUE</code>,
875+ * whichever is smaller. When reading from a stream, this field is used
876+ * only if <code>serialVersionOnStream</code> is less than 1.
877+ *
878+ * @serial
879+ * @see #getMaximumIntegerDigits
880+ */
881+ private byte maxIntegerDigits = 40;
882+
883+ /**
884+ * The minimum number of digits allowed in the integer portion of a
885+ * number. <code>minimumIntegerDigits</code> must be less than or equal to
886+ * <code>maximumIntegerDigits</code>.
887+ * <p>
888+ * <strong>Note:</strong> This field exists only for serialization
889+ * compatibility with JDK 1.1. In Java platform 2 v1.2 and higher, the new
890+ * <code>int</code> field <code>minimumIntegerDigits</code> is used instead.
891+ * When writing to a stream, <code>minIntegerDigits</code> is set to
892+ * <code>minimumIntegerDigits</code> or <code>Byte.MAX_VALUE</code>,
893+ * whichever is smaller. When reading from a stream, this field is used
894+ * only if <code>serialVersionOnStream</code> is less than 1.
895+ *
896+ * @serial
897+ * @see #getMinimumIntegerDigits
898+ */
899+ private byte minIntegerDigits = 1;
900+
901+ /**
902+ * The maximum number of digits allowed in the fractional portion of a
903+ * number. <code>maximumFractionDigits</code> must be greater than or equal to
904+ * <code>minimumFractionDigits</code>.
905+ * <p>
906+ * <strong>Note:</strong> This field exists only for serialization
907+ * compatibility with JDK 1.1. In Java platform 2 v1.2 and higher, the new
908+ * <code>int</code> field <code>maximumFractionDigits</code> is used instead.
909+ * When writing to a stream, <code>maxFractionDigits</code> is set to
910+ * <code>maximumFractionDigits</code> or <code>Byte.MAX_VALUE</code>,
911+ * whichever is smaller. When reading from a stream, this field is used
912+ * only if <code>serialVersionOnStream</code> is less than 1.
913+ *
914+ * @serial
915+ * @see #getMaximumFractionDigits
916+ */
917+ private byte maxFractionDigits = 3; // invariant, >= minFractionDigits
918+
919+ /**
920+ * The minimum number of digits allowed in the fractional portion of a
921+ * number. <code>minimumFractionDigits</code> must be less than or equal to
922+ * <code>maximumFractionDigits</code>.
923+ * <p>
924+ * <strong>Note:</strong> This field exists only for serialization
925+ * compatibility with JDK 1.1. In Java platform 2 v1.2 and higher, the new
926+ * <code>int</code> field <code>minimumFractionDigits</code> is used instead.
927+ * When writing to a stream, <code>minFractionDigits</code> is set to
928+ * <code>minimumFractionDigits</code> or <code>Byte.MAX_VALUE</code>,
929+ * whichever is smaller. When reading from a stream, this field is used
930+ * only if <code>serialVersionOnStream</code> is less than 1.
931+ *
932+ * @serial
933+ * @see #getMinimumFractionDigits
934+ */
935+ private byte minFractionDigits = 0;
936+
937+ /**
938+ * True if this format will parse numbers as integers only.
939+ *
940+ * @serial
941+ * @see #isParseIntegerOnly
942+ */
943+ private boolean parseIntegerOnly = false;
944+
945+ // new fields for 1.2. byte is too small for integer digits.
946+
947+ /**
948+ * The maximum number of digits allowed in the integer portion of a
949+ * number. <code>maximumIntegerDigits</code> must be greater than or equal to
950+ * <code>minimumIntegerDigits</code>.
951+ *
952+ * @serial
953+ * @since 1.2
954+ * @see #getMaximumIntegerDigits
955+ */
956+ private int maximumIntegerDigits = 40;
957+
958+ /**
959+ * The minimum number of digits allowed in the integer portion of a
960+ * number. <code>minimumIntegerDigits</code> must be less than or equal to
961+ * <code>maximumIntegerDigits</code>.
962+ *
963+ * @serial
964+ * @since 1.2
965+ * @see #getMinimumIntegerDigits
966+ */
967+ private int minimumIntegerDigits = 1;
968+
969+ /**
970+ * The maximum number of digits allowed in the fractional portion of a
971+ * number. <code>maximumFractionDigits</code> must be greater than or equal to
972+ * <code>minimumFractionDigits</code>.
973+ *
974+ * @serial
975+ * @since 1.2
976+ * @see #getMaximumFractionDigits
977+ */
978+ private int maximumFractionDigits = 3; // invariant, >= minFractionDigits
979+
980+ /**
981+ * The minimum number of digits allowed in the fractional portion of a
982+ * number. <code>minimumFractionDigits</code> must be less than or equal to
983+ * <code>maximumFractionDigits</code>.
984+ *
985+ * @serial
986+ * @since 1.2
987+ * @see #getMinimumFractionDigits
988+ */
989+ private int minimumFractionDigits = 0;
990+
991+ static final int currentSerialVersion = 1;
992+
993+ /**
994+ * Describes the version of <code>NumberFormat</code> present on the stream.
995+ * Possible values are:
996+ * <ul>
997+ * <li><b>0</b> (or uninitialized): the JDK 1.1 version of the stream format.
998+ * In this version, the <code>int</code> fields such as
999+ * <code>maximumIntegerDigits</code> were not present, and the <code>byte</code>
1000+ * fields such as <code>maxIntegerDigits</code> are used instead.
1001+ *
1002+ * <li><b>1</b>: the 1.2 version of the stream format. The values of the
1003+ * <code>byte</code> fields such as <code>maxIntegerDigits</code> are ignored,
1004+ * and the <code>int</code> fields such as <code>maximumIntegerDigits</code>
1005+ * are used instead.
1006+ * </ul>
1007+ * When streaming out a <code>NumberFormat</code>, the most recent format
1008+ * (corresponding to the highest allowable <code>serialVersionOnStream</code>)
1009+ * is always written.
1010+ *
1011+ * @serial
1012+ * @since 1.2
1013+ */
1014+ private int serialVersionOnStream = currentSerialVersion;
1015+
1016+ // Removed "implements Cloneable" clause. Needs to update serialization
1017+ // ID for backward compatibility.
1018+ static final long serialVersionUID = -2308460125733713944L;
1019+
1020+
1021+ //
1022+ // class for AttributedCharacterIterator attributes
1023+ //
1024+ /**
1025+ * Defines constants that are used as attribute keys in the
1026+ * <code>AttributedCharacterIterator</code> returned
1027+ * from <code>NumberFormat.formatToCharacterIterator</code> and as
1028+ * field identifiers in <code>FieldPosition</code>.
1029+ *
1030+ * @since 1.4
1031+ */
1032+ public static class Field extends Format.Field {
1033+
1034+ // Proclaim serial compatibility with 1.4 FCS
1035+ private static final long serialVersionUID = 7494728892700160890L;
1036+
1037+ // table of all instances in this class, used by readResolve
1038+ private static final Map instanceMap = new HashMap(11);
1039+
1040+ /**
1041+ * Creates a Field instance with the specified
1042+ * name.
1043+ *
1044+ * @param name Name of the attribute
1045+ */
1046+ protected Field(String name) {
1047+ super(name);
1048+ if (this.getClass() == NumberFormat.Field.class) {
1049+ instanceMap.put(name, this);
1050+ }
1051+ }
1052+
1053+ /**
1054+ * Resolves instances being deserialized to the predefined constants.
1055+ *
1056+ * @throws InvalidObjectException if the constant could not be resolved.
1057+ * @return resolved NumberFormat.Field constant
1058+ */
1059+ protected Object readResolve() throws InvalidObjectException {
1060+ if (this.getClass() != NumberFormat.Field.class) {
1061+ throw new InvalidObjectException("subclass didn't correctly implement readResolve");
1062+ }
1063+
1064+ Object instance = instanceMap.get(getName());
1065+ if (instance != null) {
1066+ return instance;
1067+ } else {
1068+ throw new InvalidObjectException("unknown attribute name");
1069+ }
1070+ }
1071+
1072+ /**
1073+ * Constant identifying the integer field.
1074+ */
1075+ public static final Field INTEGER = new Field("integer");
1076+
1077+ /**
1078+ * Constant identifying the fraction field.
1079+ */
1080+ public static final Field FRACTION = new Field("fraction");
1081+
1082+ /**
1083+ * Constant identifying the exponent field.
1084+ */
1085+ public static final Field EXPONENT = new Field("exponent");
1086+
1087+ /**
1088+ * Constant identifying the decimal separator field.
1089+ */
1090+ public static final Field DECIMAL_SEPARATOR =
1091+ new Field("decimal separator");
1092+
1093+ /**
1094+ * Constant identifying the sign field.
1095+ */
1096+ public static final Field SIGN = new Field("sign");
1097+
1098+ /**
1099+ * Constant identifying the grouping separator field.
1100+ */
1101+ public static final Field GROUPING_SEPARATOR =
1102+ new Field("grouping separator");
1103+
1104+ /**
1105+ * Constant identifying the exponent symbol field.
1106+ */
1107+ public static final Field EXPONENT_SYMBOL = new
1108+ Field("exponent symbol");
1109+
1110+ /**
1111+ * Constant identifying the percent field.
1112+ */
1113+ public static final Field PERCENT = new Field("percent");
1114+
1115+ /**
1116+ * Constant identifying the permille field.
1117+ */
1118+ public static final Field PERMILLE = new Field("per mille");
1119+
1120+ /**
1121+ * Constant identifying the currency field.
1122+ */
1123+ public static final Field CURRENCY = new Field("currency");
1124+
1125+ /**
1126+ * Constant identifying the exponent sign field.
1127+ */
1128+ public static final Field EXPONENT_SIGN = new Field("exponent sign");
1129+ }
1130+
1131+ /**
1132+ * Obtains a NumberFormat instance from a NumberFormatProvider implementation.
1133+ */
1134+ private static class NumberFormatGetter
1135+ implements LocaleServiceProviderPool.LocalizedObjectGetter<NumberFormatProvider,
1136+ NumberFormat> {
1137+ private static final NumberFormatGetter INSTANCE = new NumberFormatGetter();
1138+
1139+ public NumberFormat getObject(NumberFormatProvider numberFormatProvider,
1140+ Locale locale,
1141+ String key,
1142+ Object... params) {
1143+ assert params.length == 1;
1144+ int choice = (Integer)params[0];
1145+
1146+ switch (choice) {
1147+ case NUMBERSTYLE:
1148+ return numberFormatProvider.getNumberInstance(locale);
1149+ case PERCENTSTYLE:
1150+ return numberFormatProvider.getPercentInstance(locale);
1151+ case CURRENCYSTYLE:
1152+ return numberFormatProvider.getCurrencyInstance(locale);
1153+ case INTEGERSTYLE:
1154+ return numberFormatProvider.getIntegerInstance(locale);
1155+ default:
1156+ assert false : choice;
1157+ }
1158+
1159+ return null;
1160+ }
1161+ }
1162+}