/* DecimalFormat.java -- Formats and parses numbers
   Copyright (C) 1999, 2000, 2001, 2003, 2004, 2005  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.text.AttributedFormatBuffer;
import gnu.java.text.FormatBuffer;
import gnu.java.text.FormatCharacterIterator;
import gnu.java.text.StringFormatBuffer;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.Currency;
import java.util.HashMap;
import java.util.Locale;

/**
 * @author Tom Tromey (tromey@cygnus.com)
 * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
 * @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 int scanFix (String pattern, int index, FormatBuffer buf,
                       String patChars, DecimalFormatSymbols syms,
                       boolean is_suffix)
    {
    int len = pattern.length();
    boolean quoteStarted = false;
    buf.clear();
    
    boolean multiplierSet = false;
    while (index < len)
      {
	char c = pattern.charAt(index);

	if (quoteStarted)
	  {
	    if (c == '\'')
	      quoteStarted = false;
	    else
	      buf.append(c);
	    index++;
	    continue;
	  }

	if (c == '\'' && index + 1 < len
	    && pattern.charAt(index + 1) == '\'')
	  {
	    buf.append(c);
	    index++;
	  }
	else if (c == '\'')
	  {
	    quoteStarted = true;
	  }
	else if (c == '\u00a4')
	  {
			/* Currency interpreted later */
			buf.append(c);
		}
	else if (c == syms.getPercent())
	  {
	    if (multiplierSet)
	      throw new IllegalArgumentException ("multiplier already set " +
						  "- index: " + index);
	    multiplierSet = true;
	    multiplier = 100;
	    buf.append(c, NumberFormat.Field.PERCENT);
	  }
	else if (c == syms.getPerMill())
	  {
	    if (multiplierSet)
	      throw new IllegalArgumentException ("multiplier already set " +
						  "- index: " + index);
	    multiplierSet = true;
	    multiplier = 1000;
	    buf.append(c, NumberFormat.Field.PERMILLE);
	  }
	else if (patChars.indexOf(c) != -1)
	  {
	    // This is a pattern character.
	    break;
	  }
	else
		{
			buf.append(c);
		}
	index++;
      }

    if (quoteStarted)
      throw new IllegalArgumentException ("pattern is lacking a closing quote");

    return index;
  }

  // A helper which reads a number format.
  private 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;
	// Checking "zeroCount > 0" avoids 0 being formatted into "" with "#".
	if (zeroCount > 0)
	  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;
	  }

	maximumIntegerDigits = groupingSize;
	groupingSize = 0;
	if (maximumIntegerDigits > minimumIntegerDigits && maximumIntegerDigits > 0)
	  {
	    minimumIntegerDigits = 1;
	    exponentRound = maximumIntegerDigits;
	  }
	else
	  exponentRound = 1;
      }

    return index;
  }

  // This helper function creates a string consisting of all the
  // characters which can appear in a pattern and must be quoted.
  private 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 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 = MAXIMUM_INTEGER_DIGITS;
    minimumFractionDigits = 0;
    minimumIntegerDigits = 1;

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

    int max = pattern.length();
    int index = scanFix (pattern, 0, buf, patChars, syms, false);
    buf.sync();
    positivePrefix = buf.getBuffer().toString();
    positivePrefixRanges = buf.getRanges();
    positivePrefixAttrs = buf.getAttributes();

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

    index = scanFix (pattern, index, buf, patChars, syms, true);
    buf.sync();
    positiveSuffix = buf.getBuffer().toString();
    positiveSuffixRanges = buf.getRanges();
    positiveSuffixAttrs = buf.getAttributes();

    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);
	buf.sync();
	negativePrefix = buf.getBuffer().toString();
	negativePrefixRanges = buf.getRanges();
	negativePrefixAttrs = buf.getAttributes();

	// 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);
	buf.sync();
	negativeSuffix = buf.getBuffer().toString();
	negativeSuffixRanges = buf.getRanges();
	negativeSuffixAttrs = buf.getAttributes();

	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;
  }

  /**
   * Constructs a <code>DecimalFormat</code> which uses the default
   * pattern and symbols.
   */
  public DecimalFormat ()
  {
    this ("#,##0.###");
  }

  /**
   * Constructs a <code>DecimalFormat</code> which uses the given
   * pattern and the default symbols for formatting and parsing.
   *
   * @param pattern the non-localized pattern to use.
   * @throws NullPointerException if any argument is null.
   * @throws IllegalArgumentException if the pattern is invalid.
   */
  public DecimalFormat (String pattern)
  {
    this (pattern, new DecimalFormatSymbols ());
  }

  /**
   * Constructs a <code>DecimalFormat</code> using the given pattern
   * and formatting symbols.  This construction method is used to give
   * complete control over the formatting process.  
   *
   * @param pattern the non-localized pattern to use.
   * @param symbols the set of symbols used for parsing and formatting.
   * @throws NullPointerException if any argument is null.
   * @throws IllegalArgumentException if the pattern is invalid.
   */
  public DecimalFormat(String pattern, DecimalFormatSymbols symbols)
  {
    this.symbols = (DecimalFormatSymbols) symbols.clone();
    applyPattern(pattern);
  }

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

  /**
   * Tests this instance for equality with an arbitrary object.  This method
   * returns <code>true</code> if:
   * <ul>
   * <li><code>obj</code> is not <code>null</code>;</li>
   * <li><code>obj</code> is an instance of <code>DecimalFormat</code>;</li>
   * <li>this instance and <code>obj</code> have the same attributes;</li>
   * </ul>
   * 
   * @param obj  the object (<code>null</code> permitted).
   * 
   * @return A boolean.
   */
  public boolean equals(Object obj)
  {
    if (! (obj instanceof DecimalFormat))
      return false;
    DecimalFormat dup = (DecimalFormat) obj;
    return (decimalSeparatorAlwaysShown == dup.decimalSeparatorAlwaysShown 
           && groupingUsed == dup.groupingUsed 
           && groupingSize == dup.groupingSize 
           && multiplier == dup.multiplier
           && useExponentialNotation == dup.useExponentialNotation
           && minExponentDigits == dup.minExponentDigits
           && minimumIntegerDigits == dup.minimumIntegerDigits
           && maximumIntegerDigits == dup.maximumIntegerDigits
           && minimumFractionDigits == dup.minimumFractionDigits
           && maximumFractionDigits == dup.maximumFractionDigits
           && equals(negativePrefix, dup.negativePrefix)
           && equals(negativeSuffix, dup.negativeSuffix)
           && equals(positivePrefix, dup.positivePrefix)
           && equals(positiveSuffix, dup.positiveSuffix)
           && symbols.equals(dup.symbols));
  }

  private void formatInternal (double number, FormatBuffer dest,
			       FieldPosition fieldPos)
  {
    // A very special case.
    if (Double.isNaN(number))
      {
	dest.append(symbols.getNaN());
	if (fieldPos != null && 
	    (fieldPos.getField() == INTEGER_FIELD ||
	     fieldPos.getFieldAttribute() == NumberFormat.Field.INTEGER))
	  {
	    int index = dest.length();
	    fieldPos.setBeginIndex(index - symbols.getNaN().length());
	    fieldPos.setEndIndex(index);
	  }
	return;
      }
		
    boolean is_neg = number < 0;
    if (is_neg)
      {
	if (negativePrefix != null)
	  {
	    dest.append(substituteCurrency(negativePrefix, number),
			negativePrefixRanges, negativePrefixAttrs);
	  }
	else
	  {
	    dest.append(symbols.getMinusSign(), NumberFormat.Field.SIGN);
	    dest.append(substituteCurrency(positivePrefix, number),
			positivePrefixRanges, positivePrefixAttrs);
	  }
	number = - number;
      }
    else
      {
	dest.append(substituteCurrency(positivePrefix, number),
		    positivePrefixRanges, positivePrefixAttrs);
      }
    int integerBeginIndex = dest.length();
    int integerEndIndex = 0;
    int zeroStart = symbols.getZeroDigit() - '0';
		
    if (Double.isInfinite (number))
      {
	dest.append(symbols.getInfinity());
	integerEndIndex = dest.length();
      }
    else
      {
	number *= multiplier;
	
	// Compute exponent.
	long exponent = 0;
	double baseNumber;
	if (useExponentialNotation && number > 0)
	  {
	    exponent = (long) Math.floor (Math.log10(number));
	    exponent = exponent - (exponent % exponentRound);
	    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);
	String intPart = Long.toString((long)Math.floor(baseNumber));
	int count, groupPosition = intPart.length();

	dest.setDefaultAttribute(NumberFormat.Field.INTEGER);

	for (count = 0; count < minimumIntegerDigits-intPart.length(); count++)
	  dest.append(symbols.getZeroDigit());

	for (count = 0;
	     count < maximumIntegerDigits && count < intPart.length();
	     count++)
	  {
	    int dig = intPart.charAt(count);

	    // Append group separator if required.
	    if (groupingUsed && count > 0 && groupingSize != 0 && groupPosition % groupingSize == 0)
	      {
		dest.append(symbols.getGroupingSeparator(), NumberFormat.Field.GROUPING_SEPARATOR);
		dest.setDefaultAttribute(NumberFormat.Field.INTEGER);
	      }
	    dest.append((char) (zeroStart + dig));

	    groupPosition--;
	  }
	dest.setDefaultAttribute(null);

	integerEndIndex = dest.length();
	   
	int decimal_index = integerEndIndex;
	int consecutive_zeros = 0;
	int total_digits = 0;

	int localMaximumFractionDigits = maximumFractionDigits;

	if (useExponentialNotation)
	  localMaximumFractionDigits += minimumIntegerDigits - count;

	// Strip integer part from NUMBER.
	double fracPart = baseNumber - Math.floor(baseNumber);
	
	if ( ((fracPart != 0 || minimumFractionDigits > 0) && localMaximumFractionDigits > 0)
	     || decimalSeparatorAlwaysShown)
	  {
	    dest.append (symbols.getDecimalSeparator(), NumberFormat.Field.DECIMAL_SEPARATOR);
	  }

	int fraction_begin = dest.length();
	dest.setDefaultAttribute(NumberFormat.Field.FRACTION);
	for (count = 0;
	     count < localMaximumFractionDigits
	       && (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.cutTail(extra_zeros);
	    total_digits -= extra_zeros;
	    if (total_digits == 0 && !decimalSeparatorAlwaysShown)
	      dest.cutTail(1);
	  }

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

	// Finally, print the exponent.
	if (useExponentialNotation)
	  {
	    dest.append(symbols.getExponential(), NumberFormat.Field.EXPONENT_SYMBOL);	    
	    if (exponent < 0)
	      {
		dest.append (symbols.getMinusSign (), NumberFormat.Field.EXPONENT_SIGN);
		exponent = - exponent;
	      }
	    index = dest.length();
	    dest.setDefaultAttribute(NumberFormat.Field.EXPONENT);
	    String exponentString = Long.toString ((long) exponent);

	    for (count = 0; count < minExponentDigits-exponentString.length();
		 count++)
	      dest.append((char) symbols.getZeroDigit());

	    for (count = 0;
		 count < exponentString.length();
		 ++count)
	      {
		int dig = exponentString.charAt(count);
		dest.append((char) (zeroStart + dig));
	      }
	  }
      }

    if (fieldPos != null && 
	(fieldPos.getField() == INTEGER_FIELD ||
	 fieldPos.getFieldAttribute() == NumberFormat.Field.INTEGER))
      {
	fieldPos.setBeginIndex(integerBeginIndex);
	fieldPos.setEndIndex(integerEndIndex);
      }
		
    if (is_neg && negativeSuffix != null)
      {
	dest.append(substituteCurrency(negativeSuffix, number),
		    negativeSuffixRanges, negativeSuffixAttrs);
      }
    else
      {
	dest.append(substituteCurrency(positiveSuffix, number),
		    positiveSuffixRanges, positiveSuffixAttrs);
      }
  }

  public StringBuffer format (double number, StringBuffer dest,
			      FieldPosition fieldPos)
  {
    formatInternal (number, new StringFormatBuffer(dest), fieldPos);
    return dest;
  }

  public AttributedCharacterIterator formatToCharacterIterator (Object value)
  {
    AttributedFormatBuffer sbuf = new AttributedFormatBuffer();

    if (value instanceof Number)
      formatInternal(((Number) value).doubleValue(), sbuf, null);
    else
      throw new IllegalArgumentException 
	("Cannot format given Object as a Number");
    
    sbuf.sync();
    return new FormatCharacterIterator(sbuf.getBuffer().toString(), 
				       sbuf.getRanges(), 
				       sbuf.getAttributes());
  }

  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(substituteCurrency(negativePrefix, number));
	else
	  {
	    dest.append(symbols.getMinusSign());
	    dest.append(substituteCurrency(positivePrefix, number));
	  }
	number = - number;
      }
    else
      dest.append(substituteCurrency(positivePrefix, number));

    int integerBeginIndex = dest.length();
    int index = dest.length();
    int count = 0;

    /* Handle percentages, etc. */
    number *= multiplier;
    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)
		? substituteCurrency(negativeSuffix, number)
		: substituteCurrency(positiveSuffix, number));
    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();
  }

  /**
   * Returns a copy of the symbols used by this instance.
   * 
   * @return A copy of the symbols.
   */
  public DecimalFormatSymbols getDecimalFormatSymbols()
  {
    return (DecimalFormatSymbols) symbols.clone();
  }

  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;
  }

  /**
   * Returns a hash code for this object.
   *
   * @return A hash code.
   */
  public int hashCode()
  {
    return toPattern().hashCode();
  }

  public boolean isDecimalSeparatorAlwaysShown ()
  {
    return decimalSeparatorAlwaysShown;
  }

  public Number parse (String str, ParsePosition pos)
  {
    /*
     * Our strategy is simple: copy the text into separate buffers: one for the int part,
     * one for the fraction part and for the exponential part.
     * We translate or omit locale-specific information.  
     * If exponential is sufficiently big we merge the fraction and int part and
     * remove the '.' and then we use Long to convert the number. In the other
     * case, we use Double to convert the full number.
     */

    boolean is_neg = false;
    int index = pos.getIndex();
    StringBuffer int_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 multiplier?

    StringBuffer buf = int_buf;
    StringBuffer frac_buf = null;
    StringBuffer exp_buf = null;
    int start_index = index;
    int max = str.length();
    int exp_index = -1;
    int last = index + maximumIntegerDigits; 

    if (maximumFractionDigits > 0)
      last += maximumFractionDigits + 1;
    
    if (useExponentialNotation)
      last += minExponentDigits + 1;

    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+1;
	  }
	else if (c >= zero && c <= zero + 9)
	  {
	    buf.append((char) (c - zero + '0'));
	  }
	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 = frac_buf = new StringBuffer();
	    frac_buf.append('.');
	    int_part = false;
	  }
	else if (c == symbols.getExponential())
	  {
	    buf = exp_buf = new StringBuffer();
	    int_part = false;
	    exp_part = true;
	    exp_index = index+1;
	  }
	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;
      }
    else if (! got_pos_suf)
      {
       pos.setErrorIndex(index);
       return null;
      }

    String suffix = is_neg ? ns : positiveSuffix;
    long parsedMultiplier = 1;
    boolean use_long;

    if (is_neg)
      int_buf.insert(0, '-');

    // Now handle the exponential part if there is one.
    if (exp_buf != null)
      {
	int exponent_value;

	try
	  {
	    exponent_value = Integer.parseInt(exp_buf.toString());
	  }
	catch (NumberFormatException x1)
	  {
	    pos.setErrorIndex(exp_index);
	    return null;
	  }

	if (frac_buf == null)
	  {
	    // We only have to add some zeros to the int part.
	    // Build a multiplier.
	    for (int i = 0; i < exponent_value; i++)
	      int_buf.append('0');
	    
	    use_long = true;
	  }
	else
	  {
	    boolean long_sufficient;

	    if (exponent_value < frac_buf.length()-1)
	      {
		int lastNonNull = -1;
		/* We have to check the fraction buffer: it may only be full of '0'
		 * or be sufficiently filled with it to convert the number into Long.
		 */
		for (int i = 1; i < frac_buf.length(); i++)
		  if (frac_buf.charAt(i) != '0')
		    lastNonNull = i;

		long_sufficient = (lastNonNull < 0 || lastNonNull <= exponent_value);
	      }
	    else
	      long_sufficient = true;
	    
	    if (long_sufficient)
	      {
		for (int i = 1; i < frac_buf.length() && i < exponent_value; i++)
		  int_buf.append(frac_buf.charAt(i));
		for (int i = frac_buf.length()-1; i < exponent_value; i++)
		  int_buf.append('0');
		use_long = true;
	      }
	    else
	      {
		/*
		 * A long type is not sufficient, we build the full buffer to
		 * be parsed by Double.
		 */
		int_buf.append(frac_buf);
		int_buf.append('E');
		int_buf.append(exp_buf);
		use_long = false;
	      }
	  }
      }
    else
      {
	if (frac_buf != null)
	  {
	    /* Check whether the fraction buffer contains only '0' */
	    int i;
	    for (i = 1; i < frac_buf.length(); i++)
	      if (frac_buf.charAt(i) != '0')
		break;
	   
	    if (i != frac_buf.length())
	      {
		use_long = false;
		int_buf.append(frac_buf);
	      }
	    else
	      use_long = true;
	  }
	else
	  use_long = true;
      }

    String t = int_buf.toString();
    Number result = null;
    if (use_long)
      {
	try
	  {
	    result = new Long (t);
	  }
	catch (NumberFormatException x1)
	  {
	  }
      }
    else
      {
	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);
  }

  /**
   * Sets the symbols used by this instance.  This method makes a copy of 
   * the supplied symbols.
   * 
   * @param newSymbols  the symbols (<code>null</code> not permitted).
   */
  public void setDecimalFormatSymbols(DecimalFormatSymbols newSymbols)
  {
    symbols = (DecimalFormatSymbols) newSymbols.clone();
  }

  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 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 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: groupingSize);
    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);
  }

  private static final int MAXIMUM_INTEGER_DIGITS = 309; 

  // These names are fixed by the serialization spec.
  private boolean decimalSeparatorAlwaysShown;
  private byte groupingSize;
  private byte minExponentDigits;
  private int exponentRound;
  private int multiplier;
  private String negativePrefix;
  private String negativeSuffix;
  private String positivePrefix;
  private String positiveSuffix;
  private int[] negativePrefixRanges, positivePrefixRanges;
  private HashMap[] negativePrefixAttrs, positivePrefixAttrs;
  private int[] negativeSuffixRanges, positiveSuffixRanges;
  private HashMap[] negativeSuffixAttrs, positiveSuffixAttrs;
  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);

  /**
   * <p>
   * Substitutes the currency symbol into the given string,
   * based on the value used.  Currency symbols can either
   * be a simple series of characters (e.g. '$'), which are
   * simply used as is, or they can be of a more complex
   * form:
   * </p>
   * <p>
   * (lower bound)|(mid value)|(upper bound)
   * </p>
   * <p>
   * where each bound has the syntax '(value)(# or <)(symbol)',
   * to indicate the bounding value and the symbol used.
   * </p>
   * <p>
   * The currency symbol replaces the currency specifier, '\u00a4',
   * an unlocalised character, which thus is used as such in all formats.
   * If this symbol occurs twice, the international currency code is used
   * instead.
   * </p>
   *
   * @param string The string containing the currency specifier, '\u00a4'.
   * @param number the number being formatted.
   * @return a string formatted for the correct currency.
   */
  private String substituteCurrency(String string, double number)
  {
    int index;
    int length;
    char currentChar;
    StringBuffer buf;
    
    index = 0;
    length = string.length();
    buf = new StringBuffer();
    
    while (index < length)
      {
	currentChar = string.charAt(index);
	if (string.charAt(index) == '\u00a4')
	  {
	    if ((index + 1) < length && string.charAt(index + 1) == '\u00a4')
	      {
		buf.append(symbols.getInternationalCurrencySymbol());
		index += 2;
	      }
	    else
	      {
		String symbol;
		
		symbol = symbols.getCurrencySymbol();
		if (symbol.startsWith("="))
		  {
		    String[] bounds;
		    int[] boundValues;
		    String[] boundSymbols;
		    
		    bounds = symbol.substring(1).split("\\|");
		    boundValues = new int[3];
		    boundSymbols = new String[3];
		    for (int a = 0; a < 3; ++a)
		      {
			String[] bound;
			
			bound = bounds[a].split("[#<]");
			boundValues[a] = Integer.parseInt(bound[0]);
			boundSymbols[a] = bound[1];
		      }
		    if (number <= boundValues[0])
		      {
			buf.append(boundSymbols[0]);
		      }
		    else if (number >= boundValues[2])
		      {
			buf.append(boundSymbols[2]);
		      }
		    else 
		      {
			buf.append(boundSymbols[1]);
		      }
		    ++index;
		  }
		else
		  {
		    buf.append(symbol);
		    ++index;
		  }
	      }
	  }
	else
	  {
	    buf.append(string.charAt(index));
	    ++index;
	  }
      }
    return buf.toString();
  }
  
}
