/* DecimalFormat.java -- Formats and parses numbers
   Copyright (C) 1999, 2000, 2001 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., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA.

As a special exception, if you link this library with other files to
produce an executable, this library does not by itself cause the
resulting executable to be covered by the GNU General Public License.
This exception does not however invalidate any other reasons why the
executable file might be covered by the GNU General Public License. */

package java.text;

import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.io.ObjectInputStream;
import java.io.IOException;

/**
 * @author Tom Tromey <tromey@cygnus.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.
 * Note however that the docs are very unclear about how format parsing
 * should work.  No doubt there are problems here.
 */
public class DecimalFormat extends NumberFormat
{
  // This is a helper for applyPatternWithSymbols.  It reads a prefix
  // or a suffix.  It can cause some side-effects.
  private final int scanFix (String pattern, int index, StringBuffer buf,
			     String patChars, DecimalFormatSymbols syms,
			     boolean is_suffix)
  {
    int len = pattern.length();
    buf.setLength(0);
    boolean multiplierSet = false;
    while (index < len)
      {
	char c = pattern.charAt(index);
	if (c == '\'' && index + 1 < len
	    && pattern.charAt(index + 1) == '\'')
	  {
	    buf.append(c);
	    ++index;
	  }
	else if (c == '\'' && index + 2 < len
		 && pattern.charAt(index + 2) == '\'')
	  {
	    buf.append(pattern.charAt(index + 1));
	    index += 2;
	  }
	else if (c == '\u00a4')
	  {
	    if (index + 1 < len && pattern.charAt(index + 1) == '\u00a4')
	      {
		buf.append(syms.getInternationalCurrencySymbol());
		++index;
	      }
	    else
	      buf.append(syms.getCurrencySymbol());
	  }
	else if (is_suffix && c == syms.getPercent())
	  {
	    if (multiplierSet)
	      throw new IllegalArgumentException ("multiplier already set " +
						  "- index: " + index);
	    multiplierSet = true;
	    multiplier = 100;
	    buf.append(c);
	  }
	else if (is_suffix && c == syms.getPerMill())
	  {
	    if (multiplierSet)
	      throw new IllegalArgumentException ("multiplier already set " +
						  "- index: " + index);
	    multiplierSet = true;
	    multiplier = 1000;
	    buf.append(c);
	  }
	else if (patChars.indexOf(c) != -1)
	  {
	    // This is a pattern character.
	    break;
	  }
	else
	  buf.append(c);
	++index;
      }

    return index;
  }

