/* NumberFormat.java -- Formats and parses numbers
   Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2007
   Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
 
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package java.text;

import gnu.java.locale.LocaleHelper;

import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import java.text.spi.NumberFormatProvider;

import java.util.Currency;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.ServiceLoader;

/**
 * This is the abstract superclass of all classes which format and 
 * parse numeric values such as decimal numbers, integers, currency values,
 * and percentages.  These classes perform their parsing and formatting
 * in a locale specific manner, accounting for such items as differing
 * currency symbols and thousands separators.
 * <p>
 * To create an instance of a concrete subclass of <code>NumberFormat</code>,
 * do not call a class constructor directly.  Instead, use one of the
 * static factory methods in this class such as 
 * <code>getCurrencyInstance</code>.
 * 
 * @author Tom Tromey (tromey@cygnus.com)
 * @author Aaron M. Renn (arenn@urbanophile.com)
 * @date March 4, 1999
 */
/* Written using "Java Class Libraries", 2nd edition, plus online
 * API docs for JDK 1.2 from http://www.javasoft.com.
 * Status:  Believed complete and correct to 1.2, except getAvailableLocales.
 */
public abstract class NumberFormat extends Format implements Cloneable
{
  /**
   * This is a constant used to create a <code>FieldPosition</code> object
   * that will return the integer portion of a formatted number.
   */
  public static final int INTEGER_FIELD = 0;

  /**
   * This is a constant used to create a <code>FieldPosition</code> object
   * that will return the fractional portion of a formatted number.
   */
  public static final int FRACTION_FIELD = 1;

  public static class Field extends Format.Field
  {
    static final long serialVersionUID = 7494728892700160890L;

    /**
     * Attribute set to all characters containing digits of the integer
     * part.
     */
    public static final NumberFormat.Field INTEGER
      = new Field("integer");

    /**
     * Attribute set to all characters containing digits of the fractional
     * part.
     */
    public static final NumberFormat.Field FRACTION
      = new Field("fraction");

    /**
     * Attribute set to all characters containing digits of the exponential
     * part.
     */
    public static final NumberFormat.Field EXPONENT
      = new Field("exponent");

    /**
     * Attribute set to all characters containing a decimal separator.
     */
    public static final NumberFormat.Field DECIMAL_SEPARATOR
      = new Field("decimal separator");

    /**
     * Attribute set to all characters containing a sign (plus or minus).
     */
    public static final NumberFormat.Field SIGN
      = new Field("sign");

    /**
     * Attribute set to all characters containing a grouping separator (e.g.
     * a comma, a white space,...).
     */
    public static final NumberFormat.Field GROUPING_SEPARATOR
      = new Field("grouping separator");

    /**
     * Attribute set to all characters containing an exponential symbol (e.g.
     * 'E')
     */
    public static final NumberFormat.Field EXPONENT_SYMBOL
      = new Field("exponent symbol");

    /**
     * Attribute set to all characters containing a percent symbol (e.g. '%')
     */
    public static final NumberFormat.Field PERCENT
      = new Field("percent");

    /**
     * Attribute set to all characters containing a permille symbol.
     */
    public static final NumberFormat.Field PERMILLE
      = new Field("permille");

    /**
     * Attribute set to all characters containing the currency unit.
     */
    public static final NumberFormat.Field CURRENCY
      = new Field("currency");

    /**
     * Attribute set to all characters containing the exponent sign.
     */
    public static final NumberFormat.Field EXPONENT_SIGN
      = new Field("exponent sign");

    /**
     * Private fields to register all fields contained in this descriptor.
     */
    private static final NumberFormat.Field[] allFields =
    {
      INTEGER, FRACTION, EXPONENT, DECIMAL_SEPARATOR, SIGN,
      GROUPING_SEPARATOR, EXPONENT_SYMBOL, PERCENT,
      PERMILLE, CURRENCY, EXPONENT_SIGN
    };

    /**
     * This constructor is only used by the deserializer. Without it,
     * it would fail to construct a valid object.
     */
    private Field()
    {
      super("");
    }

    /**
     * Create a Field instance with the specified field name.
     *
     * @param field_name Field name for the new Field instance.
     */
    protected Field(String field_name)
    {
      super (field_name);
    }

