001/* NumberFormat.java -- Formats and parses numbers
002   Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2007
003   Free Software Foundation, Inc.
004
005This file is part of GNU Classpath.
006
007GNU Classpath is free software; you can redistribute it and/or modify
008it under the terms of the GNU General Public License as published by
009the Free Software Foundation; either version 2, or (at your option)
010any later version.
011 
012GNU Classpath is distributed in the hope that it will be useful, but
013WITHOUT ANY WARRANTY; without even the implied warranty of
014MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
015General Public License for more details.
016
017You should have received a copy of the GNU General Public License
018along with GNU Classpath; see the file COPYING.  If not, write to the
019Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02002110-1301 USA.
021
022Linking this library statically or dynamically with other modules is
023making a combined work based on this library.  Thus, the terms and
024conditions of the GNU General Public License cover the whole
025combination.
026
027As a special exception, the copyright holders of this library give you
028permission to link this library with independent modules to produce an
029executable, regardless of the license terms of these independent
030modules, and to copy and distribute the resulting executable under
031terms of your choice, provided that you also meet, for each linked
032independent module, the terms and conditions of the license of that
033module.  An independent module is a module which is not derived from
034or based on this library.  If you modify this library, you may extend
035this exception to your version of the library, but you are not
036obligated to do so.  If you do not wish to do so, delete this
037exception statement from your version. */
038
039
040package java.text;
041
042import gnu.java.locale.LocaleHelper;
043
044import java.io.IOException;
045import java.io.InvalidObjectException;
046import java.io.ObjectInputStream;
047import java.io.ObjectOutputStream;
048
049import java.text.spi.NumberFormatProvider;
050
051import java.util.Currency;
052import java.util.Locale;
053import java.util.MissingResourceException;
054import java.util.ResourceBundle;
055import java.util.ServiceLoader;
056
057/**
058 * This is the abstract superclass of all classes which format and 
059 * parse numeric values such as decimal numbers, integers, currency values,
060 * and percentages.  These classes perform their parsing and formatting
061 * in a locale specific manner, accounting for such items as differing
062 * currency symbols and thousands separators.
063 * <p>
064 * To create an instance of a concrete subclass of <code>NumberFormat</code>,
065 * do not call a class constructor directly.  Instead, use one of the
066 * static factory methods in this class such as 
067 * <code>getCurrencyInstance</code>.
068 * 
069 * @author Tom Tromey (tromey@cygnus.com)
070 * @author Aaron M. Renn (arenn@urbanophile.com)
071 * @date March 4, 1999
072 */
073/* Written using "Java Class Libraries", 2nd edition, plus online
074 * API docs for JDK 1.2 from http://www.javasoft.com.
075 * Status:  Believed complete and correct to 1.2, except getAvailableLocales.
076 */
077public abstract class NumberFormat extends Format implements Cloneable
078{
079  /**
080   * This is a constant used to create a <code>FieldPosition</code> object
081   * that will return the integer portion of a formatted number.
082   */
083  public static final int INTEGER_FIELD = 0;
084
085  /**
086   * This is a constant used to create a <code>FieldPosition</code> object
087   * that will return the fractional portion of a formatted number.
088   */
089  public static final int FRACTION_FIELD = 1;
090
091  public static class Field extends Format.Field
092  {
093    static final long serialVersionUID = 7494728892700160890L;
094
095    /**
096     * Attribute set to all characters containing digits of the integer
097     * part.
098     */
099    public static final NumberFormat.Field INTEGER
100      = new Field("integer");
101
102    /**
103     * Attribute set to all characters containing digits of the fractional
104     * part.
105     */
106    public static final NumberFormat.Field FRACTION
107      = new Field("fraction");
108
109    /**
110     * Attribute set to all characters containing digits of the exponential
111     * part.
112     */
113    public static final NumberFormat.Field EXPONENT
114      = new Field("exponent");
115
116    /**
117     * Attribute set to all characters containing a decimal separator.
118     */
119    public static final NumberFormat.Field DECIMAL_SEPARATOR
120      = new Field("decimal separator");
121
122    /**
123     * Attribute set to all characters containing a sign (plus or minus).
124     */
125    public static final NumberFormat.Field SIGN
126      = new Field("sign");
127
128    /**
129     * Attribute set to all characters containing a grouping separator (e.g.
130     * a comma, a white space,...).
131     */
132    public static final NumberFormat.Field GROUPING_SEPARATOR
133      = new Field("grouping separator");
134
135    /**
136     * Attribute set to all characters containing an exponential symbol (e.g.
137     * 'E')
138     */
139    public static final NumberFormat.Field EXPONENT_SYMBOL
140      = new Field("exponent symbol");
141
142    /**
143     * Attribute set to all characters containing a percent symbol (e.g. '%')
144     */
145    public static final NumberFormat.Field PERCENT
146      = new Field("percent");
147
148    /**
149     * Attribute set to all characters containing a permille symbol.
150     */
151    public static final NumberFormat.Field PERMILLE
152      = new Field("permille");
153
154    /**
155     * Attribute set to all characters containing the currency unit.
156     */
157    public static final NumberFormat.Field CURRENCY
158      = new Field("currency");
159
160    /**
161     * Attribute set to all characters containing the exponent sign.
162     */
163    public static final NumberFormat.Field EXPONENT_SIGN
164      = new Field("exponent sign");
165
166    /**
167     * Private fields to register all fields contained in this descriptor.
168     */
169    private static final NumberFormat.Field[] allFields =
170    {
171      INTEGER, FRACTION, EXPONENT, DECIMAL_SEPARATOR, SIGN,
172      GROUPING_SEPARATOR, EXPONENT_SYMBOL, PERCENT,
173      PERMILLE, CURRENCY, EXPONENT_SIGN
174    };
175
176    /**
177     * This constructor is only used by the deserializer. Without it,
178     * it would fail to construct a valid object.
179     */
180    @SuppressWarnings("unused")
181    private Field()
182    {
183      super("");
184    }
185
186    /**
187     * Create a Field instance with the specified field name.
188     *
189     * @param field_name Field name for the new Field instance.
190     */
191    protected Field(String field_name)
192    {
193      super (field_name);
194    }
195
196    /**
197     * This function is used by the deserializer to know which object
198     * to use when it encounters an encoded NumberFormat.Field in a 
199     * serialization stream. If the stream is valid it should return
200     * one of the above field. In the other case we throw an exception.
201     *
202     * @return a valid official NumberFormat.Field instance.
203     *
204     * @throws InvalidObjectException if the field name is invalid.
205     */
206    protected Object readResolve() throws InvalidObjectException
207    {
208      String s = getName();
209      for (int i = 0; i < allFields.length; i++)
210        if (s.equals(allFields[i].getName()))
211          return allFields[i];
212
213      throw new InvalidObjectException("no such NumberFormat field called "
214                                       + s);
215    }
216  }
217
218  /**
219   * This method is a specialization of the format method that performs
220   * a simple formatting of the specified <code>long</code> number.
221   *
222   * @param number The <code>long</code> to format.
223   *
224   * @return The formatted number
225   */
226  public final String format (long number)
227  {
228    StringBuffer sbuf = new StringBuffer(50);
229    format (number, sbuf, new FieldPosition(0));
230    return sbuf.toString();
231  }
232
233  /**
234   * @specnote this method was final in releases before 1.5
235   */
236  public StringBuffer format (Object obj, StringBuffer sbuf,
237                              FieldPosition pos)
238  {
239    if (obj instanceof Number)
240      return format(((Number) obj).doubleValue(), sbuf, pos);
241  
242    throw new
243      IllegalArgumentException("Cannot format given Object as a Number");
244  }
245
246  /**
247   * This method formats the specified <code>double</code> and appends it to
248   * a <code>StringBuffer</code>.
249   * 
250   * @param number The <code>double</code> to format.
251   * @param sbuf The <code>StringBuffer</code> to append the formatted number 
252   *             to.
253   * @param pos The desired <code>FieldPosition</code>.
254   *
255   * @return The <code>StringBuffer</code> with the appended number.
256   */
257  public abstract StringBuffer format (double number,
258                                       StringBuffer sbuf, FieldPosition pos);
259
260  /**
261   * This method formats the specified <code>long</code> and appends it to
262   * a <code>StringBuffer</code>.
263   * 
264   * @param number The <code>long</code> to format.
265   * @param sbuf The <code>StringBuffer</code> to append the formatted number 
266   *             to.
267   * @param pos The desired <code>FieldPosition</code>.
268   *
269   * @return The <code>StringBuffer</code> with the appended number.
270   */
271  public abstract StringBuffer format (long number,
272                                       StringBuffer sbuf, FieldPosition pos);
273
274  /**
275   * This method tests the specified object for equality against this object.
276   * This will be <code>true</code> if the following conditions are met:
277   * <p>
278   * <ul>
279   * <li>The specified object is not <code>null</code>.
280   * <li>The specified object is an instance of <code>NumberFormat</code>.
281   * </ul>
282   * <p>
283   * Since this method does not test much, it is highly advised that 
284   * concrete subclasses override this method.
285   *
286   * @param obj The <code>Object</code> to test against equality with
287   *            this object. 
288   * 
289   * @return <code>true</code> if the specified object is equal to
290   * this object, <code>false</code> otherwise. 
291   */
292  public boolean equals (Object obj)
293  {
294    if (! (obj instanceof NumberFormat))
295      return false;
296    NumberFormat nf = (NumberFormat) obj;
297    return (groupingUsed == nf.groupingUsed
298            && maximumFractionDigits == nf.maximumFractionDigits
299            && maximumIntegerDigits == nf.maximumIntegerDigits
300            && minimumFractionDigits == nf.minimumFractionDigits
301            && minimumIntegerDigits == nf.minimumIntegerDigits
302            && parseIntegerOnly == nf.parseIntegerOnly);
303  }
304
305  /**
306   * This method returns a list of locales for which concrete instances
307   * of <code>NumberFormat</code> subclasses may be created.
308   *
309   * @return The list of available locales.
310   */
311  public static Locale[] getAvailableLocales ()
312  {
313    Locale[] list = new Locale[1];
314    list[0] = Locale.US;
315    return list;
316  }
317
318  private static NumberFormat computeInstance(Locale loc, String resource,
319                                              String def)
320    throws MissingResourceException
321  {
322    if (loc.equals(Locale.ROOT))
323      return new DecimalFormat(def, DecimalFormatSymbols.getInstance(loc)); 
324    ResourceBundle res =
325      ResourceBundle.getBundle("gnu.java.locale.LocaleInformation",
326                               loc, ClassLoader.getSystemClassLoader());
327    String fmt;
328    try
329      {
330        fmt = res == null ? def : res.getString(resource);
331      }
332    catch (MissingResourceException x)
333      {
334        fmt = def;
335      }
336    DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(loc);
337    return new DecimalFormat (fmt, dfs);
338  }
339
340  /**
341   * This method returns an instance of <code>NumberFormat</code> suitable
342   * for formatting and parsing currency values in the default locale.
343   *
344   * @return An instance of <code>NumberFormat</code> for handling currencies.
345   */
346  public static final NumberFormat getCurrencyInstance ()
347  {
348    return getCurrencyInstance (Locale.getDefault());
349  }
350
351  /**
352   * This method returns an instance of <code>NumberFormat</code> suitable
353   * for formatting and parsing currency values in the specified locale.
354   *
355   * @return An instance of <code>NumberFormat</code> for handling currencies.
356   */
357  public static NumberFormat getCurrencyInstance (Locale loc)
358  {
359    try
360      {
361        NumberFormat format;
362        
363        format = computeInstance (loc, "currencyFormat",
364                                  "\u00A4#,##0.00;(\u00A4#,##0.00)");
365        format.setMaximumFractionDigits(format.getCurrency().getDefaultFractionDigits());  
366        return format;
367      }
368    catch (MissingResourceException e)
369      {
370        for (NumberFormatProvider p :
371               ServiceLoader.load(NumberFormatProvider.class))
372          {
373            for (Locale l : p.getAvailableLocales())
374              {
375                if (l.equals(loc))
376                  {
377                    NumberFormat nf = p.getCurrencyInstance(loc);
378                    if (nf != null)
379                      return nf;
380                    break;
381                  }
382              }
383          }
384        return getCurrencyInstance(LocaleHelper.getFallbackLocale(loc));
385      }
386  }
387
388  /**
389   * This method returns a default instance for the default locale. This
390   * will be a concrete subclass of <code>NumberFormat</code>, but the 
391   * actual class returned is dependent on the locale.
392   *
393   * @return An instance of the default <code>NumberFormat</code> class.
394   */
395  public static final NumberFormat getInstance ()
396  {
397    return getInstance (Locale.getDefault());
398  }
399
400  /**
401   * This method returns a default instance for the specified locale. This
402   * will be a concrete subclass of <code>NumberFormat</code>, but the 
403   * actual class returned is dependent on the locale.
404   *
405   * @param loc The desired locale.
406   *
407   * @return An instance of the default <code>NumberFormat</code> class.
408   */
409  public static NumberFormat getInstance (Locale loc)
410  {
411    // For now always return a number instance.
412    return getNumberInstance (loc);
413  }
414
415  /**
416   * This method returns the maximum number of digits allowed in the fraction
417   * portion of a number.
418   *
419   * @return The maximum number of digits allowed in the fraction
420   * portion of a number. 
421   */
422  public int getMaximumFractionDigits ()
423  {
424    return maximumFractionDigits;
425  }
426
427  /**
428   * This method returns the maximum number of digits allowed in the integer
429   * portion of a number.
430   *
431   * @return The maximum number of digits allowed in the integer
432   * portion of a number. 
433   */
434  public int getMaximumIntegerDigits ()
435  {
436    return maximumIntegerDigits;
437  }
438
439  /**
440   * This method returns the minimum number of digits allowed in the fraction
441   * portion of a number.
442   *
443   * @return The minimum number of digits allowed in the fraction
444   * portion of a number. 
445   */
446  public int getMinimumFractionDigits ()
447  {
448    return minimumFractionDigits;
449  }
450
451  /**
452   * This method returns the minimum number of digits allowed in the integer
453   * portion of a number.
454   *
455   * @return The minimum number of digits allowed in the integer
456   * portion of a number. 
457   */
458  public int getMinimumIntegerDigits ()
459  {
460    return minimumIntegerDigits;
461  }
462
463  /**
464   * This method returns a default instance for the specified locale. This
465   * will be a concrete subclass of <code>NumberFormat</code>, but the 
466   * actual class returned is dependent on the locale.
467   *
468   * @return An instance of the default <code>NumberFormat</code> class.
469   */
470  public static final NumberFormat getNumberInstance ()
471  {
472    return getNumberInstance (Locale.getDefault());
473  }
474
475  /**
476   * This method returns a general purpose number formatting and parsing
477   * class for the default locale.  This will be a concrete subclass of
478   * <code>NumberFormat</code>, but the actual class returned is dependent
479   * on the locale.
480   *
481   * @return An instance of a generic number formatter for the default locale.
482   */
483  public static NumberFormat getNumberInstance (Locale loc)
484  {
485    try
486      {
487        return computeInstance (loc, "numberFormat", "#,##0.###");
488      }
489    catch (MissingResourceException e)
490      {
491        for (NumberFormatProvider p :
492               ServiceLoader.load(NumberFormatProvider.class))
493          {
494            for (Locale l : p.getAvailableLocales())
495              {
496                if (l.equals(loc))
497                  {
498                    NumberFormat nf = p.getNumberInstance(loc);
499                    if (nf != null)
500                      return nf;
501                    break;
502                  }
503              }
504          }
505        return getNumberInstance(LocaleHelper.getFallbackLocale(loc));
506      }
507  }
508
509  /**
510   * This method returns an integer formatting and parsing class for the
511   * default locale. This will be a concrete subclass of <code>NumberFormat</code>,
512   * but the actual class returned is dependent on the locale.
513   *
514   * @return An instance of an integer number formatter for the default locale.
515   * @since 1.4 
516   */
517  public static final NumberFormat getIntegerInstance()
518  {
519    return getIntegerInstance (Locale.getDefault());
520  }
521
522  /**
523   * This method returns an integer formatting and parsing class for the
524   * default locale. This will be a concrete subclass of <code>NumberFormat</code>,
525   * but the actual class returned is dependent on the locale.
526   *
527   * @param locale the desired locale.
528   *
529   * @return An instance of an integer number formatter for the desired locale.
530   * @since 1.4 
531   */
532  public static NumberFormat getIntegerInstance(Locale locale)
533  {
534    try
535      {
536        NumberFormat format = computeInstance (locale,
537                                               "integerFormat", "#,##0");
538        format.setMaximumFractionDigits(0);
539        format.setParseIntegerOnly (true);
540        return format;
541      }
542    catch (MissingResourceException e)
543      {
544        for (NumberFormatProvider p :
545               ServiceLoader.load(NumberFormatProvider.class))
546          {
547            for (Locale l : p.getAvailableLocales())
548              {
549                if (l.equals(locale))
550                  {
551                    NumberFormat nf = p.getIntegerInstance(locale);
552                    if (nf != null)
553                      return nf;
554                    break;
555                  }
556              }
557          }
558        return getIntegerInstance(LocaleHelper.getFallbackLocale(locale));
559      }
560  }
561
562  /**
563   * This method returns an instance of <code>NumberFormat</code> suitable
564   * for formatting and parsing percentage values in the default locale.
565   *
566   * @return An instance of <code>NumberFormat</code> for handling percentages.
567   */
568  public static final NumberFormat getPercentInstance ()
569  {
570    return getPercentInstance (Locale.getDefault());
571  }
572
573  /**
574   * This method returns an instance of <code>NumberFormat</code> suitable
575   * for formatting and parsing percentage values in the specified locale.
576   *
577   * @param loc The desired locale.
578   *
579   * @return An instance of <code>NumberFormat</code> for handling percentages.
580   */
581  public static NumberFormat getPercentInstance (Locale loc)
582  {
583    try
584      {
585        return computeInstance (loc, "percentFormat", "#,##0%");
586      }
587    catch (MissingResourceException e)
588      {
589        for (NumberFormatProvider p :
590               ServiceLoader.load(NumberFormatProvider.class))
591          {
592            for (Locale l : p.getAvailableLocales())
593              {
594                if (l.equals(loc))
595                  {
596                    NumberFormat nf = p.getPercentInstance(loc);
597                    if (nf != null)
598                      return nf;
599                    break;
600                  }
601              }
602          }
603        return getPercentInstance(LocaleHelper.getFallbackLocale(loc));
604      }
605  }
606
607  /**
608   * This method returns a hash value for this object.
609   *
610   * @return The hash code.
611   */
612  public int hashCode ()
613  {
614    int hash = super.hashCode();
615    hash ^= (maximumFractionDigits + maximumIntegerDigits
616             + minimumFractionDigits + minimumIntegerDigits);
617    if (groupingUsed)
618      hash ^= 0xf0f0;
619    if (parseIntegerOnly)
620      hash ^= 0x0f0f;
621    return hash;
622  }
623
624  /**
625   * This method tests whether or not grouping is in use.  Grouping is
626   * a method of marking separations in numbers, such as thousand separators
627   * in the US English locale.  The grouping positions and symbols are all
628   * locale specific.  As an example, with grouping disabled, the number one
629   * million would appear as "1000000".  With grouping enabled, this number
630   * might appear as "1,000,000".  (Both of these assume the US English
631   * locale).
632   *
633   * @return <code>true</code> if grouping is enabled,
634   * <code>false</code> otherwise. 
635   */
636  public boolean isGroupingUsed ()
637  {
638    return groupingUsed;
639  }
640
641  /**
642   * This method tests whether or not only integer values should be parsed.
643   * If this class is parsing only integers, parsing stops at the decimal
644   * point.
645   *
646   * @return <code>true</code> if only integers are parsed,
647   * <code>false</code> otherwise. 
648   */
649  public boolean isParseIntegerOnly ()
650  {
651    return parseIntegerOnly;
652  }
653
654  /**
655   * This is a default constructor for use by subclasses.
656   */
657  protected NumberFormat ()
658  {
659  }
660
661  /**
662   * This method parses the specified string into a <code>Number</code>.  This
663   * will be a <code>Long</code> if possible, otherwise it will be a
664   * <code>Double</code>.    If no number can be parsed, no exception is
665   * thrown.  Instead, the parse position remains at its initial index.
666   *
667   * @param sourceStr The string to parse.
668   * @param pos The desired <code>ParsePosition</code>.
669   *
670   * @return The parsed <code>Number</code>
671   */
672  public abstract Number parse (String sourceStr, ParsePosition pos);
673
674  /**
675   * This method parses the specified string into a <code>Number</code>.  This
676   * will be a <code>Long</code> if possible, otherwise it will be a
677   * <code>Double</code>.  If no number can be parsed, an exception will be
678   * thrown.
679   *
680   * @param sourceStr The string to parse.
681   *
682   * @return The parsed <code>Number</code>
683   *
684   * @exception ParseException If no number can be parsed.
685   */
686  public Number parse (String sourceStr) throws ParseException
687  {
688    ParsePosition pp = new ParsePosition (0);
689    Number r = parse (sourceStr, pp);
690    if (r == null)
691      {
692        int index = pp.getErrorIndex();
693        if (index < 0)
694          index = pp.getIndex();
695        throw new ParseException ("couldn't parse number", index);
696      }
697    return r;
698  }
699
700  /**
701   * This method parses the specified string into an <code>Object</code>.  This
702   * will be a <code>Long</code> if possible, otherwise it will be a
703   * <code>Double</code>.    If no number can be parsed, no exception is
704   * thrown.  Instead, the parse position remains at its initial index.
705   *
706   * @param sourceStr The string to parse.
707   * @param pos The desired <code>ParsePosition</code>.
708  *
709  * @return The parsed <code>Object</code>
710  */
711  public final Object parseObject (String sourceStr, ParsePosition pos)
712  {
713    return parse (sourceStr, pos);
714  }
715
716  /**
717   * This method sets the grouping behavior of this formatter.  Grouping is
718   * a method of marking separations in numbers, such as thousand separators
719   * in the US English locale.  The grouping positions and symbols are all
720   * locale specific.  As an example, with grouping disabled, the number one
721   * million would appear as "1000000".  With grouping enabled, this number
722   * might appear as "1,000,000".  (Both of these assume the US English
723   * locale).
724   *
725   * @param newValue <code>true</code> to enable grouping,
726   *                     <code>false</code> to disable it. 
727   */
728  public void setGroupingUsed (boolean newValue)
729  {
730    groupingUsed = newValue;
731  }
732
733  /**
734   * This method sets the maximum number of digits allowed in the fraction
735   * portion of a number to the specified value.  If this is less than the
736   * current minimum allowed digits, the minimum allowed digits value will
737   * be lowered to be equal to the new maximum allowed digits value.
738   *
739   * @param digits The new maximum fraction digits value.
740   */
741  public void setMaximumFractionDigits (int digits)
742  {
743    maximumFractionDigits = digits;
744    if (getMinimumFractionDigits () > maximumFractionDigits)
745      setMinimumFractionDigits (maximumFractionDigits);
746  }
747
748  /**
749   * This method sets the maximum number of digits allowed in the integer
750   * portion of a number to the specified value.  If this is less than the
751   * current minimum allowed digits, the minimum allowed digits value will
752   * be lowered to be equal to the new maximum allowed digits value.
753   *
754   * @param digits The new maximum integer digits value.
755   */
756  public void setMaximumIntegerDigits (int digits)
757  {
758    maximumIntegerDigits = digits;
759    if (getMinimumIntegerDigits () > maximumIntegerDigits)
760      setMinimumIntegerDigits (maximumIntegerDigits);
761  }
762
763  /**
764   * This method sets the minimum number of digits allowed in the fraction
765   * portion of a number to the specified value.  If this is greater than the
766   * current maximum allowed digits, the maximum allowed digits value will
767   * be raised to be equal to the new minimum allowed digits value.
768   *
769   * @param digits The new minimum fraction digits value.
770   */
771  public void setMinimumFractionDigits (int digits)
772  {
773    minimumFractionDigits = digits;
774    if (getMaximumFractionDigits () < minimumFractionDigits)
775      setMaximumFractionDigits (minimumFractionDigits);
776  }
777
778  /**
779   * This method sets the minimum number of digits allowed in the integer
780   * portion of a number to the specified value.  If this is greater than the
781   * current maximum allowed digits, the maximum allowed digits value will
782   * be raised to be equal to the new minimum allowed digits value.
783   *
784   * @param digits The new minimum integer digits value.
785   */
786  public void setMinimumIntegerDigits (int digits)
787  {
788    minimumIntegerDigits = digits;
789    if (getMaximumIntegerDigits () < minimumIntegerDigits)
790      setMaximumIntegerDigits (minimumIntegerDigits);
791  }
792
793  /** 
794   * This method sets the parsing behavior of this object to parse only 
795   * integers or not.
796   *
797   * @param value <code>true</code> to parse only integers,
798   *                         <code>false</code> otherwise. 
799   */
800  public void setParseIntegerOnly (boolean value)
801  {
802    parseIntegerOnly = value;
803  }
804
805  /**
806   * This method is a specialization of the format method that performs
807   * a simple formatting of the specified <code>double</code> number.
808   *
809   * @param number The <code>double</code> to format.
810   *
811   * @return The formatted number
812   */
813  public final String format (double number)
814  {
815    StringBuffer sbuf = new StringBuffer(50);
816    FieldPosition position = new FieldPosition(0);
817    
818    format (number, sbuf, position);
819    return sbuf.toString();
820  }
821
822  // These field names are fixed by the serialization spec.
823  boolean groupingUsed;
824  int maximumFractionDigits;
825  private byte maxFractionDigits;
826  int maximumIntegerDigits;
827  private byte maxIntegerDigits;
828  int minimumFractionDigits;
829  private byte minFractionDigits;
830  int minimumIntegerDigits;
831  private byte minIntegerDigits;
832  boolean parseIntegerOnly;
833  private int serialVersionOnStream;
834  private static final long serialVersionUID = -2308460125733713944L;
835
836  private void readObject(ObjectInputStream stream)
837    throws IOException, ClassNotFoundException
838  {
839    stream.defaultReadObject();
840    if (serialVersionOnStream < 1)
841      {
842        maximumFractionDigits = maxFractionDigits;
843        maximumIntegerDigits = maxIntegerDigits;
844        minimumFractionDigits = minFractionDigits;
845        minimumIntegerDigits = minIntegerDigits;
846        serialVersionOnStream = 1;
847      }
848  }
849
850  private void writeObject(ObjectOutputStream stream) throws IOException
851  {
852    maxFractionDigits = maximumFractionDigits < Byte.MAX_VALUE ?
853      (byte) maximumFractionDigits : Byte.MAX_VALUE;
854    maxIntegerDigits = maximumIntegerDigits < Byte.MAX_VALUE ?
855      (byte) maximumIntegerDigits : Byte.MAX_VALUE;
856    minFractionDigits = minimumFractionDigits < Byte.MAX_VALUE ?
857      (byte) minimumFractionDigits : Byte.MAX_VALUE;
858    minIntegerDigits = minimumIntegerDigits < Byte.MAX_VALUE ?
859      (byte) minimumIntegerDigits : Byte.MAX_VALUE;
860    serialVersionOnStream = 1;
861    stream.defaultWriteObject();
862  }
863
864  /**
865   * Returns the currency used by this number format when formatting currency
866   * values.
867   *
868   * The default implementation throws UnsupportedOperationException.
869   *
870   * @return The used currency object, or null.
871   *
872   * @throws UnsupportedOperationException If the number format class doesn't
873   * implement currency formatting.
874   *
875   * @since 1.4
876   */
877  public Currency getCurrency()
878  {
879    throw new UnsupportedOperationException();
880  }
881
882  /**
883   * Sets the currency used by this number format when formatting currency
884   * values.
885   *
886   * The default implementation throws UnsupportedOperationException.
887   *
888   * @param currency The new currency to be used by this number format.
889   *
890   * @throws NullPointerException If currenc is null.
891   * @throws UnsupportedOperationException If the number format class doesn't
892   * implement currency formatting.
893   *
894   * @since 1.4
895   */
896  public void setCurrency(Currency currency)
897  {
898    if (currency == null)
899      throw new NullPointerException("currency may not be null");
900    
901    throw new UnsupportedOperationException();
902  }
903}