  // A helper which reads a number format.
  private final int scanFormat (String pattern, int index,
				String patChars, DecimalFormatSymbols syms,
				boolean is_positive)
  {
    int max = pattern.length();

    int countSinceGroup = 0;
    int zeroCount = 0;
    boolean saw_group = false;

    //
    // Scan integer part.
    //
    while (index < max)
      {
	char c = pattern.charAt(index);

	if (c == syms.getDigit())
	  {
	    if (zeroCount > 0)
	      throw new IllegalArgumentException ("digit mark following " +
						  "zero - index: " + index);
	    ++countSinceGroup;
	  }
	else if (c == syms.getZeroDigit())
	  {
	    ++zeroCount;
	    ++countSinceGroup;
	  }
	else if (c == syms.getGroupingSeparator())
	  {
	    countSinceGroup = 0;
	    saw_group = true;
	  }
	else
	  break;

	++index;
      }

    // We can only side-effect when parsing the positive format.
    if (is_positive)
      {
	groupingUsed = saw_group;
	groupingSize = (byte) countSinceGroup;
	minimumIntegerDigits = zeroCount;
      }

    // Early termination.
    if (index == max || pattern.charAt(index) == syms.getGroupingSeparator())
      {
	if (is_positive)
	  decimalSeparatorAlwaysShown = false;
	return index;
      }

    if (pattern.charAt(index) == syms.getDecimalSeparator())
      {
	++index;

	//
	// Scan fractional part.
	//
	int hashCount = 0;
	zeroCount = 0;
	while (index < max)
	  {
	    char c = pattern.charAt(index);
	    if (c == syms.getZeroDigit())
	      {
		if (hashCount > 0)
		  throw new IllegalArgumentException ("zero mark " +
						      "following digit - index: " + index);
		++zeroCount;
	      }
	    else if (c == syms.getDigit())
	      {
		++hashCount;
	      }
	    else if (c != syms.getExponential()
		     && c != syms.getPatternSeparator()
		     && patChars.indexOf(c) != -1)
	      throw new IllegalArgumentException ("unexpected special " +
						  "character - index: " + index);
	    else
	      break;

	    ++index;
	  }

	if (is_positive)
	  {
	    maximumFractionDigits = hashCount + zeroCount;
	    minimumFractionDigits = zeroCount;
	  }

	if (index == max)
	  return index;
      }

    if (pattern.charAt(index) == syms.getExponential())
      {
	//
	// Scan exponential format.
	//
	zeroCount = 0;
	++index;
	while (index < max)
	  {
	    char c = pattern.charAt(index);
	    if (c == syms.getZeroDigit())
	      ++zeroCount;
	    else if (c == syms.getDigit())
	      {
		if (zeroCount > 0)
		  throw new
		    IllegalArgumentException ("digit mark following zero " +
					      "in exponent - index: " +
					      index);
	      }
	    else if (patChars.indexOf(c) != -1)
	      throw new IllegalArgumentException ("unexpected special " +
						  "character - index: " +
						  index);
	    else
	      break;

	    ++index;
	  }

	if (is_positive)
	  {
	    useExponentialNotation = true;
	    minExponentDigits = (byte) zeroCount;
	  }
      }

    return index;
  }

  // This helper function creates a string consisting of all the
  // characters which can appear in a pattern and must be quoted.
  private final String patternChars (DecimalFormatSymbols syms)
  {
    StringBuffer buf = new StringBuffer ();
    buf.append(syms.getDecimalSeparator());
    buf.append(syms.getDigit());
    buf.append(syms.getExponential());
    buf.append(syms.getGroupingSeparator());
    // Adding this one causes pattern application to fail.
    // Of course, omitting is causes toPattern to fail.
    // ... but we already have bugs there.  FIXME.
    // buf.append(syms.getMinusSign());
    buf.append(syms.getPatternSeparator());
    buf.append(syms.getPercent());
    buf.append(syms.getPerMill());
    buf.append(syms.getZeroDigit());
    buf.append('\u00a4');
    return buf.toString();
  }

  private final void applyPatternWithSymbols (String pattern,
					      DecimalFormatSymbols syms)
  {
    // Initialize to the state the parser expects.
    negativePrefix = "";
    negativeSuffix = "";
    positivePrefix = "";
    positiveSuffix = "";
    decimalSeparatorAlwaysShown = false;
    groupingSize = 0;
    minExponentDigits = 0;
    multiplier = 1;
    useExponentialNotation = false;
    groupingUsed = false;
    maximumFractionDigits = 0;
    maximumIntegerDigits = 309;
    minimumFractionDigits = 0;
    minimumIntegerDigits = 1;

    StringBuffer buf = new StringBuffer ();
    String patChars = patternChars (syms);

    int max = pattern.length();
    int index = scanFix (pattern, 0, buf, patChars, syms, false);
    positivePrefix = buf.toString();

    index = scanFormat (pattern, index, patChars, syms, true);

    index = scanFix (pattern, index, buf, patChars, syms, true);
    positiveSuffix = buf.toString();

    if (index == pattern.length())
      {
	// No negative info.
	negativePrefix = null;
	negativeSuffix = null;
      }
    else
      {
	if (pattern.charAt(index) != syms.getPatternSeparator())
	  throw new IllegalArgumentException ("separator character " +
					      "expected - index: " + index);

	index = scanFix (pattern, index + 1, buf, patChars, syms, false);
	negativePrefix = buf.toString();

	// We parse the negative format for errors but we don't let
	// it side-effect this object.
	index = scanFormat (pattern, index, patChars, syms, false);

	index = scanFix (pattern, index, buf, patChars, syms, true);
	negativeSuffix = buf.toString();

	if (index != pattern.length())
	  throw new IllegalArgumentException ("end of pattern expected " +
					      "- index: " + index);
      }
  }