    /**
     * This function is used by the deserializer to know which object
     * to use when it encounters an encoded NumberFormat.Field in a 
     * serialization stream. If the stream is valid it should return
     * one of the above field. In the other case we throw an exception.
     *
     * @return a valid official NumberFormat.Field instance.
     *
     * @throws InvalidObjectException if the field name is invalid.
     */
    protected Object readResolve() throws InvalidObjectException
    {
      String s = getName();
      for (int i = 0; i < allFields.length; i++)
	if (s.equals(allFields[i].getName()))
	  return allFields[i];

      throw new InvalidObjectException("no such NumberFormat field called "
				       + s);
    }
  }

  /**
   * This method is a specialization of the format method that performs
   * a simple formatting of the specified <code>long</code> number.
   *
   * @param number The <code>long</code> to format.
   *
   * @return The formatted number
   */
  public final String format (long number)
  {
    StringBuffer sbuf = new StringBuffer(50);
    format (number, sbuf, new FieldPosition(0));
    return sbuf.toString();
  }

  /**
   * @specnote this method was final in releases before 1.5
   */
  public StringBuffer format (Object obj, StringBuffer sbuf,
                              FieldPosition pos)
  {
    if (obj instanceof Number)
      return format(((Number) obj).doubleValue(), sbuf, pos);
  
    throw new
      IllegalArgumentException("Cannot format given Object as a Number");
  }

  /**
   * This method formats the specified <code>double</code> and appends it to
   * a <code>StringBuffer</code>.
   * 
   * @param number The <code>double</code> to format.
   * @param sbuf The <code>StringBuffer</code> to append the formatted number 
   *             to.
   * @param pos The desired <code>FieldPosition</code>.
   *
   * @return The <code>StringBuffer</code> with the appended number.
   */
  public abstract StringBuffer format (double number,
				       StringBuffer sbuf, FieldPosition pos);

  /**
   * This method formats the specified <code>long</code> and appends it to
   * a <code>StringBuffer</code>.
   * 
   * @param number The <code>long</code> to format.
   * @param sbuf The <code>StringBuffer</code> to append the formatted number 
   *             to.
   * @param pos The desired <code>FieldPosition</code>.
   *
   * @return The <code>StringBuffer</code> with the appended number.
   */
  public abstract StringBuffer format (long number,
				       StringBuffer sbuf, FieldPosition pos);

  /**
   * This method tests the specified object for equality against this object.
   * This will be <code>true</code> if the following conditions are met:
   * <p>
   * <ul>
   * <li>The specified object is not <code>null</code>.
   * <li>The specified object is an instance of <code>NumberFormat</code>.
   * </ul>
   * <p>
   * Since this method does not test much, it is highly advised that 
   * concrete subclasses override this method.
   *
   * @param obj The <code>Object</code> to test against equality with
   *            this object. 
   * 
   * @return <code>true</code> if the specified object is equal to
   * this object, <code>false</code> otherwise. 
   */
  public boolean equals (Object obj)
  {
    if (! (obj instanceof NumberFormat))
      return false;
    NumberFormat nf = (NumberFormat) obj;
    return (groupingUsed == nf.groupingUsed
	    && maximumFractionDigits == nf.maximumFractionDigits
	    && maximumIntegerDigits == nf.maximumIntegerDigits
	    && minimumFractionDigits == nf.minimumFractionDigits
	    && minimumIntegerDigits == nf.minimumIntegerDigits
	    && parseIntegerOnly == nf.parseIntegerOnly);
  }

  /**
   * This method returns a list of locales for which concrete instances
   * of <code>NumberFormat</code> subclasses may be created.
   *
   * @return The list of available locales.
   */
  public static Locale[] getAvailableLocales ()
  {
    Locale[] list = new Locale[1];
    list[0] = Locale.US;
    return list;
  }

  private static NumberFormat computeInstance(Locale loc, String resource,
                                              String def)
    throws MissingResourceException
  {
    if (loc.equals(Locale.ROOT))
      return new DecimalFormat(def, DecimalFormatSymbols.getInstance(loc)); 
    ResourceBundle res =
      ResourceBundle.getBundle("gnu.java.locale.LocaleInformation",
			       loc, ClassLoader.getSystemClassLoader());
    String fmt;
    try
      {
	fmt = res == null ? def : res.getString(resource);
      }
    catch (MissingResourceException x)
      {
	fmt = def;
      }
    DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(loc);
    return new DecimalFormat (fmt, dfs);
  }

