001/*
002 * Units of Measurement Reference Implementation
003 * Copyright (c) 2005-2017, Jean-Marie Dautelle, Werner Keil, V2COM.
004 *
005 * All rights reserved.
006 *
007 * Redistribution and use in source and binary forms, with or without modification,
008 * are permitted provided that the following conditions are met:
009 *
010 * 1. Redistributions of source code must retain the above copyright notice,
011 *    this list of conditions and the following disclaimer.
012 *
013 * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions
014 *    and the following disclaimer in the documentation and/or other materials provided with the distribution.
015 *
016 * 3. Neither the name of JSR-363 nor the names of its contributors may be used to endorse or promote products
017 *    derived from this software without specific prior written permission.
018 *
019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
020 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
021 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
022 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
023 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
026 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
028 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029 */
030/*
031 * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
032 * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
033 *
034 *   The original version of this source code and documentation is copyrighted
035 * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
036 * materials are provided under terms of a License Agreement between Taligent
037 * and Sun. This technology is protected by multiple US and International
038 * patents. This notice and attribution to Taligent may not be removed.
039 *   Taligent is a registered trademark of Taligent, Inc.
040 *
041 */
042
043package tec.units.ri.internal.format.l10n;
044
045import java.util.Hashtable;
046
047/**
048 * A Java ME compliant backport of {@linkplain java.text.NumberFormat} <code>NumberFormat</code> has features designed to make it possible to format
049 * numbers in any locale. It also supports different kinds of numbers, including integers (123), fixed-point numbers (123.4), percentages (12%), and
050 * currency amounts ($123). All of these can be localized.
051 *
052 * Usage:
053 * 
054 * <pre>
055 * NumberFormat f = NumberFormat.getInstance();
056 * StringBuffer sb = f.format(new Double(123.45), new StringBuffer());
057 * </pre>
058 * <p>
059 *
060 * Or eventually it's possible to change number of decimals displayed
061 * 
062 * <pre>
063 * NumberFormat f = NumberFormat.getInstance();
064 * f.setMaximumFractionDigits(2);
065 * StringBuffer sb = f.format(new Double(123.45559), new StringBuffer());
066 * </pre>
067 * <p>
068 * <code>NumberFormat</code> helps you to format and parse numbers for any locale. Your code can be completely independent of the locale conventions
069 * for decimal points, thousands-separators, or even the particular decimal digits used, or whether the number format is even decimal.
070 * 
071 * <p>
072 * To format a number for the current Locale, use one of the factory class methods: <blockquote>
073 * 
074 * <pre>
075 * myString = NumberFormat.getInstance().format(myNumber);
076 * </pre>
077 * 
078 * </blockquote> If you are formatting multiple numbers, it is more efficient to get the format and use it multiple times so that the system doesn't
079 * have to fetch the information about the local language and country conventions multiple times. <blockquote>
080 * 
081 * <pre>
082 * NumberFormat nf = NumberFormat.getInstance();
083 * for (int i = 0; i &lt; a.length; ++i) {
084 *   output.println(nf.format(myNumber[i]) + &quot;; &quot;);
085 * }
086 * </pre>
087 * 
088 * </blockquote> To format a number for a different Locale, specify it in the call to <code>getInstance</code>. <blockquote>
089 * 
090 * <pre>
091 * NumberFormat nf = NumberFormat.getInstance(Locale.FRENCH);
092 * </pre>
093 * 
094 * </blockquote> You can also use a <code>NumberFormat</code> to parse numbers: <blockquote>
095 * 
096 * <pre>
097 * myNumber = nf.parse(myString);
098 * </pre>
099 * 
100 * </blockquote> Use <code>getInstance</code> or <code>getNumberInstance</code> to get the normal number format. Use <code>getIntegerInstance</code>
101 * to get an integer number format. Use <code>getCurrencyInstance</code> to get the currency number format. And use <code>getPercentInstance</code> to
102 * get a format for displaying percentages. With this format, a fraction like 0.53 is displayed as 53%.
103 * 
104 * <p>
105 * You can also control the display of numbers with such methods as <code>setMinimumFractionDigits</code>. If you want even more control over the
106 * format or parsing, or want to give your users more control, you can try casting the <code>NumberFormat</code> you get from the factory methods to a
107 * <code>DecimalFormat</code>. This will work for the vast majority of locales; just remember to put it in a <code>try</code> block in case you
108 * encounter an unusual one.
109 * 
110 * <p>
111 * NumberFormat and DecimalFormat are designed such that some controls work for formatting and others work for parsing. The following is the detailed
112 * description for each these control methods,
113 * <p>
114 * setParseIntegerOnly : only affects parsing, e.g. if true, "3456.78" -> 3456 (and leaves the parse position just after index 6) if false, "3456.78"
115 * -> 3456.78 (and leaves the parse position just after index 8) This is independent of formatting. If you want to not show a decimal point where
116 * there might be no digits after the decimal point, use setDecimalSeparatorAlwaysShown.
117 * <p>
118 * setDecimalSeparatorAlwaysShown : only affects formatting, and only where there might be no digits after the decimal point, such as with a pattern
119 * like "#,##0.##", e.g., if true, 3456.00 -> "3,456." if false, 3456.00 -> "3456" This is independent of parsing. If you want parsing to stop at the
120 * decimal point, use setParseIntegerOnly.
121 * 
122 * <p>
123 * You can also use forms of the <code>parse</code> and <code>format</code> methods with <code>ParsePosition</code> and <code>FieldPosition</code> to
124 * allow you to:
125 * <ul>
126 * <li>progressively parse through pieces of a string
127 * <li>align the decimal point and other areas
128 * </ul>
129 * For example, you can align numbers in two ways:
130 * <ol>
131 * <li>If you are using a monospaced font with spacing for alignment, you can pass the <code>FieldPosition</code> in your format call, with
132 * <code>field</code> = <code>INTEGER_FIELD</code>. On output, <code>getEndIndex</code> will be set to the offset between the last character of the
133 * integer and the decimal. Add (desiredSpaceCount - getEndIndex) spaces at the front of the string.
134 * 
135 * <li>If you are using proportional fonts, instead of padding with spaces, measure the width of the string in pixels from the start to
136 * <code>getEndIndex</code>. Then move the pen by (desiredPixelWidth - widthToAlignmentPoint) before drawing the text. It also works where there is no
137 * decimal, but possibly additional characters at the end, e.g., with parentheses in negative numbers: "(12)" for -12.
138 * </ol>
139 * 
140 * <h4><a name="synchronization">Synchronization</a></h4>
141 * 
142 * <p>
143 * Number formats are generally not synchronized. It is recommended to create separate format instances for each thread. If multiple threads access a
144 * format concurrently, it must be synchronized externally.
145 * 
146 * @version $Revision: 0.5 $
147 * @see DecimalFormat
148 * @author Mark Davis
149 * @author Helena Shih
150 * @author <a href="mailto:jasone@greenrivercomputing.com">Jason Essington</a>
151 * @author <a href="mailto:units@catmedia.us">Werner Keil</a>
152 */
153public abstract class NumberFormat extends Format {
154
155  /**
156   * Field constant used to construct a FieldPosition object. Signifies that the position of the integer part of a formatted number should be
157   * returned.
158   * 
159   * @see FieldPosition
160   */
161  public static final int INTEGER_FIELD = 0;
162
163  /**
164   * Field constant used to construct a FieldPosition object. Signifies that the position of the fraction part of a formatted number should be
165   * returned.
166   * 
167   * @see FieldPosition
168   */
169  public static final int FRACTION_FIELD = 1;
170
171  /**
172   * Formats an object to produce a string. This general routines allows polymorphic parsing and formatting for objects.
173   * 
174   * @param number
175   *          the object to format
176   * @param toAppendTo
177   *          where the text is to be appended
178   * @param pos
179   *          On input: an alignment field, if desired. On output: the offsets of the alignment field.
180   * @return the value passed in as toAppendTo (this allows chaining, as with StringBuffer.append())
181   * @exception IllegalArgumentException
182   *              when the Format cannot format the given object.
183   * @see FieldPosition
184   */
185  public final StringBuffer format(Object number, StringBuffer toAppendTo, FieldPosition pos) {
186    if (number instanceof Long)
187      return format(((Long) number).longValue(), toAppendTo, pos);
188    else if (number instanceof Double)
189      return format(((Double) number).doubleValue(), toAppendTo, pos);
190    else if (number instanceof Integer)
191      return format(((Integer) number).intValue(), toAppendTo, pos);
192    else {
193      throw new IllegalArgumentException("Cannot format given Object as a Number");
194    }
195  }
196
197  /**
198   * Parses text from a string to produce a <code>Number</code>.
199   * <p>
200   * The method attempts to parse text starting at the index given by <code>pos</code>. If parsing succeeds, then the index of <code>pos</code> is
201   * updated to the index after the last character used (parsing does not necessarily use all characters up to the end of the string), and the parsed
202   * number is returned. The updated <code>pos</code> can be used to indicate the starting point for the next call to this method. If an error occurs,
203   * then the index of <code>pos</code> is not changed, the error index of <code>pos</code> is set to the index of the character where the error
204   * occurred, and null is returned.
205   * <p>
206   * See the {@link #parse(String, ParsePosition)} method for more information on number parsing.
207   * 
208   * @param source
209   *          A <code>String</code>, part of which should be parsed.
210   * @param pos
211   *          A <code>ParsePosition</code> object with index and error index information as described above.
212   * @return A <code>Number</code> parsed from the string. In case of error, returns null.
213   * @exception NullPointerException
214   *              if <code>pos</code> is null.
215   */
216  // public final Object parseObject(String source, ParsePosition pos) {
217  // return parse(source, pos);
218  // }
219  /**
220   * Specialization of format.
221   * 
222   * @see Format#format
223   */
224  public final String format(double number) {
225    return format(number, new StringBuffer(), DontCareFieldPosition.INSTANCE).toString();
226  }
227
228  /**
229   * Specialization of format.
230   * 
231   * @see Format#format
232   */
233  public final String format(long number) {
234    return format(number, new StringBuffer(), DontCareFieldPosition.INSTANCE).toString();
235  }
236
237  /**
238   * Specialization of format.
239   * 
240   * @see Format#format
241   */
242  public abstract StringBuffer format(double number, StringBuffer toAppendTo, FieldPosition pos);
243
244  /**
245   * Specialization of format.
246   * 
247   * @see Format#format
248   */
249  public abstract StringBuffer format(long number, StringBuffer toAppendTo, FieldPosition pos);
250
251  // /**
252  // * Returns a Long if possible (e.g., within the range [Long.MIN_VALUE,
253  // * Long.MAX_VALUE] and with no decimals), otherwise a Double. If
254  // IntegerOnly
255  // * is set, will stop at a decimal point (or equivalent; e.g., for rational
256  // * numbers "1 2/3", will stop after the 1). Does not throw an exception;
257  // if
258  // * no object can be parsed, index is unchanged!
259  // *
260  // * @see NumberFormat#isParseIntegerOnly
261  // * @see Format#parseObject
262  // */
263  // public abstract Number parse(String source, ParsePosition parsePosition);
264  //
265  // /**
266  // * Parses text from the beginning of the given string to produce a number.
267  // * The method may not use the entire text of the given string.
268  // * <p>
269  // * See the {@link #parse(String, ParsePosition)} method for more
270  // information
271  // * on number parsing.
272  // *
273  // * @param source
274  // * A <code>String</code> whose beginning should be parsed.
275  // * @return A <code>Number</code> parsed from the string.
276  // * @exception ParseException
277  // * if the beginning of the specified string cannot be parsed.
278  // */
279  // public Number parse(String source) throws ParseException {
280  // ParsePosition parsePosition = new ParsePosition(0);
281  // Number result = parse(source, parsePosition);
282  // if (parsePosition.index == 0) {
283  // throw new ParseException("Unparseable number: \"" + source + "\"",
284  // parsePosition.errorIndex);
285  // }
286  // return result;
287  // }
288
289  /**
290   * Returns true if this format will parse numbers as integers only. For example in the English locale, with ParseIntegerOnly true, the string
291   * "1234." would be parsed as the integer value 1234 and parsing would stop at the "." character. Of course, the exact format accepted by the parse
292   * operation is locale dependant and determined by sub-classes of NumberFormat.
293   */
294  boolean isParseIntegerOnly() {
295    return parseIntegerOnly;
296  }
297
298  /**
299   * Sets whether or not numbers should be parsed as integers only.
300   * 
301   * @see #isParseIntegerOnly
302   */
303  void setParseIntegerOnly(boolean value) {
304    parseIntegerOnly = value;
305  }
306
307  // ============== Locale Stuff =====================
308
309  /**
310   * Returns a general-purpose number format.
311   *
312   * @return the {@code NumberFormat} instance for general-purpose number formatting
313   */
314  public static final NumberFormat getInstance() {
315    return getNumberInstance();
316  }
317
318  /**
319   * Returns a general-purpose number format for the current default locale.
320   */
321  public final static NumberFormat getNumberInstance() {
322    return getInstance(NUMBERSTYLE);
323  }
324
325  /**
326   * Returns an integer number format for the current default locale. The returned number format is configured to round floating point numbers to the
327   * nearest integer using IEEE half-even rounding (see {@link java.math.BigDecimal#ROUND_HALF_EVEN ROUND_HALF_EVEN}) for formatting, and to parse
328   * only the integer part of an input string (see {@link #isParseIntegerOnly isParseIntegerOnly}). NOTE: <B>java.math.BigDecimal</B> is found in J2ME
329   * CDC profiles such as J2ME Foundation Profile.
330   * 
331   * @return a number format for integer values
332   */
333  public final static NumberFormat getIntegerInstance() {
334    return getInstance(INTEGERSTYLE);
335  }
336
337  /**
338   * Returns a currency format for the current default locale.
339   */
340  public final static NumberFormat getCurrencyInstance() {
341    return getInstance(CURRENCYSTYLE);
342  }
343
344  /**
345   * Returns a percentage format for the current default locale.
346   */
347  public final static NumberFormat getPercentInstance() {
348    return getInstance(PERCENTSTYLE);
349  }
350
351  /**
352   * Returns a scientific format for the current default locale.
353   */
354  /* public */final static NumberFormat getScientificInstance() {
355    return getInstance(SCIENTIFICSTYLE);
356  }
357
358  /**
359   * Overrides hashCode
360   */
361  public int hashCode() {
362    return maximumIntegerDigits * 37 + maxFractionDigits;
363    // just enough fields for a reasonable distribution
364  }
365
366  /**
367   * Overrides equals
368   */
369  public boolean equals(Object obj) {
370    if (obj == null)
371      return false;
372    if (this == obj)
373      return true;
374    if (getClass() != obj.getClass())
375      return false;
376    NumberFormat other = (NumberFormat) obj;
377    return (maximumIntegerDigits == other.maximumIntegerDigits && minimumIntegerDigits == other.minimumIntegerDigits
378        && maximumFractionDigits == other.maximumFractionDigits && minimumFractionDigits == other.minimumFractionDigits
379        && groupingUsed == other.groupingUsed && parseIntegerOnly == other.parseIntegerOnly);
380  }
381
382  /**
383   * Returns true if grouping is used in this format. For example, in the English locale, with grouping on, the number 1234567 might be formatted as
384   * "1,234,567". The grouping separator as well as the size of each group is locale dependant and is determined by sub-classes of NumberFormat.
385   * 
386   * @see #setGroupingUsed
387   */
388  boolean isGroupingUsed() {
389    return groupingUsed;
390  }
391
392  /**
393   * Set whether or not grouping will be used in this format.
394   * 
395   * @see #isGroupingUsed
396   */
397  void setGroupingUsed(boolean newValue) {
398    groupingUsed = newValue;
399  }
400
401  /**
402   * Returns the maximum number of digits allowed in the integer portion of a number.
403   * 
404   * @see #setMaximumIntegerDigits
405   */
406  public int getMaximumIntegerDigits() {
407    return maximumIntegerDigits;
408  }
409
410  /**
411   * Sets the maximum number of digits allowed in the integer portion of a number. maximumIntegerDigits must be >= minimumIntegerDigits. If the new
412   * value for maximumIntegerDigits is less than the current value of minimumIntegerDigits, then minimumIntegerDigits will also be set to the new
413   * value.
414   * 
415   * @param newValue
416   *          the maximum number of integer digits to be shown; if less than zero, then zero is used. The concrete subclass may enforce an upper limit
417   *          to this value appropriate to the numeric type being formatted.
418   * @see #getMaximumIntegerDigits
419   */
420  public void setMaximumIntegerDigits(int newValue) {
421    maximumIntegerDigits = Math.max(0, newValue);
422    if (minimumIntegerDigits > maximumIntegerDigits)
423      minimumIntegerDigits = maximumIntegerDigits;
424  }
425
426  /**
427   * Returns the minimum number of digits allowed in the integer portion of a number.
428   * 
429   * @see #setMinimumIntegerDigits
430   */
431  public int getMinimumIntegerDigits() {
432    return minimumIntegerDigits;
433  }
434
435  /**
436   * Sets the minimum number of digits allowed in the integer portion of a number. minimumIntegerDigits must be <= maximumIntegerDigits. If the new
437   * value for minimumIntegerDigits exceeds the current value of maximumIntegerDigits, then maximumIntegerDigits will also be set to the new value
438   * 
439   * @param newValue
440   *          the minimum number of integer digits to be shown; if less than zero, then zero is used. The concrete subclass may enforce an upper limit
441   *          to this value appropriate to the numeric type being formatted.
442   * @see #getMinimumIntegerDigits
443   */
444  public void setMinimumIntegerDigits(int newValue) {
445    minimumIntegerDigits = Math.max(0, newValue);
446    if (minimumIntegerDigits > maximumIntegerDigits)
447      maximumIntegerDigits = minimumIntegerDigits;
448  }
449
450  /**
451   * Returns the maximum number of digits allowed in the fraction portion of a number.
452   * 
453   * @see #setMaximumFractionDigits
454   */
455  public int getMaximumFractionDigits() {
456    return maximumFractionDigits;
457  }
458
459  /**
460   * Sets the maximum number of digits allowed in the fraction portion of a number. maximumFractionDigits must be >= minimumFractionDigits. If the new
461   * value for maximumFractionDigits is less than the current value of minimumFractionDigits, then minimumFractionDigits will also be set to the new
462   * value.
463   * 
464   * @param newValue
465   *          the maximum number of fraction digits to be shown; if less than zero, then zero is used. The concrete subclass may enforce an upper
466   *          limit to this value appropriate to the numeric type being formatted.
467   * @see #getMaximumFractionDigits
468   */
469  public void setMaximumFractionDigits(int newValue) {
470    maximumFractionDigits = Math.max(0, newValue);
471    if (maximumFractionDigits < minimumFractionDigits)
472      minimumFractionDigits = maximumFractionDigits;
473  }
474
475  /**
476   * Returns the minimum number of digits allowed in the fraction portion of a number.
477   * 
478   * @see #setMinimumFractionDigits
479   */
480  public int getMinimumFractionDigits() {
481    return minimumFractionDigits;
482  }
483
484  /**
485   * Sets the minimum number of digits allowed in the fraction portion of a number. minimumFractionDigits must be <= maximumFractionDigits. If the new
486   * value for minimumFractionDigits exceeds the current value of maximumFractionDigits, then maximumIntegerDigits will also be set to the new value
487   * 
488   * @param newValue
489   *          the minimum number of fraction digits to be shown; if less than zero, then zero is used. The concrete subclass may enforce an upper
490   *          limit to this value appropriate to the numeric type being formatted.
491   * @see #getMinimumFractionDigits
492   */
493  public void setMinimumFractionDigits(int newValue) {
494    minimumFractionDigits = Math.max(0, newValue);
495    if (maximumFractionDigits < minimumFractionDigits)
496      maximumFractionDigits = minimumFractionDigits;
497  }
498
499  // =======================privates===============================
500
501  private static NumberFormat getInstance(int choice) {
502    /* try the cache first */
503    String[] numberPatterns = new String[] { "", "", "", "", "" };
504
505    DecimalFormatSymbols symbols = new DecimalFormatSymbols();
506    int entry = (choice == INTEGERSTYLE) ? NUMBERSTYLE : choice;
507    DecimalFormat format = new DecimalFormat(numberPatterns[entry], symbols);
508
509    if (choice == INTEGERSTYLE) {
510      format.setMaximumFractionDigits(0);
511      format.setDecimalSeparatorAlwaysShown(false);
512      format.setParseIntegerOnly(true);
513    } else if (choice == CURRENCYSTYLE) {
514      // format.adjustForCurrencyDefaultFractionDigits();
515    }
516
517    return format;
518  }
519
520  // Constants used by factory methods to specify a style of format.
521  private static final int NUMBERSTYLE = 0;
522  private static final int CURRENCYSTYLE = 1;
523  private static final int PERCENTSTYLE = 2;
524  private static final int SCIENTIFICSTYLE = 3;
525  private static final int INTEGERSTYLE = 4;
526
527  /**
528   * True if the the grouping (i.e. thousands) separator is used when formatting and parsing numbers.
529   * 
530   * @serial
531   * @see #isGroupingUsed
532   */
533  private boolean groupingUsed = true;
534
535  /**
536   * The maximum number of digits allowed in the integer portion of a number. <code>maxIntegerDigits</code> must be greater than or equal to
537   * <code>minIntegerDigits</code>.
538   * <p>
539   * <strong>Note:</strong> This field exists only for serialization compatibility with JDK 1.1. In Java platform 2 v1.2 and higher, the new
540   * <code>int</code> field <code>maximumIntegerDigits</code> is used instead. When writing to a stream, <code>maxIntegerDigits</code> is set to
541   * <code>maximumIntegerDigits</code> or <code>Byte.MAX_VALUE</code>, whichever is smaller. When reading from a stream, this field is used only if
542   * <code>serialVersionOnStream</code> is less than 1.
543   * 
544   * @serial
545   * @see #getMaximumIntegerDigits
546   */
547  private byte maxIntegerDigits = 40;
548
549  /**
550   * The minimum number of digits allowed in the integer portion of a number. <code>minimumIntegerDigits</code> must be less than or equal to
551   * <code>maximumIntegerDigits</code>.
552   * <p>
553   * <strong>Note:</strong> This field exists only for serialization compatibility with JDK 1.1. In Java platform 2 v1.2 and higher, the new
554   * <code>int</code> field <code>minimumIntegerDigits</code> is used instead. When writing to a stream, <code>minIntegerDigits</code> is set to
555   * <code>minimumIntegerDigits</code> or <code>Byte.MAX_VALUE</code>, whichever is smaller. When reading from a stream, this field is used only if
556   * <code>serialVersionOnStream</code> is less than 1.
557   * 
558   * @serial
559   * @see #getMinimumIntegerDigits
560   */
561  private byte minIntegerDigits = 1;
562
563  /**
564   * The maximum number of digits allowed in the fractional portion of a number. <code>maximumFractionDigits</code> must be greater than or equal to
565   * <code>minimumFractionDigits</code>.
566   * <p>
567   * <strong>Note:</strong> This field exists only for serialization compatibility with JDK 1.1. In Java platform 2 v1.2 and higher, the new
568   * <code>int</code> field <code>maximumFractionDigits</code> is used instead. When writing to a stream, <code>maxFractionDigits</code> is set to
569   * <code>maximumFractionDigits</code> or <code>Byte.MAX_VALUE</code>, whichever is smaller. When reading from a stream, this field is used only if
570   * <code>serialVersionOnStream</code> is less than 1.
571   * 
572   * @serial
573   * @see #getMaximumFractionDigits
574   */
575  private byte maxFractionDigits = 3; // invariant, >= minFractionDigits
576
577  /**
578   * The minimum number of digits allowed in the fractional portion of a number. <code>minimumFractionDigits</code> must be less than or equal to
579   * <code>maximumFractionDigits</code>.
580   * <p>
581   * <strong>Note:</strong> This field exists only for serialization compatibility with JDK 1.1. In Java platform 2 v1.2 and higher, the new
582   * <code>int</code> field <code>minimumFractionDigits</code> is used instead. When writing to a stream, <code>minFractionDigits</code> is set to
583   * <code>minimumFractionDigits</code> or <code>Byte.MAX_VALUE</code>, whichever is smaller. When reading from a stream, this field is used only if
584   * <code>serialVersionOnStream</code> is less than 1.
585   * 
586   * @serial
587   * @see #getMinimumFractionDigits
588   */
589  private byte minFractionDigits = 0;
590
591  /**
592   * True if this format will parse numbers as integers only.
593   * 
594   * @serial
595   * @see #isParseIntegerOnly
596   */
597  private boolean parseIntegerOnly = false;
598
599  // new fields for 1.2. byte is too small for integer digits.
600
601  /**
602   * The maximum number of digits allowed in the integer portion of a number. <code>maximumIntegerDigits</code> must be greater than or equal to
603   * <code>minimumIntegerDigits</code>.
604   * 
605   * @serial
606   * @since 1.2
607   * @see #getMaximumIntegerDigits
608   */
609  private int maximumIntegerDigits = 40;
610
611  /**
612   * The minimum number of digits allowed in the integer portion of a number. <code>minimumIntegerDigits</code> must be less than or equal to
613   * <code>maximumIntegerDigits</code>.
614   * 
615   * @serial
616   * @since 1.2
617   * @see #getMinimumIntegerDigits
618   */
619  private int minimumIntegerDigits = 1;
620
621  /**
622   * The maximum number of digits allowed in the fractional portion of a number. <code>maximumFractionDigits</code> must be greater than or equal to
623   * <code>minimumFractionDigits</code>.
624   * 
625   * @serial
626   * @since 1.2
627   * @see #getMaximumFractionDigits
628   */
629  private int maximumFractionDigits = 3; // invariant, >= minFractionDigits
630
631  /**
632   * The minimum number of digits allowed in the fractional portion of a number. <code>minimumFractionDigits</code> must be less than or equal to
633   * <code>maximumFractionDigits</code>.
634   * 
635   * @serial
636   * @since 1.2
637   * @see #getMinimumFractionDigits
638   */
639  private int minimumFractionDigits = 0;
640
641  static final int currentSerialVersion = 1;
642
643  /**
644   * Describes the version of <code>NumberFormat</code> present on the stream. Possible values are:
645   * <ul>
646   * <li><b>0</b> (or uninitialized): the JDK 1.1 version of the stream format. In this version, the <code>int</code> fields such as
647   * <code>maximumIntegerDigits</code> were not present, and the <code>byte</code> fields such as <code>maxIntegerDigits</code> are used instead.
648   * 
649   * <li><b>1</b>: the 1.2 version of the stream format. The values of the <code>byte</code> fields such as <code>maxIntegerDigits</code> are ignored,
650   * and the <code>int</code> fields such as <code>maximumIntegerDigits</code> are used instead.
651   * </ul>
652   * When streaming out a <code>NumberFormat</code>, the most recent format (corresponding to the highest allowable <code>serialVersionOnStream</code>
653   * ) is always written.
654   * 
655   * @serial
656   * @since 1.2
657   */
658  private int serialVersionOnStream = currentSerialVersion;
659
660  // Removed "implements Cloneable" clause. Needs to update serialization
661  // ID for backward compatibility.
662  static final long serialVersionUID = -2308460125733713944L;
663
664  //
665  // class for AttributedCharacterIterator attributes
666  //
667  /**
668   * Defines constants that are used as attribute keys in the <code>AttributedCharacterIterator</code> returned from
669   * <code>NumberFormat.formatToCharacterIterator</code> and as field identifiers in <code>FieldPosition</code>.
670   * 
671   * @since 1.4
672   */
673  public static class Field extends Format.Field {
674    // table of all instances in this class, used by readResolve
675    @SuppressWarnings("rawtypes")
676    private static final Hashtable instanceMap = new Hashtable(11);
677
678    /**
679     * Creates a Field instance with the specified name.
680     * 
681     * @param name
682     *          Name of the attribute
683     */
684    protected Field(String name) {
685      super(name);
686      if (this.getClass() == NumberFormat.Field.class) {
687        instanceMap.put(name, this);
688      }
689    }
690
691    /**
692     * Constant identifying the integer field.
693     */
694    public static final Field INTEGER = new Field("integer");
695
696    /**
697     * Constant identifying the fraction field.
698     */
699    public static final Field FRACTION = new Field("fraction");
700
701    /**
702     * Constant identifying the exponent field.
703     */
704    public static final Field EXPONENT = new Field("exponent");
705
706    /**
707     * Constant identifying the decimal separator field.
708     */
709    public static final Field DECIMAL_SEPARATOR = new Field("decimal separator");
710
711    /**
712     * Constant identifying the sign field.
713     */
714    public static final Field SIGN = new Field("sign");
715
716    /**
717     * Constant identifying the grouping separator field.
718     */
719    public static final Field GROUPING_SEPARATOR = new Field("grouping separator");
720
721    /**
722     * Constant identifying the exponent symbol field.
723     */
724    public static final Field EXPONENT_SYMBOL = new Field("exponent symbol");
725
726    /**
727     * Constant identifying the percent field.
728     */
729    public static final Field PERCENT = new Field("percent");
730
731    /**
732     * Constant identifying the permille field.
733     */
734    public static final Field PERMILLE = new Field("per mille");
735
736    /**
737     * Constant identifying the currency field.
738     */
739    public static final Field CURRENCY = new Field("currency");
740
741    /**
742     * Constant identifying the exponent sign field.
743     */
744    public static final Field EXPONENT_SIGN = new Field("exponent sign");
745  }
746}