  public void applyLocalizedPattern (String pattern)
  {
    // JCL p. 638 claims this throws a ParseException but p. 629
    // contradicts this.  Empirical tests with patterns of "0,###.0"
    // and "#.#.#" corroborate the p. 629 statement that an
    // IllegalArgumentException is thrown.
    applyPatternWithSymbols (pattern, symbols);
  }

  public void applyPattern (String pattern)
  {
    // JCL p. 638 claims this throws a ParseException but p. 629
    // contradicts this.  Empirical tests with patterns of "0,###.0"
    // and "#.#.#" corroborate the p. 629 statement that an
    // IllegalArgumentException is thrown.
    applyPatternWithSymbols (pattern, nonLocalizedSymbols);
  }

  public Object clone ()
  {
    DecimalFormat c = (DecimalFormat) super.clone ();
    c.symbols = (DecimalFormatSymbols) symbols.clone ();
    return c;
  }

  public DecimalFormat ()
  {
    this ("#,##0.###");
  }

  public DecimalFormat (String pattern)
  {
    this (pattern, new DecimalFormatSymbols ());
  }

  public DecimalFormat (String pattern, DecimalFormatSymbols symbols)
  {
    this.symbols = symbols;
    applyPattern (pattern);
  }

  private final boolean equals (String s1, String s2)
  {
    if (s1 == null || s2 == null)
      return s1 == s2;
    return s1.equals(s2);
  }

  public boolean equals (Object obj)
  {
    if (! (obj instanceof DecimalFormat))
      return false;
    DecimalFormat dup = (DecimalFormat) obj;
    return (decimalSeparatorAlwaysShown == dup.decimalSeparatorAlwaysShown
	    && groupingSize == dup.groupingSize
	    && minExponentDigits == dup.minExponentDigits
	    && multiplier == dup.multiplier
	    && equals(negativePrefix, dup.negativePrefix)
	    && equals(negativeSuffix, dup.negativeSuffix)
	    && equals(positivePrefix, dup.positivePrefix)
	    && equals(positiveSuffix, dup.positiveSuffix)
	    && symbols.equals(dup.symbols)
	    && useExponentialNotation == dup.useExponentialNotation);
  }