  /**
   * This method returns an instance of <code>NumberFormat</code> suitable
   * for formatting and parsing currency values in the default locale.
   *
   * @return An instance of <code>NumberFormat</code> for handling currencies.
   */
  public static final NumberFormat getCurrencyInstance ()
  {
    return getCurrencyInstance (Locale.getDefault());
  }

  /**
   * This method returns an instance of <code>NumberFormat</code> suitable
   * for formatting and parsing currency values in the specified locale.
   *
   * @return An instance of <code>NumberFormat</code> for handling currencies.
   */
  public static NumberFormat getCurrencyInstance (Locale loc)
  {
    try
      {
	NumberFormat format;
	
	format = computeInstance (loc, "currencyFormat",
				  "\u00A4#,##0.00;(\u00A4#,##0.00)");
	format.setMaximumFractionDigits(format.getCurrency().getDefaultFractionDigits());  
	return format;
      }
    catch (MissingResourceException e)
      {
	for (NumberFormatProvider p :
	       ServiceLoader.load(NumberFormatProvider.class))
	  {
	    for (Locale l : p.getAvailableLocales())
	      {
		if (l.equals(loc))
		  {
		    NumberFormat nf = p.getCurrencyInstance(loc);
		    if (nf != null)
		      return nf;
		    break;
		  }
	      }
	  }
	return getCurrencyInstance(LocaleHelper.getFallbackLocale(loc));
      }
  }

  /**
   * This method returns a default instance for the default locale. This
   * will be a concrete subclass of <code>NumberFormat</code>, but the 
   * actual class returned is dependent on the locale.
   *
   * @return An instance of the default <code>NumberFormat</code> class.
   */
  public static final NumberFormat getInstance ()
  {
    return getInstance (Locale.getDefault());
  }

  /**
   * This method returns a default instance for the specified locale. This
   * will be a concrete subclass of <code>NumberFormat</code>, but the 
   * actual class returned is dependent on the locale.
   *
   * @param loc The desired locale.
   *
   * @return An instance of the default <code>NumberFormat</code> class.
   */
  public static NumberFormat getInstance (Locale loc)
  {
    // For now always return a number instance.
    return getNumberInstance (loc);
  }

  /**
   * This method returns the maximum number of digits allowed in the fraction
   * portion of a number.
   *
   * @return The maximum number of digits allowed in the fraction
   * portion of a number. 
   */
  public int getMaximumFractionDigits ()
  {
    return maximumFractionDigits;
  }

  /**
   * This method returns the maximum number of digits allowed in the integer
   * portion of a number.
   *
   * @return The maximum number of digits allowed in the integer
   * portion of a number. 
   */
  public int getMaximumIntegerDigits ()
  {
    return maximumIntegerDigits;
  }

  /**
   * This method returns the minimum number of digits allowed in the fraction
   * portion of a number.
   *
   * @return The minimum number of digits allowed in the fraction
   * portion of a number. 
   */
  public int getMinimumFractionDigits ()
  {
    return minimumFractionDigits;
  }

  /**
   * This method returns the minimum number of digits allowed in the integer
   * portion of a number.
   *
   * @return The minimum number of digits allowed in the integer
   * portion of a number. 
   */
  public int getMinimumIntegerDigits ()
  {
    return minimumIntegerDigits;
  }

  /**
   * This method returns a default instance for the specified locale. This
   * will be a concrete subclass of <code>NumberFormat</code>, but the 
   * actual class returned is dependent on the locale.
   *
   * @return An instance of the default <code>NumberFormat</code> class.
   */
  public static final NumberFormat getNumberInstance ()
  {
    return getNumberInstance (Locale.getDefault());
  }

