/* DecimalFormat.java -- Formats and parses numbers
   Copyright (C) 1999, 2000, 2001, 2003 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.

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 java.util.Currency;
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()
		     && c != syms.getPercent()
		     && c != syms.getPerMill()
		     && 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 = (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 && groupingSize != 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 && groupingSize != 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;
  }

  /**
   * Returns the currency corresponding to the currency symbol stored
   * in the instance of <code>DecimalFormatSymbols</code> used by this
   * <code>DecimalFormat</code>.
   *
   * @return A new instance of <code>Currency</code> if
   * the currency code matches a known one, null otherwise.
   */
  public Currency getCurrency()
  {
    return symbols.getCurrency();
  }

  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 digits?
    // What about leading zeros?  What about multiplier?

    int start_index = index;
    int max = str.length();
    int last = index + maximumIntegerDigits;
    if (last > 0 && max > last)
      max = last;
    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 
		&& groupingSize != 0  
		&& (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 
		&& groupingSize != 0 
		&& (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;
  }

  /**
   * Sets the <code>Currency</code> on the
   * <code>DecimalFormatSymbols</code> used, which also sets the
   * currency symbols on those symbols.
   */
  public void setCurrency(Currency currency)
  {
    symbols.setCurrency(currency);
  }

  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)
  {
    super.setMaximumFractionDigits(Math.min(newValue, 340));
  }

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

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

  public void setMinimumIntegerDigits (int newValue)
  {
    super.setMinimumIntegerDigits(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);
}