  public StringBuffer format (double number, StringBuffer dest,
			      FieldPosition fieldPos)
  {
    // A very special case.
    if (Double.isNaN(number))
      {
	dest.append(symbols.getNaN());
	if (fieldPos != null && fieldPos.getField() == INTEGER_FIELD)
	  {
	    int index = dest.length();
	    fieldPos.setBeginIndex(index - symbols.getNaN().length());
	    fieldPos.setEndIndex(index);
	  }
	return dest;
      }

    boolean is_neg = number < 0;
    if (is_neg)
      {
	if (negativePrefix != null)
	  dest.append(negativePrefix);
	else
	  {
	    dest.append(symbols.getMinusSign());
	    dest.append(positivePrefix);
	  }
	number = - number;
      }
    else
      dest.append(positivePrefix);

    int integerBeginIndex = dest.length();
    int integerEndIndex = 0;
    if (Double.isInfinite (number))
      {
	dest.append(symbols.getInfinity());
	integerEndIndex = dest.length();
      }
    else
      {
	number *= multiplier;

	// Compute exponent.
	long exponent = 0;
	double baseNumber;
	if (useExponentialNotation)
	  {
	    exponent = (long) Math.floor (Math.log(number) / Math.log(10));
	    if (minimumIntegerDigits > 0)
	      exponent -= minimumIntegerDigits - 1;
	    baseNumber = (long) (number / Math.pow(10.0, exponent));
	  }
	else
	  baseNumber = number;

	// Round to the correct number of digits.
	baseNumber += 5 * Math.pow(10.0, - maximumFractionDigits - 1);

	int index = dest.length();
	double intPart = Math.floor(baseNumber);
	int count = 0;
	while (count < maximumIntegerDigits
	       && (intPart > 0 || count < minimumIntegerDigits))
	  {
	    long dig = (long) (intPart % 10);
	    intPart = Math.floor(intPart / 10);

	    // Append group separator if required.
	    if (groupingUsed && count > 0 && count % groupingSize == 0)
	      dest.insert(index, symbols.getGroupingSeparator());

	    dest.insert(index, (char) (symbols.getZeroDigit() + dig));

	    ++count;
	  }

	integerEndIndex = dest.length();

	int decimal_index = integerEndIndex;
	int consecutive_zeros = 0;
	int total_digits = 0;

	// Strip integer part from NUMBER.
	double fracPart = baseNumber - Math.floor(baseNumber);
	for (count = 0;
	     count < maximumFractionDigits
	       && (fracPart != 0 || count < minimumFractionDigits);
	     ++count)
	  {
	    ++total_digits;
	    fracPart *= 10;
	    long dig = (long) fracPart;
	    if (dig == 0)
	      ++consecutive_zeros;
	    else
	      consecutive_zeros = 0;
	    dest.append((char) (symbols.getZeroDigit() + dig));

	    // Strip integer part from FRACPART.
	    fracPart = fracPart - Math.floor (fracPart);
	  }

	// Strip extraneous trailing `0's.  We can't always detect
	// these in the loop.
	int extra_zeros = Math.min (consecutive_zeros,
				    total_digits - minimumFractionDigits);
	if (extra_zeros > 0)
	  {
	    dest.setLength(dest.length() - extra_zeros);
	    total_digits -= extra_zeros;
	  }

	// If required, add the decimal symbol.
	if (decimalSeparatorAlwaysShown
	    || total_digits > 0)
	  {
	    dest.insert(decimal_index, symbols.getDecimalSeparator());
	    if (fieldPos != null && fieldPos.getField() == FRACTION_FIELD)
	      {
		fieldPos.setBeginIndex(decimal_index + 1);
		fieldPos.setEndIndex(dest.length());
	      }
	  }

	// Finally, print the exponent.
	if (useExponentialNotation)
	  {
	    dest.append(symbols.getExponential());
	    if (exponent < 0)
	      {
		dest.append (symbols.getMinusSign ());
		exponent = - exponent;
	      }
	    index = dest.length();
	    for (count = 0;
		 exponent > 0 || count < minExponentDigits;
		 ++count)
	      {
		long dig = exponent % 10;
		exponent /= 10;
		dest.insert(index, (char) (symbols.getZeroDigit() + dig));
	      }
	  }
      }

    if (fieldPos != null && fieldPos.getField() == INTEGER_FIELD)
      {
	fieldPos.setBeginIndex(integerBeginIndex);
	fieldPos.setEndIndex(integerEndIndex);
      }

    dest.append((is_neg && negativeSuffix != null)
		? negativeSuffix
		: positiveSuffix);
    return dest;
  }