  /**
   * This method returns a general purpose number formatting and parsing
   * class for the default locale.  This will be a concrete subclass of
   * <code>NumberFormat</code>, but the actual class returned is dependent
   * on the locale.
   *
   * @return An instance of a generic number formatter for the default locale.
   */
  public static NumberFormat getNumberInstance (Locale loc)
  {
    try
      {
	return computeInstance (loc, "numberFormat", "#,##0.###");
      }
    catch (MissingResourceException e)
      {
	for (NumberFormatProvider p :
	       ServiceLoader.load(NumberFormatProvider.class))
	  {
	    for (Locale l : p.getAvailableLocales())
	      {
		if (l.equals(loc))
		  {
		    NumberFormat nf = p.getNumberInstance(loc);
		    if (nf != null)
		      return nf;
		    break;
		  }
	      }
	  }
	return getNumberInstance(LocaleHelper.getFallbackLocale(loc));
      }
  }

  /**
   * This method returns an integer formatting and parsing class for the
   * default locale. This will be a concrete subclass of <code>NumberFormat</code>,
   * but the actual class returned is dependent on the locale.
   *
   * @return An instance of an integer number formatter for the default locale.
   * @since 1.4 
   */
  public static final NumberFormat getIntegerInstance()
  {
    return getIntegerInstance (Locale.getDefault());
  }

  /**
   * This method returns an integer formatting and parsing class for the
   * default locale. This will be a concrete subclass of <code>NumberFormat</code>,
   * but the actual class returned is dependent on the locale.
   *
   * @param locale the desired locale.
   *
   * @return An instance of an integer number formatter for the desired locale.
   * @since 1.4 
   */
  public static NumberFormat getIntegerInstance(Locale locale)
  {
    try
      {
	NumberFormat format = computeInstance (locale,
					       "integerFormat", "#,##0");
	format.setMaximumFractionDigits(0);
	format.setParseIntegerOnly (true);
	return format;
      }
    catch (MissingResourceException e)
      {
	for (NumberFormatProvider p :
	       ServiceLoader.load(NumberFormatProvider.class))
	  {
	    for (Locale l : p.getAvailableLocales())
	      {
		if (l.equals(locale))
		  {
		    NumberFormat nf = p.getIntegerInstance(locale);
		    if (nf != null)
		      return nf;
		    break;
		  }
	      }
	  }
	return getIntegerInstance(LocaleHelper.getFallbackLocale(locale));
      }
  }

  /**
   * This method returns an instance of <code>NumberFormat</code> suitable
   * for formatting and parsing percentage values in the default locale.
   *
   * @return An instance of <code>NumberFormat</code> for handling percentages.
   */
  public static final NumberFormat getPercentInstance ()
  {
    return getPercentInstance (Locale.getDefault());
  }

  /**
   * This method returns an instance of <code>NumberFormat</code> suitable
   * for formatting and parsing percentage values in the specified locale.
   *
   * @param loc The desired locale.
   *
   * @return An instance of <code>NumberFormat</code> for handling percentages.
   */
  public static NumberFormat getPercentInstance (Locale loc)
  {
    try
      {
	return computeInstance (loc, "percentFormat", "#,##0%");
      }
    catch (MissingResourceException e)
      {
	for (NumberFormatProvider p :
	       ServiceLoader.load(NumberFormatProvider.class))
	  {
	    for (Locale l : p.getAvailableLocales())
	      {
		if (l.equals(loc))
		  {
		    NumberFormat nf = p.getPercentInstance(loc);
		    if (nf != null)
		      return nf;
		    break;
		  }
	      }
	  }
	return getPercentInstance(LocaleHelper.getFallbackLocale(loc));
      }
  }

  /**
   * This method returns a hash value for this object.
   *
   * @return The hash code.
   */
  public int hashCode ()
  {
    int hash = super.hashCode();
    hash ^= (maximumFractionDigits + maximumIntegerDigits
	     + minimumFractionDigits + minimumIntegerDigits);
    if (groupingUsed)
      hash ^= 0xf0f0;
    if (parseIntegerOnly)
      hash ^= 0x0f0f;
    return hash;
  }

  /**
   * This method tests whether or not grouping is in use.  Grouping is
   * a method of marking separations in numbers, such as thousand separators
   * in the US English locale.  The grouping positions and symbols are all
   * locale specific.  As an example, with grouping disabled, the number one
   * million would appear as "1000000".  With grouping enabled, this number
   * might appear as "1,000,000".  (Both of these assume the US English
   * locale).
   *
   * @return <code>true</code> if grouping is enabled,
   * <code>false</code> otherwise. 
   */
  public boolean isGroupingUsed ()
  {
    return groupingUsed;
  }

