001    /* NumberFormat.java -- Formats and parses numbers
002       Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2007
003       Free Software Foundation, Inc.
004    
005    This file is part of GNU Classpath.
006    
007    GNU Classpath is free software; you can redistribute it and/or modify
008    it under the terms of the GNU General Public License as published by
009    the Free Software Foundation; either version 2, or (at your option)
010    any later version.
011     
012    GNU Classpath is distributed in the hope that it will be useful, but
013    WITHOUT ANY WARRANTY; without even the implied warranty of
014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
015    General Public License for more details.
016    
017    You should have received a copy of the GNU General Public License
018    along with GNU Classpath; see the file COPYING.  If not, write to the
019    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
020    02110-1301 USA.
021    
022    Linking this library statically or dynamically with other modules is
023    making a combined work based on this library.  Thus, the terms and
024    conditions of the GNU General Public License cover the whole
025    combination.
026    
027    As a special exception, the copyright holders of this library give you
028    permission to link this library with independent modules to produce an
029    executable, regardless of the license terms of these independent
030    modules, and to copy and distribute the resulting executable under
031    terms of your choice, provided that you also meet, for each linked
032    independent module, the terms and conditions of the license of that
033    module.  An independent module is a module which is not derived from
034    or based on this library.  If you modify this library, you may extend
035    this exception to your version of the library, but you are not
036    obligated to do so.  If you do not wish to do so, delete this
037    exception statement from your version. */
038    
039    
040    package java.text;
041    
042    import gnu.java.locale.LocaleHelper;
043    
044    import java.io.IOException;
045    import java.io.InvalidObjectException;
046    import java.io.ObjectInputStream;
047    import java.io.ObjectOutputStream;
048    
049    import java.text.spi.NumberFormatProvider;
050    
051    import java.util.Currency;
052    import java.util.Locale;
053    import java.util.MissingResourceException;
054    import java.util.ResourceBundle;
055    import 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     */
077    public 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    }