  public StringBuffer format (long number, StringBuffer dest,
			      FieldPosition fieldPos)
  {
    // If using exponential notation, we just format as a double.
    if (useExponentialNotation)
      return format ((double) number, dest, fieldPos);

    boolean is_neg = number < 0;
    if (is_neg)
      {
	if (negativePrefix != null)
	  dest.append(negativePrefix);
	else
	  {
	    dest.append(symbols.getMinusSign());
	    dest.append(positivePrefix);
	  }
	number = - number;
      }
    else
      dest.append(positivePrefix);

    int integerBeginIndex = dest.length();
    int index = dest.length();
    int count = 0;
    while (count < maximumIntegerDigits
	   && (number > 0 || count < minimumIntegerDigits))
      {
	long dig = number % 10;
	number /= 10;
	// NUMBER and DIG will be less than 0 if the original number
	// was the most negative long.
	if (dig < 0)
	  {
	    dig = - dig;
	    number = - number;
	  }

	// Append group separator if required.
	if (groupingUsed && count > 0 && count % groupingSize == 0)
	  dest.insert(index, symbols.getGroupingSeparator());

	dest.insert(index, (char) (symbols.getZeroDigit() + dig));

	++count;
      }

    if (fieldPos != null && fieldPos.getField() == INTEGER_FIELD)
      {
	fieldPos.setBeginIndex(integerBeginIndex);
	fieldPos.setEndIndex(dest.length());
      }

    if (decimalSeparatorAlwaysShown || minimumFractionDigits > 0)
      {
	dest.append(symbols.getDecimalSeparator());
	if (fieldPos != null && fieldPos.getField() == FRACTION_FIELD)
	  {
	    fieldPos.setBeginIndex(dest.length());
	    fieldPos.setEndIndex(dest.length() + minimumFractionDigits);
	  }
      }

    for (count = 0; count < minimumFractionDigits; ++count)
      dest.append(symbols.getZeroDigit());

    dest.append((is_neg && negativeSuffix != null)
		? negativeSuffix
		: positiveSuffix);
    return dest;
  }

  public DecimalFormatSymbols getDecimalFormatSymbols ()
  {
    return symbols;
  }

  public int getGroupingSize ()
  {
    return groupingSize;
  }

  public int getMultiplier ()
  {
    return multiplier;
  }

  public String getNegativePrefix ()
  {
    return negativePrefix;
  }

  public String getNegativeSuffix ()
  {
    return negativeSuffix;
  }

  public String getPositivePrefix ()
  {
    return positivePrefix;
  }

  public String getPositiveSuffix ()
  {
    return positiveSuffix;
  }

  public int hashCode ()
  {
    int hash = (negativeSuffix.hashCode() ^ negativePrefix.hashCode()
		^positivePrefix.hashCode() ^ positiveSuffix.hashCode());
    // FIXME.
    return hash;
  }

  public boolean isDecimalSeparatorAlwaysShown ()
  {
    return decimalSeparatorAlwaysShown;
  }