  /**
   * This method tests whether or not only integer values should be parsed.
   * If this class is parsing only integers, parsing stops at the decimal
   * point.
   *
   * @return <code>true</code> if only integers are parsed,
   * <code>false</code> otherwise. 
   */
  public boolean isParseIntegerOnly ()
  {
    return parseIntegerOnly;
  }

  /**
   * This is a default constructor for use by subclasses.
   */
  public NumberFormat ()
  {
  }

  /**
   * This method parses the specified string into a <code>Number</code>.  This
   * will be a <code>Long</code> if possible, otherwise it will be a
   * <code>Double</code>.    If no number can be parsed, no exception is
   * thrown.  Instead, the parse position remains at its initial index.
   *
   * @param sourceStr The string to parse.
   * @param pos The desired <code>ParsePosition</code>.
   *
   * @return The parsed <code>Number</code>
   */
  public abstract Number parse (String sourceStr, ParsePosition pos);

  /**
   * This method parses the specified string into a <code>Number</code>.  This
   * will be a <code>Long</code> if possible, otherwise it will be a
   * <code>Double</code>.  If no number can be parsed, an exception will be
   * thrown.
   *
   * @param sourceStr The string to parse.
   *
   * @return The parsed <code>Number</code>
   *
   * @exception ParseException If no number can be parsed.
   */
  public Number parse (String sourceStr) throws ParseException
  {
    ParsePosition pp = new ParsePosition (0);
    Number r = parse (sourceStr, pp);
    if (r == null)
      {
	int index = pp.getErrorIndex();
	if (index < 0)
	  index = pp.getIndex();
	throw new ParseException ("couldn't parse number", index);
      }
    return r;
  }

  /**
   * This method parses the specified string into an <code>Object</code>.  This
   * will be a <code>Long</code> if possible, otherwise it will be a
   * <code>Double</code>.    If no number can be parsed, no exception is
   * thrown.  Instead, the parse position remains at its initial index.
   *
   * @param sourceStr The string to parse.
   * @param pos The desired <code>ParsePosition</code>.
  *
  * @return The parsed <code>Object</code>
  */
  public final Object parseObject (String sourceStr, ParsePosition pos)
  {
    return parse (sourceStr, pos);
  }

  /**
   * This method sets the grouping behavior of this formatter.  Grouping is
   * a method of marking separations in numbers, such as thousand separators
   * in the US English locale.  The grouping positions and symbols are all
   * locale specific.  As an example, with grouping disabled, the number one
   * million would appear as "1000000".  With grouping enabled, this number
   * might appear as "1,000,000".  (Both of these assume the US English
   * locale).
   *
   * @param newValue <code>true</code> to enable grouping,
   *                     <code>false</code> to disable it. 
   */
  public void setGroupingUsed (boolean newValue)
  {
    groupingUsed = newValue;
  }

  /**
   * This method sets the maximum number of digits allowed in the fraction
   * portion of a number to the specified value.  If this is less than the
   * current minimum allowed digits, the minimum allowed digits value will
   * be lowered to be equal to the new maximum allowed digits value.
   *
   * @param digits The new maximum fraction digits value.
   */
  public void setMaximumFractionDigits (int digits)
  {
    maximumFractionDigits = digits;
    if (getMinimumFractionDigits () > maximumFractionDigits)
      setMinimumFractionDigits (maximumFractionDigits);
  }

  /**
   * This method sets the maximum number of digits allowed in the integer
   * portion of a number to the specified value.  If this is less than the
   * current minimum allowed digits, the minimum allowed digits value will
   * be lowered to be equal to the new maximum allowed digits value.
   *
   * @param digits The new maximum integer digits value.
   */
  public void setMaximumIntegerDigits (int digits)
  {
    maximumIntegerDigits = digits;
    if (getMinimumIntegerDigits () > maximumIntegerDigits)
      setMinimumIntegerDigits (maximumIntegerDigits);
  }

