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        private Field()
181        {
182          super("");
183        }
184    
185        /**
186         * Create a Field instance with the specified field name.
187         *
188         * @param field_name Field name for the new Field instance.
189         */
190        protected Field(String field_name)
191        {
192          super (field_name);
193        }
194    
195        /**
196         * This function is used by the deserializer to know which object
197         * to use when it encounters an encoded NumberFormat.Field in a 
198         * serialization stream. If the stream is valid it should return
199         * one of the above field. In the other case we throw an exception.
200         *
201         * @return a valid official NumberFormat.Field instance.
202         *
203         * @throws InvalidObjectException if the field name is invalid.
204         */
205        protected Object readResolve() throws InvalidObjectException
206        {
207          String s = getName();
208          for (int i = 0; i < allFields.length; i++)
209            if (s.equals(allFields[i].getName()))
210              return allFields[i];
211    
212          throw new InvalidObjectException("no such NumberFormat field called "
213                                           + s);
214        }
215      }
216    
217      /**
218       * This method is a specialization of the format method that performs
219       * a simple formatting of the specified <code>long</code> number.
220       *
221       * @param number The <code>long</code> to format.
222       *
223       * @return The formatted number
224       */
225      public final String format (long number)
226      {
227        StringBuffer sbuf = new StringBuffer(50);
228        format (number, sbuf, new FieldPosition(0));
229        return sbuf.toString();
230      }
231    
232      /**
233       * @specnote this method was final in releases before 1.5
234       */
235      public StringBuffer format (Object obj, StringBuffer sbuf,
236                                  FieldPosition pos)
237      {
238        if (obj instanceof Number)
239          return format(((Number) obj).doubleValue(), sbuf, pos);
240      
241        throw new
242          IllegalArgumentException("Cannot format given Object as a Number");
243      }
244    
245      /**
246       * This method formats the specified <code>double</code> and appends it to
247       * a <code>StringBuffer</code>.
248       * 
249       * @param number The <code>double</code> to format.
250       * @param sbuf The <code>StringBuffer</code> to append the formatted number 
251       *             to.
252       * @param pos The desired <code>FieldPosition</code>.
253       *
254       * @return The <code>StringBuffer</code> with the appended number.
255       */
256      public abstract StringBuffer format (double number,
257                                           StringBuffer sbuf, FieldPosition pos);
258    
259      /**
260       * This method formats the specified <code>long</code> and appends it to
261       * a <code>StringBuffer</code>.
262       * 
263       * @param number The <code>long</code> to format.
264       * @param sbuf The <code>StringBuffer</code> to append the formatted number 
265       *             to.
266       * @param pos The desired <code>FieldPosition</code>.
267       *
268       * @return The <code>StringBuffer</code> with the appended number.
269       */
270      public abstract StringBuffer format (long number,
271                                           StringBuffer sbuf, FieldPosition pos);
272    
273      /**
274       * This method tests the specified object for equality against this object.
275       * This will be <code>true</code> if the following conditions are met:
276       * <p>
277       * <ul>
278       * <li>The specified object is not <code>null</code>.
279       * <li>The specified object is an instance of <code>NumberFormat</code>.
280       * </ul>
281       * <p>
282       * Since this method does not test much, it is highly advised that 
283       * concrete subclasses override this method.
284       *
285       * @param obj The <code>Object</code> to test against equality with
286       *            this object. 
287       * 
288       * @return <code>true</code> if the specified object is equal to
289       * this object, <code>false</code> otherwise. 
290       */
291      public boolean equals (Object obj)
292      {
293        if (! (obj instanceof NumberFormat))
294          return false;
295        NumberFormat nf = (NumberFormat) obj;
296        return (groupingUsed == nf.groupingUsed
297                && maximumFractionDigits == nf.maximumFractionDigits
298                && maximumIntegerDigits == nf.maximumIntegerDigits
299                && minimumFractionDigits == nf.minimumFractionDigits
300                && minimumIntegerDigits == nf.minimumIntegerDigits
301                && parseIntegerOnly == nf.parseIntegerOnly);
302      }
303    
304      /**
305       * This method returns a list of locales for which concrete instances
306       * of <code>NumberFormat</code> subclasses may be created.
307       *
308       * @return The list of available locales.
309       */
310      public static Locale[] getAvailableLocales ()
311      {
312        Locale[] list = new Locale[1];
313        list[0] = Locale.US;
314        return list;
315      }
316    
317      private static NumberFormat computeInstance(Locale loc, String resource,
318                                                  String def)
319        throws MissingResourceException
320      {
321        if (loc.equals(Locale.ROOT))
322          return new DecimalFormat(def, DecimalFormatSymbols.getInstance(loc)); 
323        ResourceBundle res =
324          ResourceBundle.getBundle("gnu.java.locale.LocaleInformation",
325                                   loc, ClassLoader.getSystemClassLoader());
326        String fmt;
327        try
328          {
329            fmt = res == null ? def : res.getString(resource);
330          }
331        catch (MissingResourceException x)
332          {
333            fmt = def;
334          }
335        DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(loc);
336        return new DecimalFormat (fmt, dfs);
337      }
338    
339      /**
340       * This method returns an instance of <code>NumberFormat</code> suitable
341       * for formatting and parsing currency values in the default locale.
342       *
343       * @return An instance of <code>NumberFormat</code> for handling currencies.
344       */
345      public static final NumberFormat getCurrencyInstance ()
346      {
347        return getCurrencyInstance (Locale.getDefault());
348      }
349    
350      /**
351       * This method returns an instance of <code>NumberFormat</code> suitable
352       * for formatting and parsing currency values in the specified locale.
353       *
354       * @return An instance of <code>NumberFormat</code> for handling currencies.
355       */
356      public static NumberFormat getCurrencyInstance (Locale loc)
357      {
358        try
359          {
360            NumberFormat format;
361            
362            format = computeInstance (loc, "currencyFormat",
363                                      "\u00A4#,##0.00;(\u00A4#,##0.00)");
364            format.setMaximumFractionDigits(format.getCurrency().getDefaultFractionDigits());  
365            return format;
366          }
367        catch (MissingResourceException e)
368          {
369            for (NumberFormatProvider p :
370                   ServiceLoader.load(NumberFormatProvider.class))
371              {
372                for (Locale l : p.getAvailableLocales())
373                  {
374                    if (l.equals(loc))
375                      {
376                        NumberFormat nf = p.getCurrencyInstance(loc);
377                        if (nf != null)
378                          return nf;
379                        break;
380                      }
381                  }
382              }
383            return getCurrencyInstance(LocaleHelper.getFallbackLocale(loc));
384          }
385      }
386    
387      /**
388       * This method returns a default instance for the default locale. This
389       * will be a concrete subclass of <code>NumberFormat</code>, but the 
390       * actual class returned is dependent on the locale.
391       *
392       * @return An instance of the default <code>NumberFormat</code> class.
393       */
394      public static final NumberFormat getInstance ()
395      {
396        return getInstance (Locale.getDefault());
397      }
398    
399      /**
400       * This method returns a default instance for the specified locale. This
401       * will be a concrete subclass of <code>NumberFormat</code>, but the 
402       * actual class returned is dependent on the locale.
403       *
404       * @param loc The desired locale.
405       *
406       * @return An instance of the default <code>NumberFormat</code> class.
407       */
408      public static NumberFormat getInstance (Locale loc)
409      {
410        // For now always return a number instance.
411        return getNumberInstance (loc);
412      }
413    
414      /**
415       * This method returns the maximum number of digits allowed in the fraction
416       * portion of a number.
417       *
418       * @return The maximum number of digits allowed in the fraction
419       * portion of a number. 
420       */
421      public int getMaximumFractionDigits ()
422      {
423        return maximumFractionDigits;
424      }
425    
426      /**
427       * This method returns the maximum number of digits allowed in the integer
428       * portion of a number.
429       *
430       * @return The maximum number of digits allowed in the integer
431       * portion of a number. 
432       */
433      public int getMaximumIntegerDigits ()
434      {
435        return maximumIntegerDigits;
436      }
437    
438      /**
439       * This method returns the minimum number of digits allowed in the fraction
440       * portion of a number.
441       *
442       * @return The minimum number of digits allowed in the fraction
443       * portion of a number. 
444       */
445      public int getMinimumFractionDigits ()
446      {
447        return minimumFractionDigits;
448      }
449    
450      /**
451       * This method returns the minimum number of digits allowed in the integer
452       * portion of a number.
453       *
454       * @return The minimum number of digits allowed in the integer
455       * portion of a number. 
456       */
457      public int getMinimumIntegerDigits ()
458      {
459        return minimumIntegerDigits;
460      }
461    
462      /**
463       * This method returns a default instance for the specified locale. This
464       * will be a concrete subclass of <code>NumberFormat</code>, but the 
465       * actual class returned is dependent on the locale.
466       *
467       * @return An instance of the default <code>NumberFormat</code> class.
468       */
469      public static final NumberFormat getNumberInstance ()
470      {
471        return getNumberInstance (Locale.getDefault());
472      }
473    
474      /**
475       * This method returns a general purpose number formatting and parsing
476       * class for the default locale.  This will be a concrete subclass of
477       * <code>NumberFormat</code>, but the actual class returned is dependent
478       * on the locale.
479       *
480       * @return An instance of a generic number formatter for the default locale.
481       */
482      public static NumberFormat getNumberInstance (Locale loc)
483      {
484        try
485          {
486            return computeInstance (loc, "numberFormat", "#,##0.###");
487          }
488        catch (MissingResourceException e)
489          {
490            for (NumberFormatProvider p :
491                   ServiceLoader.load(NumberFormatProvider.class))
492              {
493                for (Locale l : p.getAvailableLocales())
494                  {
495                    if (l.equals(loc))
496                      {
497                        NumberFormat nf = p.getNumberInstance(loc);
498                        if (nf != null)
499                          return nf;
500                        break;
501                      }
502                  }
503              }
504            return getNumberInstance(LocaleHelper.getFallbackLocale(loc));
505          }
506      }
507    
508      /**
509       * This method returns an integer formatting and parsing class for the
510       * default locale. This will be a concrete subclass of <code>NumberFormat</code>,
511       * but the actual class returned is dependent on the locale.
512       *
513       * @return An instance of an integer number formatter for the default locale.
514       * @since 1.4 
515       */
516      public static final NumberFormat getIntegerInstance()
517      {
518        return getIntegerInstance (Locale.getDefault());
519      }
520    
521      /**
522       * This method returns an integer formatting and parsing class for the
523       * default locale. This will be a concrete subclass of <code>NumberFormat</code>,
524       * but the actual class returned is dependent on the locale.
525       *
526       * @param locale the desired locale.
527       *
528       * @return An instance of an integer number formatter for the desired locale.
529       * @since 1.4 
530       */
531      public static NumberFormat getIntegerInstance(Locale locale)
532      {
533        try
534          {
535            NumberFormat format = computeInstance (locale,
536                                                   "integerFormat", "#,##0");
537            format.setMaximumFractionDigits(0);
538            format.setParseIntegerOnly (true);
539            return format;
540          }
541        catch (MissingResourceException e)
542          {
543            for (NumberFormatProvider p :
544                   ServiceLoader.load(NumberFormatProvider.class))
545              {
546                for (Locale l : p.getAvailableLocales())
547                  {
548                    if (l.equals(locale))
549                      {
550                        NumberFormat nf = p.getIntegerInstance(locale);
551                        if (nf != null)
552                          return nf;
553                        break;
554                      }
555                  }
556              }
557            return getIntegerInstance(LocaleHelper.getFallbackLocale(locale));
558          }
559      }
560    
561      /**
562       * This method returns an instance of <code>NumberFormat</code> suitable
563       * for formatting and parsing percentage values in the default locale.
564       *
565       * @return An instance of <code>NumberFormat</code> for handling percentages.
566       */
567      public static final NumberFormat getPercentInstance ()
568      {
569        return getPercentInstance (Locale.getDefault());
570      }
571    
572      /**
573       * This method returns an instance of <code>NumberFormat</code> suitable
574       * for formatting and parsing percentage values in the specified locale.
575       *
576       * @param loc The desired locale.
577       *
578       * @return An instance of <code>NumberFormat</code> for handling percentages.
579       */
580      public static NumberFormat getPercentInstance (Locale loc)
581      {
582        try
583          {
584            return computeInstance (loc, "percentFormat", "#,##0%");
585          }
586        catch (MissingResourceException e)
587          {
588            for (NumberFormatProvider p :
589                   ServiceLoader.load(NumberFormatProvider.class))
590              {
591                for (Locale l : p.getAvailableLocales())
592                  {
593                    if (l.equals(loc))
594                      {
595                        NumberFormat nf = p.getPercentInstance(loc);
596                        if (nf != null)
597                          return nf;
598                        break;
599                      }
600                  }
601              }
602            return getPercentInstance(LocaleHelper.getFallbackLocale(loc));
603          }
604      }
605    
606      /**
607       * This method returns a hash value for this object.
608       *
609       * @return The hash code.
610       */
611      public int hashCode ()
612      {
613        int hash = super.hashCode();
614        hash ^= (maximumFractionDigits + maximumIntegerDigits
615                 + minimumFractionDigits + minimumIntegerDigits);
616        if (groupingUsed)
617          hash ^= 0xf0f0;
618        if (parseIntegerOnly)
619          hash ^= 0x0f0f;
620        return hash;
621      }
622    
623      /**
624       * This method tests whether or not grouping is in use.  Grouping is
625       * a method of marking separations in numbers, such as thousand separators
626       * in the US English locale.  The grouping positions and symbols are all
627       * locale specific.  As an example, with grouping disabled, the number one
628       * million would appear as "1000000".  With grouping enabled, this number
629       * might appear as "1,000,000".  (Both of these assume the US English
630       * locale).
631       *
632       * @return <code>true</code> if grouping is enabled,
633       * <code>false</code> otherwise. 
634       */
635      public boolean isGroupingUsed ()
636      {
637        return groupingUsed;
638      }
639    
640      /**
641       * This method tests whether or not only integer values should be parsed.
642       * If this class is parsing only integers, parsing stops at the decimal
643       * point.
644       *
645       * @return <code>true</code> if only integers are parsed,
646       * <code>false</code> otherwise. 
647       */
648      public boolean isParseIntegerOnly ()
649      {
650        return parseIntegerOnly;
651      }
652    
653      /**
654       * This is a default constructor for use by subclasses.
655       */
656      public NumberFormat ()
657      {
658      }
659    
660      /**
661       * This method parses the specified string into a <code>Number</code>.  This
662       * will be a <code>Long</code> if possible, otherwise it will be a
663       * <code>Double</code>.    If no number can be parsed, no exception is
664       * thrown.  Instead, the parse position remains at its initial index.
665       *
666       * @param sourceStr The string to parse.
667       * @param pos The desired <code>ParsePosition</code>.
668       *
669       * @return The parsed <code>Number</code>
670       */
671      public abstract Number parse (String sourceStr, ParsePosition pos);
672    
673      /**
674       * This method parses the specified string into a <code>Number</code>.  This
675       * will be a <code>Long</code> if possible, otherwise it will be a
676       * <code>Double</code>.  If no number can be parsed, an exception will be
677       * thrown.
678       *
679       * @param sourceStr The string to parse.
680       *
681       * @return The parsed <code>Number</code>
682       *
683       * @exception ParseException If no number can be parsed.
684       */
685      public Number parse (String sourceStr) throws ParseException
686      {
687        ParsePosition pp = new ParsePosition (0);
688        Number r = parse (sourceStr, pp);
689        if (r == null)
690          {
691            int index = pp.getErrorIndex();
692            if (index < 0)
693              index = pp.getIndex();
694            throw new ParseException ("couldn't parse number", index);
695          }
696        return r;
697      }
698    
699      /**
700       * This method parses the specified string into an <code>Object</code>.  This
701       * will be a <code>Long</code> if possible, otherwise it will be a
702       * <code>Double</code>.    If no number can be parsed, no exception is
703       * thrown.  Instead, the parse position remains at its initial index.
704       *
705       * @param sourceStr The string to parse.
706       * @param pos The desired <code>ParsePosition</code>.
707      *
708      * @return The parsed <code>Object</code>
709      */
710      public final Object parseObject (String sourceStr, ParsePosition pos)
711      {
712        return parse (sourceStr, pos);
713      }
714    
715      /**
716       * This method sets the grouping behavior of this formatter.  Grouping is
717       * a method of marking separations in numbers, such as thousand separators
718       * in the US English locale.  The grouping positions and symbols are all
719       * locale specific.  As an example, with grouping disabled, the number one
720       * million would appear as "1000000".  With grouping enabled, this number
721       * might appear as "1,000,000".  (Both of these assume the US English
722       * locale).
723       *
724       * @param newValue <code>true</code> to enable grouping,
725       *                     <code>false</code> to disable it. 
726       */
727      public void setGroupingUsed (boolean newValue)
728      {
729        groupingUsed = newValue;
730      }
731    
732      /**
733       * This method sets the maximum number of digits allowed in the fraction
734       * portion of a number to the specified value.  If this is less than the
735       * current minimum allowed digits, the minimum allowed digits value will
736       * be lowered to be equal to the new maximum allowed digits value.
737       *
738       * @param digits The new maximum fraction digits value.
739       */
740      public void setMaximumFractionDigits (int digits)
741      {
742        maximumFractionDigits = digits;
743        if (getMinimumFractionDigits () > maximumFractionDigits)
744          setMinimumFractionDigits (maximumFractionDigits);
745      }
746    
747      /**
748       * This method sets the maximum number of digits allowed in the integer
749       * portion of a number to the specified value.  If this is less than the
750       * current minimum allowed digits, the minimum allowed digits value will
751       * be lowered to be equal to the new maximum allowed digits value.
752       *
753       * @param digits The new maximum integer digits value.
754       */
755      public void setMaximumIntegerDigits (int digits)
756      {
757        maximumIntegerDigits = digits;
758        if (getMinimumIntegerDigits () > maximumIntegerDigits)
759          setMinimumIntegerDigits (maximumIntegerDigits);
760      }
761    
762      /**
763       * This method sets the minimum number of digits allowed in the fraction
764       * portion of a number to the specified value.  If this is greater than the
765       * current maximum allowed digits, the maximum allowed digits value will
766       * be raised to be equal to the new minimum allowed digits value.
767       *
768       * @param digits The new minimum fraction digits value.
769       */
770      public void setMinimumFractionDigits (int digits)
771      {
772        minimumFractionDigits = digits;
773        if (getMaximumFractionDigits () < minimumFractionDigits)
774          setMaximumFractionDigits (minimumFractionDigits);
775      }
776    
777      /**
778       * This method sets the minimum number of digits allowed in the integer
779       * portion of a number to the specified value.  If this is greater than the
780       * current maximum allowed digits, the maximum allowed digits value will
781       * be raised to be equal to the new minimum allowed digits value.
782       *
783       * @param digits The new minimum integer digits value.
784       */
785      public void setMinimumIntegerDigits (int digits)
786      {
787        minimumIntegerDigits = digits;
788        if (getMaximumIntegerDigits () < minimumIntegerDigits)
789          setMaximumIntegerDigits (minimumIntegerDigits);
790      }
791    
792      /** 
793       * This method sets the parsing behavior of this object to parse only 
794       * integers or not.
795       *
796       * @param value <code>true</code> to parse only integers,
797       *                         <code>false</code> otherwise. 
798       */
799      public void setParseIntegerOnly (boolean value)
800      {
801        parseIntegerOnly = value;
802      }
803    
804      /**
805       * This method is a specialization of the format method that performs
806       * a simple formatting of the specified <code>double</code> number.
807       *
808       * @param number The <code>double</code> to format.
809       *
810       * @return The formatted number
811       */
812      public final String format (double number)
813      {
814        StringBuffer sbuf = new StringBuffer(50);
815        FieldPosition position = new FieldPosition(0);
816        
817        format (number, sbuf, position);
818        return sbuf.toString();
819      }
820    
821      // These field names are fixed by the serialization spec.
822      boolean groupingUsed;
823      int maximumFractionDigits;
824      private byte maxFractionDigits;
825      int maximumIntegerDigits;
826      private byte maxIntegerDigits;
827      int minimumFractionDigits;
828      private byte minFractionDigits;
829      int minimumIntegerDigits;
830      private byte minIntegerDigits;
831      boolean parseIntegerOnly;
832      private int serialVersionOnStream;
833      private static final long serialVersionUID = -2308460125733713944L;
834    
835      private void readObject(ObjectInputStream stream)
836        throws IOException, ClassNotFoundException
837      {
838        stream.defaultReadObject();
839        if (serialVersionOnStream < 1)
840          {
841            maximumFractionDigits = maxFractionDigits;
842            maximumIntegerDigits = maxIntegerDigits;
843            minimumFractionDigits = minFractionDigits;
844            minimumIntegerDigits = minIntegerDigits;
845            serialVersionOnStream = 1;
846          }
847      }
848    
849      private void writeObject(ObjectOutputStream stream) throws IOException
850      {
851        maxFractionDigits = maximumFractionDigits < Byte.MAX_VALUE ?
852          (byte) maximumFractionDigits : Byte.MAX_VALUE;
853        maxIntegerDigits = maximumIntegerDigits < Byte.MAX_VALUE ?
854          (byte) maximumIntegerDigits : Byte.MAX_VALUE;
855        minFractionDigits = minimumFractionDigits < Byte.MAX_VALUE ?
856          (byte) minimumFractionDigits : Byte.MAX_VALUE;
857        minIntegerDigits = minimumIntegerDigits < Byte.MAX_VALUE ?
858          (byte) minimumIntegerDigits : Byte.MAX_VALUE;
859        serialVersionOnStream = 1;
860        stream.defaultWriteObject();
861      }
862    
863      /**
864       * Returns the currency used by this number format when formatting currency
865       * values.
866       *
867       * The default implementation throws UnsupportedOperationException.
868       *
869       * @return The used currency object, or null.
870       *
871       * @throws UnsupportedOperationException If the number format class doesn't
872       * implement currency formatting.
873       *
874       * @since 1.4
875       */
876      public Currency getCurrency()
877      {
878        throw new UnsupportedOperationException();
879      }
880    
881      /**
882       * Sets the currency used by this number format when formatting currency
883       * values.
884       *
885       * The default implementation throws UnsupportedOperationException.
886       *
887       * @param currency The new currency to be used by this number format.
888       *
889       * @throws NullPointerException If currenc is null.
890       * @throws UnsupportedOperationException If the number format class doesn't
891       * implement currency formatting.
892       *
893       * @since 1.4
894       */
895      public void setCurrency(Currency currency)
896      {
897        if (currency == null)
898          throw new NullPointerException("currency may not be null");
899        
900        throw new UnsupportedOperationException();
901      }
902    }