  public Number parse (String str, ParsePosition pos)
  {
    // Our strategy is simple: copy the text into a buffer,
    // translating or omitting locale-specific information.  Then
    // let Double or Long convert the number for us.

    boolean is_neg = false;
    int index = pos.getIndex();
    StringBuffer buf = new StringBuffer ();

      // We have to check both prefixes, because one might be empty.
      // We want to pick the longest prefix that matches.
    boolean got_pos = str.startsWith(positivePrefix, index);
    String np = (negativePrefix != null
		 ? negativePrefix
		 : positivePrefix + symbols.getMinusSign());
    boolean got_neg = str.startsWith(np, index);

    if (got_pos && got_neg)
      {
	// By checking this way, we preserve ambiguity in the case
	// where the negative format differs only in suffix.  We
	// check this again later.
	if (np.length() > positivePrefix.length())
	  {
	    is_neg = true;
	    index += np.length();
	  }
	else
	  index += positivePrefix.length();
      }
    else if (got_neg)
      {
	is_neg = true;
	index += np.length();
      }
    else if (got_pos)
      index += positivePrefix.length();
    else
      {
	pos.setErrorIndex (index);
	return null;
      }

    // FIXME: handle Inf and NaN.

      // FIXME: do we have to respect minimum/maxmimum digit stuff?
      // What about leading zeros?  What about multiplier?

    int start_index = index;
    int max = str.length();
    char zero = symbols.getZeroDigit();
    int last_group = -1;
    boolean int_part = true;
    boolean exp_part = false;
    for (; index < max; ++index)
      {
	char c = str.charAt(index);

	// FIXME: what about grouping size?
	if (groupingUsed && c == symbols.getGroupingSeparator())
	  {
	    if (last_group != -1
		&& (index - last_group) % groupingSize != 0)
	      {
		pos.setErrorIndex(index);
		return null;
	      }
	    last_group = index;
	  }
	else if (c >= zero && c <= zero + 9)
	  {
	    buf.append((char) (c - zero + '0'));
	    exp_part = false;
	  }
	else if (parseIntegerOnly)
	  break;
	else if (c == symbols.getDecimalSeparator())
	  {
	    if (last_group != -1
		&& (index - last_group) % groupingSize != 0)
	      {
		pos.setErrorIndex(index);
		return null;
	      }
	    buf.append('.');
	    int_part = false;
	  }
	else if (c == symbols.getExponential())
	  {
	    buf.append('E');
	    int_part = false;
	    exp_part = true;
	  }
	else if (exp_part
		 && (c == '+' || c == '-' || c == symbols.getMinusSign()))
	  {
	    // For exponential notation.
	    buf.append(c);
	  }
	else
	  break;
      }

    if (index == start_index)
      {
	// Didn't see any digits.
	pos.setErrorIndex(index);
	return null;
      }

    // Check the suffix.  We must do this before converting the
    // buffer to a number to handle the case of a number which is
    // the most negative Long.
    boolean got_pos_suf = str.startsWith(positiveSuffix, index);
    String ns = (negativePrefix == null ? positiveSuffix : negativeSuffix);
    boolean got_neg_suf = str.startsWith(ns, index);
    if (is_neg)
      {
	if (! got_neg_suf)
	  {
	    pos.setErrorIndex(index);
	    return null;
	  }
      }
    else if (got_pos && got_neg && got_neg_suf)
      {
	is_neg = true;
      }
    else if (got_pos != got_pos_suf && got_neg != got_neg_suf)
      {
	pos.setErrorIndex(index);
	return null;
      }

    String suffix = is_neg ? ns : positiveSuffix;
    if (is_neg)
      buf.insert(0, '-');

    String t = buf.toString();
    Number result = null;
    try
      {
	result = new Long (t);
      }
    catch (NumberFormatException x1)
      {
	try
	  {
	    result = new Double (t);
	  }
	catch (NumberFormatException x2)
	  {
	  }
      }
    if (result == null)
      {
	pos.setErrorIndex(index);
	return null;
      }

    pos.setIndex(index + suffix.length());

    return result;
  }

  public void setDecimalFormatSymbols (DecimalFormatSymbols newSymbols)
  {
    symbols = newSymbols;
  }

  public void setDecimalSeparatorAlwaysShown (boolean newValue)
  {
    decimalSeparatorAlwaysShown = newValue;
  }

  public void setGroupingSize (int groupSize)
  {
    groupingSize = (byte) groupSize;
  }

  public void setMaximumFractionDigits (int newValue)
  {
    maximumFractionDigits = Math.min(newValue, 340);
  }

  public void setMaximumIntegerDigits (int newValue)
  {
    maximumIntegerDigits = Math.min(newValue, 309);
  }

  public void setMinimumFractionDigits (int newValue)
  {
    minimumFractionDigits = Math.min(newValue, 340);
  }

  public void setMinimumIntegerDigits (int newValue)
  {
    minimumIntegerDigits = Math.min(newValue, 309);
  }

  public void setMultiplier (int newValue)
  {
    multiplier = newValue;
  }

  public void setNegativePrefix (String newValue)
  {
    negativePrefix = newValue;
  }

