OSDN Git Service

Imported Classpath 0.18.
[pf3gnuchains/gcc-fork.git] / libjava / classpath / java / text / NumberFormat.java
1 /* NumberFormat.java -- Formats and parses numbers
2    Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004 Free Software Foundation, Inc.
3
4 This file is part of GNU Classpath.
5
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10  
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING.  If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version. */
37
38
39 package java.text;
40
41 import java.io.IOException;
42 import java.io.InvalidObjectException;
43 import java.io.ObjectInputStream;
44 import java.io.ObjectOutputStream;
45 import java.util.Currency;
46 import java.util.Locale;
47 import java.util.MissingResourceException;
48 import java.util.ResourceBundle;
49
50 /**
51  * This is the abstract superclass of all classes which format and 
52  * parse numeric values such as decimal numbers, integers, currency values,
53  * and percentages.  These classes perform their parsing and formatting
54  * in a locale specific manner, accounting for such items as differing
55  * currency symbols and thousands separators.
56  * <p>
57  * To create an instance of a concrete subclass of <code>NumberFormat</code>,
58  * do not call a class constructor directly.  Instead, use one of the
59  * static factory methods in this class such as 
60  * <code>getCurrencyInstance</code>.
61  * 
62  * @author Tom Tromey (tromey@cygnus.com)
63  * @author Aaron M. Renn (arenn@urbanophile.com)
64  * @date March 4, 1999
65  */
66 /* Written using "Java Class Libraries", 2nd edition, plus online
67  * API docs for JDK 1.2 from http://www.javasoft.com.
68  * Status:  Believed complete and correct to 1.2, except getAvailableLocales.
69  */
70 public abstract class NumberFormat extends Format implements Cloneable
71 {
72   /**
73    * This is a constant used to create a <code>FieldPosition</code> object
74    * that will return the integer portion of a formatted number.
75    */
76   public static final int INTEGER_FIELD = 0;
77
78   /**
79    * This is a constant used to create a <code>FieldPosition</code> object
80    * that will return the fractional portion of a formatted number.
81    */
82   public static final int FRACTION_FIELD = 1;
83
84   public static class Field extends Format.Field
85   {
86     static final long serialVersionUID = 7494728892700160890L;
87
88     /**
89      * Attribute set to all characters containing digits of the integer
90      * part.
91      */
92     public static final NumberFormat.Field INTEGER
93       = new Field("integer");
94
95     /**
96      * Attribute set to all characters containing digits of the fractional
97      * part.
98      */
99     public static final NumberFormat.Field FRACTION
100       = new Field("fraction");
101
102     /**
103      * Attribute set to all characters containing digits of the exponential
104      * part.
105      */
106     public static final NumberFormat.Field EXPONENT
107       = new Field("exponent");
108
109     /**
110      * Attribute set to all characters containing a decimal separator.
111      */
112     public static final NumberFormat.Field DECIMAL_SEPARATOR
113       = new Field("decimal separator");
114
115     /**
116      * Attribute set to all characters containing a sign (plus or minus).
117      */
118     public static final NumberFormat.Field SIGN
119       = new Field("sign");
120
121     /**
122      * Attribute set to all characters containing a grouping separator (e.g.
123      * a comma, a white space,...).
124      */
125     public static final NumberFormat.Field GROUPING_SEPARATOR
126       = new Field("grouping separator");
127
128     /**
129      * Attribute set to all characters containing an exponential symbol (e.g.
130      * 'E')
131      */
132     public static final NumberFormat.Field EXPONENT_SYMBOL
133       = new Field("exponent symbol");
134
135     /**
136      * Attribute set to all characters containing a percent symbol (e.g. '%')
137      */
138     public static final NumberFormat.Field PERCENT
139       = new Field("percent");
140
141     /**
142      * Attribute set to all characters containing a permille symbol.
143      */
144     public static final NumberFormat.Field PERMILLE
145       = new Field("permille");
146
147     /**
148      * Attribute set to all characters containing the currency unit.
149      */
150     public static final NumberFormat.Field CURRENCY
151       = new Field("currency");
152
153     /**
154      * Attribute set to all characters containing the exponent sign.
155      */
156     public static final NumberFormat.Field EXPONENT_SIGN
157       = new Field("exponent sign");
158
159     /**
160      * Private fields to register all fields contained in this descriptor.
161      */
162     private static final NumberFormat.Field[] allFields =
163     {
164       INTEGER, FRACTION, EXPONENT, DECIMAL_SEPARATOR, SIGN,
165       GROUPING_SEPARATOR, EXPONENT_SYMBOL, PERCENT,
166       PERMILLE, CURRENCY, EXPONENT_SIGN
167     };
168
169     /**
170      * This constructor is only used by the deserializer. Without it,
171      * it would fail to construct a valid object.
172      */
173     private Field()
174     {
175       super("");
176     }
177
178     /**
179      * Create a Field instance with the specified field name.
180      *
181      * @param field_name Field name for the new Field instance.
182      */
183     protected Field(String field_name)
184     {
185       super (field_name);
186     }
187
188     /**
189      * This function is used by the deserializer to know which object
190      * to use when it encounters an encoded NumberFormat.Field in a 
191      * serialization stream. If the stream is valid it should return
192      * one of the above field. In the other case we throw an exception.
193      *
194      * @return a valid official NumberFormat.Field instance.
195      *
196      * @throws InvalidObjectException if the field name is invalid.
197      */
198     protected Object readResolve() throws InvalidObjectException
199     {
200       String s = getName();
201       for (int i = 0; i < allFields.length; i++)
202         if (s.equals(allFields[i].getName()))
203           return allFields[i];
204
205       throw new InvalidObjectException("no such NumberFormat field called "
206                                        + s);
207     }
208   }
209
210   /**
211    * This method is a specialization of the format method that performs
212    * a simple formatting of the specified <code>long</code> number.
213    *
214    * @param number The <code>long</code> to format.
215    *
216    * @return The formatted number
217    */
218   public final String format (long number)
219   {
220     StringBuffer sbuf = new StringBuffer(50);
221     format (number, sbuf, null);
222     return sbuf.toString();
223   }
224
225   public final StringBuffer format (Object obj, StringBuffer sbuf,
226                                     FieldPosition pos)
227   {
228     if (obj instanceof Number)
229       return format(((Number) obj).doubleValue(), sbuf, pos);
230     else
231       throw new IllegalArgumentException 
232         ("Cannot format given Object as a Number");
233   }
234
235   /**
236    * This method formats the specified <code>double</code> and appends it to
237    * a <code>StringBuffer</code>.
238    * 
239    * @param number The <code>double</code> to format.
240    * @param sbuf The <code>StringBuffer</code> to append the formatted number 
241    *             to.
242    * @param pos The desired <code>FieldPosition</code>.
243    *
244    * @return The <code>StringBuffer</code> with the appended number.
245    */
246   public abstract StringBuffer format (double number,
247                                        StringBuffer sbuf, FieldPosition pos);
248
249   /**
250    * This method formats the specified <code>long</code> and appends it to
251    * a <code>StringBuffer</code>.
252    * 
253    * @param number The <code>long</code> to format.
254    * @param sbuf The <code>StringBuffer</code> to append the formatted number 
255    *             to.
256    * @param pos The desired <code>FieldPosition</code>.
257    *
258    * @return The <code>StringBuffer</code> with the appended number.
259    */
260   public abstract StringBuffer format (long number,
261                                        StringBuffer sbuf, FieldPosition pos);
262
263   /**
264    * This method tests the specified object for equality against this object.
265    * This will be <code>true</code> if the following conditions are met:
266    * <p>
267    * <ul>
268    * <li>The specified object is not <code>null</code>.
269    * <li>The specified object is an instance of <code>NumberFormat</code>.
270    * </ul>
271    * <p>
272    * Since this method does not test much, it is highly advised that 
273    * concrete subclasses override this method.
274    *
275    * @param obj The <code>Object</code> to test against equality with
276    *            this object. 
277    * 
278    * @return <code>true</code> if the specified object is equal to
279    * this object, <code>false</code> otherwise. 
280    */
281   public boolean equals (Object obj)
282   {
283     if (! (obj instanceof NumberFormat))
284       return false;
285     NumberFormat nf = (NumberFormat) obj;
286     return (groupingUsed == nf.groupingUsed
287             && maximumFractionDigits == nf.maximumFractionDigits
288             && maximumIntegerDigits == nf.maximumIntegerDigits
289             && minimumFractionDigits == nf.minimumFractionDigits
290             && minimumIntegerDigits == nf.minimumIntegerDigits
291             && parseIntegerOnly == nf.parseIntegerOnly);
292   }
293
294   /**
295    * This method returns a list of locales for which concrete instances
296    * of <code>NumberFormat</code> subclasses may be created.
297    *
298    * @return The list of available locales.
299    */
300   public static Locale[] getAvailableLocales ()
301   {
302     Locale[] list = new Locale[1];
303     list[0] = Locale.US;
304     return list;
305   }
306
307   private static NumberFormat computeInstance(Locale loc, String resource,
308                                               String def)
309   {
310     ResourceBundle res;
311     try
312       {
313         res = ResourceBundle.getBundle("gnu.java.locale.LocaleInformation",
314                 loc, ClassLoader.getSystemClassLoader());
315       }
316     catch (MissingResourceException x)
317       {
318         res = null;
319       }
320     String fmt;
321     try
322       {
323         fmt = res == null ? def : res.getString(resource);
324       }
325     catch (MissingResourceException x)
326       {
327         fmt = def;
328       }
329     DecimalFormatSymbols dfs = new DecimalFormatSymbols (loc);
330     return new DecimalFormat (fmt, dfs);
331   }
332
333   /**
334    * This method returns an instance of <code>NumberFormat</code> suitable
335    * for formatting and parsing currency values in the default locale.
336    *
337    * @return An instance of <code>NumberFormat</code> for handling currencies.
338    */
339   public static final NumberFormat getCurrencyInstance ()
340   {
341     return getCurrencyInstance (Locale.getDefault());
342   }
343
344   /**
345    * This method returns an instance of <code>NumberFormat</code> suitable
346    * for formatting and parsing currency values in the specified locale.
347    *
348    * @return An instance of <code>NumberFormat</code> for handling currencies.
349    */
350   public static NumberFormat getCurrencyInstance (Locale loc)
351   {
352     NumberFormat format;
353     
354     format = computeInstance (loc, "currencyFormat", "$#,##0.00;($#,##0.00)");
355     format.setMaximumFractionDigits(format.getCurrency().getDefaultFractionDigits());  
356     return format;
357   }
358
359   /**
360    * This method returns a default instance for the default locale. This
361    * will be a concrete subclass of <code>NumberFormat</code>, but the 
362    * actual class returned is dependent on the locale.
363    *
364    * @return An instance of the default <code>NumberFormat</code> class.
365    */
366   public static final NumberFormat getInstance ()
367   {
368     return getInstance (Locale.getDefault());
369   }
370
371   /**
372    * This method returns a default instance for the specified locale. This
373    * will be a concrete subclass of <code>NumberFormat</code>, but the 
374    * actual class returned is dependent on the locale.
375    *
376    * @param loc The desired locale.
377    *
378    * @return An instance of the default <code>NumberFormat</code> class.
379    */
380   public static NumberFormat getInstance (Locale loc)
381   {
382     // For now always return a number instance.
383     return getNumberInstance (loc);
384   }
385
386   /**
387    * This method returns the maximum number of digits allowed in the fraction
388    * portion of a number.
389    *
390    * @return The maximum number of digits allowed in the fraction
391    * portion of a number. 
392    */
393   public int getMaximumFractionDigits ()
394   {
395     return maximumFractionDigits;
396   }
397
398   /**
399    * This method returns the maximum number of digits allowed in the integer
400    * portion of a number.
401    *
402    * @return The maximum number of digits allowed in the integer
403    * portion of a number. 
404    */
405   public int getMaximumIntegerDigits ()
406   {
407     return maximumIntegerDigits;
408   }
409
410   /**
411    * This method returns the minimum number of digits allowed in the fraction
412    * portion of a number.
413    *
414    * @return The minimum number of digits allowed in the fraction
415    * portion of a number. 
416    */
417   public int getMinimumFractionDigits ()
418   {
419     return minimumFractionDigits;
420   }
421
422   /**
423    * This method returns the minimum number of digits allowed in the integer
424    * portion of a number.
425    *
426    * @return The minimum number of digits allowed in the integer
427    * portion of a number. 
428    */
429   public int getMinimumIntegerDigits ()
430   {
431     return minimumIntegerDigits;
432   }
433
434   /**
435    * This method returns a default instance for the specified locale. This
436    * will be a concrete subclass of <code>NumberFormat</code>, but the 
437    * actual class returned is dependent on the locale.
438    *
439    * @return An instance of the default <code>NumberFormat</code> class.
440    */
441   public static final NumberFormat getNumberInstance ()
442   {
443     return getNumberInstance (Locale.getDefault());
444   }
445
446   /**
447    * This method returns a general purpose number formatting and parsing
448    * class for the default locale.  This will be a concrete subclass of
449    * <code>NumberFormat</code>, but the actual class returned is dependent
450    * on the locale.
451    *
452    * @return An instance of a generic number formatter for the default locale.
453    */
454   public static NumberFormat getNumberInstance (Locale loc)
455   {
456     return computeInstance (loc, "numberFormat", "#,##0.###");
457   }
458
459   /**
460    * This method returns an integer formatting and parsing class for the
461    * default locale. This will be a concrete subclass of <code>NumberFormat</code>,
462    * but the actual class returned is dependent on the locale.
463    *
464    * @return An instance of an integer number formatter for the default locale.
465    * @since 1.4 
466    */
467   public static final NumberFormat getIntegerInstance()
468   {
469     return getIntegerInstance (Locale.getDefault());
470   }
471
472   /**
473    * This method returns an integer formatting and parsing class for the
474    * default locale. This will be a concrete subclass of <code>NumberFormat</code>,
475    * but the actual class returned is dependent on the locale.
476    *
477    * @param locale the desired locale.
478    *
479    * @return An instance of an integer number formatter for the desired locale.
480    * @since 1.4 
481    */
482   public static NumberFormat getIntegerInstance(Locale locale)
483   {
484     NumberFormat format = computeInstance (locale, "numberFormat", "#,##0");
485     format.setMaximumFractionDigits(0);
486     format.setParseIntegerOnly (true);
487     return format;
488   }
489
490   /**
491    * This method returns an instance of <code>NumberFormat</code> suitable
492    * for formatting and parsing percentage values in the default locale.
493    *
494    * @return An instance of <code>NumberFormat</code> for handling percentages.
495    */
496   public static final NumberFormat getPercentInstance ()
497   {
498     return getPercentInstance (Locale.getDefault());
499   }
500
501   /**
502    * This method returns an instance of <code>NumberFormat</code> suitable
503    * for formatting and parsing percentage values in the specified locale.
504    *
505    * @param loc The desired locale.
506    *
507    * @return An instance of <code>NumberFormat</code> for handling percentages.
508    */
509   public static NumberFormat getPercentInstance (Locale loc)
510   {
511     return computeInstance (loc, "percentFormat", "#,##0%");
512   }
513
514   /**
515    * This method returns a hash value for this object.
516    *
517    * @return The hash code.
518    */
519   public int hashCode ()
520   {
521     int hash = super.hashCode();
522     hash ^= (maximumFractionDigits + maximumIntegerDigits
523              + minimumFractionDigits + minimumIntegerDigits);
524     if (groupingUsed)
525       hash ^= 0xf0f0;
526     if (parseIntegerOnly)
527       hash ^= 0x0f0f;
528     return hash;
529   }
530
531   /**
532    * This method tests whether or not grouping is in use.  Grouping is
533    * a method of marking separations in numbers, such as thousand separators
534    * in the US English locale.  The grouping positions and symbols are all
535    * locale specific.  As an example, with grouping disabled, the number one
536    * million would appear as "1000000".  With grouping enabled, this number
537    * might appear as "1,000,000".  (Both of these assume the US English
538    * locale).
539    *
540    * @return <code>true</code> if grouping is enabled,
541    * <code>false</code> otherwise. 
542    */
543   public boolean isGroupingUsed ()
544   {
545     return groupingUsed;
546   }
547
548   /**
549    * This method tests whether or not only integer values should be parsed.
550    * If this class is parsing only integers, parsing stops at the decimal
551    * point.
552    *
553    * @return <code>true</code> if only integers are parsed,
554    * <code>false</code> otherwise. 
555    */
556   public boolean isParseIntegerOnly ()
557   {
558     return parseIntegerOnly;
559   }
560
561   /**
562    * This is a default constructor for use by subclasses.
563    */
564   public NumberFormat ()
565   {
566   }
567
568   /**
569    * This method parses the specified string into a <code>Number</code>.  This
570    * will be a <code>Long</code> if possible, otherwise it will be a
571    * <code>Double</code>.    If no number can be parsed, no exception is
572    * thrown.  Instead, the parse position remains at its initial index.
573    *
574    * @param sourceStr The string to parse.
575    * @param pos The desired <code>ParsePosition</code>.
576    *
577    * @return The parsed <code>Number</code>
578    */
579   public abstract Number parse (String sourceStr, ParsePosition pos);
580
581   /**
582    * This method parses the specified string into a <code>Number</code>.  This
583    * will be a <code>Long</code> if possible, otherwise it will be a
584    * <code>Double</code>.  If no number can be parsed, an exception will be
585    * thrown.
586    *
587    * @param sourceStr The string to parse.
588    *
589    * @return The parsed <code>Number</code>
590    *
591    * @exception ParseException If no number can be parsed.
592    */
593   public Number parse (String sourceStr) throws ParseException
594   {
595     ParsePosition pp = new ParsePosition (0);
596     Number r = parse (sourceStr, pp);
597     if (r == null)
598       {
599         int index = pp.getErrorIndex();
600         if (index < 0)
601           index = pp.getIndex();
602         throw new ParseException ("couldn't parse number", index);
603       }
604     return r;
605   }
606
607   /**
608    * This method parses the specified string into an <code>Object</code>.  This
609    * will be a <code>Long</code> if possible, otherwise it will be a
610    * <code>Double</code>.    If no number can be parsed, no exception is
611    * thrown.  Instead, the parse position remains at its initial index.
612    *
613    * @param sourceStr The string to parse.
614    * @param pos The desired <code>ParsePosition</code>.
615   *
616   * @return The parsed <code>Object</code>
617   */
618   public final Object parseObject (String sourceStr, ParsePosition pos)
619   {
620     return parse (sourceStr, pos);
621   }
622
623   /**
624    * This method sets the grouping behavior of this formatter.  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    * @param newValue <code>true</code> to enable grouping,
633    *                     <code>false</code> to disable it. 
634    */
635   public void setGroupingUsed (boolean newValue)
636   {
637     groupingUsed = newValue;
638   }
639
640   /**
641    * This method sets the maximum number of digits allowed in the fraction
642    * portion of a number to the specified value.  If this is less than the
643    * current minimum allowed digits, the minimum allowed digits value will
644    * be lowered to be equal to the new maximum allowed digits value.
645    *
646    * @param digits The new maximum fraction digits value.
647    */
648   public void setMaximumFractionDigits (int digits)
649   {
650     maximumFractionDigits = digits;
651     if (getMinimumFractionDigits () > maximumFractionDigits)
652       setMinimumFractionDigits (maximumFractionDigits);
653   }
654
655   /**
656    * This method sets the maximum number of digits allowed in the integer
657    * portion of a number to the specified value.  If this is less than the
658    * current minimum allowed digits, the minimum allowed digits value will
659    * be lowered to be equal to the new maximum allowed digits value.
660    *
661    * @param digits The new maximum integer digits value.
662    */
663   public void setMaximumIntegerDigits (int digits)
664   {
665     maximumIntegerDigits = digits;
666     if (getMinimumIntegerDigits () > maximumIntegerDigits)
667       setMinimumIntegerDigits (maximumIntegerDigits);
668   }
669
670   /**
671    * This method sets the minimum number of digits allowed in the fraction
672    * portion of a number to the specified value.  If this is greater than the
673    * current maximum allowed digits, the maximum allowed digits value will
674    * be raised to be equal to the new minimum allowed digits value.
675    *
676    * @param digits The new minimum fraction digits value.
677    */
678   public void setMinimumFractionDigits (int digits)
679   {
680     minimumFractionDigits = digits;
681     if (getMaximumFractionDigits () < minimumFractionDigits)
682       setMaximumFractionDigits (minimumFractionDigits);
683   }
684
685   /**
686    * This method sets the minimum number of digits allowed in the integer
687    * portion of a number to the specified value.  If this is greater than the
688    * current maximum allowed digits, the maximum allowed digits value will
689    * be raised to be equal to the new minimum allowed digits value.
690    *
691    * @param digits The new minimum integer digits value.
692    */
693   public void setMinimumIntegerDigits (int digits)
694   {
695     minimumIntegerDigits = digits;
696     if (getMaximumIntegerDigits () < minimumIntegerDigits)
697       setMaximumIntegerDigits (minimumIntegerDigits);
698   }
699
700   /** 
701    * This method sets the parsing behavior of this object to parse only 
702    * integers or not.
703    *
704    * @param value <code>true</code> to parse only integers,
705    *                         <code>false</code> otherwise. 
706    */
707   public void setParseIntegerOnly (boolean value)
708   {
709     parseIntegerOnly = value;
710   }
711
712   /**
713    * This method is a specialization of the format method that performs
714    * a simple formatting of the specified <code>double</code> number.
715    *
716    * @param number The <code>double</code> to format.
717    *
718    * @return The formatted number
719    */
720   public final String format (double number)
721   {
722     StringBuffer sbuf = new StringBuffer(50);
723     format (number, sbuf, null);
724     return sbuf.toString();
725   }
726
727   // These field names are fixed by the serialization spec.
728   boolean groupingUsed;
729   int maximumFractionDigits;
730   private byte maxFractionDigits;
731   int maximumIntegerDigits;
732   private byte maxIntegerDigits;
733   int minimumFractionDigits;
734   private byte minFractionDigits;
735   int minimumIntegerDigits;
736   private byte minIntegerDigits;
737   boolean parseIntegerOnly;
738   private int serialVersionOnStream;
739   private static final long serialVersionUID = -2308460125733713944L;
740
741   private void readObject(ObjectInputStream stream)
742     throws IOException, ClassNotFoundException
743   {
744     stream.defaultReadObject();
745     if (serialVersionOnStream < 1)
746       {
747         maximumFractionDigits = maxFractionDigits;
748         maximumIntegerDigits = maxIntegerDigits;
749         minimumFractionDigits = minFractionDigits;
750         minimumIntegerDigits = minIntegerDigits;
751         serialVersionOnStream = 1;
752       }
753   }
754
755   private void writeObject(ObjectOutputStream stream) throws IOException
756   {
757     maxFractionDigits = maximumFractionDigits < Byte.MAX_VALUE ?
758       (byte) maximumFractionDigits : Byte.MAX_VALUE;
759     maxIntegerDigits = maximumIntegerDigits < Byte.MAX_VALUE ?
760       (byte) maximumIntegerDigits : Byte.MAX_VALUE;
761     minFractionDigits = minimumFractionDigits < Byte.MAX_VALUE ?
762       (byte) minimumFractionDigits : Byte.MAX_VALUE;
763     minIntegerDigits = minimumIntegerDigits < Byte.MAX_VALUE ?
764       (byte) minimumIntegerDigits : Byte.MAX_VALUE;
765     serialVersionOnStream = 1;
766     stream.defaultWriteObject();
767   }
768
769   /**
770    * Returns the currency used by this number format when formatting currency
771    * values.
772    *
773    * The default implementation throws UnsupportedOperationException.
774    *
775    * @return The used currency object, or null.
776    *
777    * @throws UnsupportedOperationException If the number format class doesn't
778    * implement currency formatting.
779    *
780    * @since 1.4
781    */
782   public Currency getCurrency()
783   {
784     throw new UnsupportedOperationException();
785   }
786
787   /**
788    * Sets the currency used by this number format when formatting currency
789    * values.
790    *
791    * The default implementation throws UnsupportedOperationException.
792    *
793    * @param currency The new currency to be used by this number format.
794    *
795    * @throws NullPointerException If currenc is null.
796    * @throws UnsupportedOperationException If the number format class doesn't
797    * implement currency formatting.
798    *
799    * @since 1.4
800    */
801   public void setCurrency(Currency currency)
802   {
803     if (currency == null)
804       throw new NullPointerException("currency may not be null");
805     
806     throw new UnsupportedOperationException();
807   }
808 }