  /**
   * This method sets the minimum number of digits allowed in the fraction
   * portion of a number to the specified value.  If this is greater than the
   * current maximum allowed digits, the maximum allowed digits value will
   * be raised to be equal to the new minimum allowed digits value.
   *
   * @param digits The new minimum fraction digits value.
   */
  public void setMinimumFractionDigits (int digits)
  {
    minimumFractionDigits = digits;
    if (getMaximumFractionDigits () < minimumFractionDigits)
      setMaximumFractionDigits (minimumFractionDigits);
  }

  /**
   * This method sets the minimum number of digits allowed in the integer
   * portion of a number to the specified value.  If this is greater than the
   * current maximum allowed digits, the maximum allowed digits value will
   * be raised to be equal to the new minimum allowed digits value.
   *
   * @param digits The new minimum integer digits value.
   */
  public void setMinimumIntegerDigits (int digits)
  {
    minimumIntegerDigits = digits;
    if (getMaximumIntegerDigits () < minimumIntegerDigits)
      setMaximumIntegerDigits (minimumIntegerDigits);
  }

  /** 
   * This method sets the parsing behavior of this object to parse only 
   * integers or not.
   *
   * @param value <code>true</code> to parse only integers,
   *                         <code>false</code> otherwise. 
   */
  public void setParseIntegerOnly (boolean value)
  {
    parseIntegerOnly = value;
  }

  /**
   * This method is a specialization of the format method that performs
   * a simple formatting of the specified <code>double</code> number.
   *
   * @param number The <code>double</code> to format.
   *
   * @return The formatted number
   */
  public final String format (double number)
  {
    StringBuffer sbuf = new StringBuffer(50);
    FieldPosition position = new FieldPosition(0);
    
    format (number, sbuf, position);
    return sbuf.toString();
  }

  // These field names are fixed by the serialization spec.
  boolean groupingUsed;
  int maximumFractionDigits;
  private byte maxFractionDigits;
  int maximumIntegerDigits;
  private byte maxIntegerDigits;
  int minimumFractionDigits;
  private byte minFractionDigits;
  int minimumIntegerDigits;
  private byte minIntegerDigits;
  boolean parseIntegerOnly;
  private int serialVersionOnStream;
  private static final long serialVersionUID = -2308460125733713944L;

  private void readObject(ObjectInputStream stream)
    throws IOException, ClassNotFoundException
  {
    stream.defaultReadObject();
    if (serialVersionOnStream < 1)
      {
        maximumFractionDigits = maxFractionDigits;
	maximumIntegerDigits = maxIntegerDigits;
	minimumFractionDigits = minFractionDigits;
	minimumIntegerDigits = minIntegerDigits;
	serialVersionOnStream = 1;
      }
  }

  private void writeObject(ObjectOutputStream stream) throws IOException
  {
    maxFractionDigits = maximumFractionDigits < Byte.MAX_VALUE ?
      (byte) maximumFractionDigits : Byte.MAX_VALUE;
    maxIntegerDigits = maximumIntegerDigits < Byte.MAX_VALUE ?
      (byte) maximumIntegerDigits : Byte.MAX_VALUE;
    minFractionDigits = minimumFractionDigits < Byte.MAX_VALUE ?
      (byte) minimumFractionDigits : Byte.MAX_VALUE;
    minIntegerDigits = minimumIntegerDigits < Byte.MAX_VALUE ?
      (byte) minimumIntegerDigits : Byte.MAX_VALUE;
    serialVersionOnStream = 1;
    stream.defaultWriteObject();
  }

  /**
   * Returns the currency used by this number format when formatting currency
   * values.
   *
   * The default implementation throws UnsupportedOperationException.
   *
   * @return The used currency object, or null.
   *
   * @throws UnsupportedOperationException If the number format class doesn't
   * implement currency formatting.
   *
   * @since 1.4
   */
  public Currency getCurrency()
  {
    throw new UnsupportedOperationException();
  }

  /**
   * Sets the currency used by this number format when formatting currency
   * values.
   *
   * The default implementation throws UnsupportedOperationException.
   *
   * @param currency The new currency to be used by this number format.
   *
   * @throws NullPointerException If currenc is null.
   * @throws UnsupportedOperationException If the number format class doesn't
   * implement currency formatting.
   *
   * @since 1.4
   */
  public void setCurrency(Currency currency)
  {
    if (currency == null)
      throw new NullPointerException("currency may not be null");
    
    throw new UnsupportedOperationException();
  }
}