  public void setNegativeSuffix (String newValue)
  {
    negativeSuffix = newValue;
  }

  public void setPositivePrefix (String newValue)
  {
    positivePrefix = newValue;
  }

  public void setPositiveSuffix (String newValue)
  {
    positiveSuffix = newValue;
  }

  private final void quoteFix (StringBuffer buf, String text, String patChars)
  {
    int len = text.length();
    for (int index = 0; index < len; ++index)
      {
	char c = text.charAt(index);
	if (patChars.indexOf(c) != -1)
	  {
	    buf.append('\'');
	    buf.append(c);
	    buf.append('\'');
	  }
	else
	  buf.append(c);
      }
  }

  private final String computePattern (DecimalFormatSymbols syms)
  {
    StringBuffer mainPattern = new StringBuffer ();
    // We have to at least emit a zero for the minimum number of
    // digits.  Past that we need hash marks up to the grouping
    // separator (and one beyond).
    int total_digits = Math.max(minimumIntegerDigits,
				groupingUsed ? groupingSize + 1: 0);
    for (int i = 0; i < total_digits - minimumIntegerDigits; ++i)
      mainPattern.append(syms.getDigit());
    for (int i = total_digits - minimumIntegerDigits; i < total_digits; ++i)
      mainPattern.append(syms.getZeroDigit());
    // Inserting the gropuing operator afterwards is easier.
    if (groupingUsed)
      mainPattern.insert(mainPattern.length() - groupingSize,
			 syms.getGroupingSeparator());
    // See if we need decimal info.
    if (minimumFractionDigits > 0 || maximumFractionDigits > 0
	|| decimalSeparatorAlwaysShown)
      mainPattern.append(syms.getDecimalSeparator());
    for (int i = 0; i < minimumFractionDigits; ++i)
      mainPattern.append(syms.getZeroDigit());
    for (int i = minimumFractionDigits; i < maximumFractionDigits; ++i)
      mainPattern.append(syms.getDigit());
    if (useExponentialNotation)
      {
	mainPattern.append(syms.getExponential());
	for (int i = 0; i < minExponentDigits; ++i)
	  mainPattern.append(syms.getZeroDigit());
	if (minExponentDigits == 0)
	  mainPattern.append(syms.getDigit());
      }

    String main = mainPattern.toString();
    String patChars = patternChars (syms);
    mainPattern.setLength(0);

    quoteFix (mainPattern, positivePrefix, patChars);
    mainPattern.append(main);
    quoteFix (mainPattern, positiveSuffix, patChars);

    if (negativePrefix != null)
      {
	quoteFix (mainPattern, negativePrefix, patChars);
	mainPattern.append(main);
	quoteFix (mainPattern, negativeSuffix, patChars);
      }

    return mainPattern.toString();
  }

  public String toLocalizedPattern ()
  {
    return computePattern (symbols);
  }

  public String toPattern ()
  {
    return computePattern (nonLocalizedSymbols);
  }

  // These names are fixed by the serialization spec.
  private boolean decimalSeparatorAlwaysShown;
  private byte groupingSize;
  private byte minExponentDigits;
  private int multiplier;
  private String negativePrefix;
  private String negativeSuffix;
  private String positivePrefix;
  private String positiveSuffix;
  private int serialVersionOnStream = 1;
  private DecimalFormatSymbols symbols;
  private boolean useExponentialNotation;
  private static final long serialVersionUID = 864413376551465018L;

  private void readObject(ObjectInputStream stream)
    throws IOException, ClassNotFoundException
  {
    stream.defaultReadObject();
    if (serialVersionOnStream < 1)
      {
        useExponentialNotation = false;
	serialVersionOnStream = 1;
      }
  }

  // The locale-independent pattern symbols happen to be the same as
  // the US symbols.
  private static final DecimalFormatSymbols nonLocalizedSymbols
    = new DecimalFormatSymbols (Locale.US);
}
