/* ChoiceFormat.java -- Format over a range of numbers
   Copyright (C) 1998, 1999, 2000, 2001, 2002, 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., 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.Vector;

/**
 * This class allows a format to be specified based on a range of numbers.
 * To use this class, first specify two lists of formats and range terminators.
 * These lists must be arrays of equal length.  The format of index 
 * <code>i</code> will be selected for value <code>X</code> if 
 * <code>terminator[i] &lt;= X &lt; limit[i + 1]</code>.  If the value X is not
 * included in any range, then either the first or last format will be 
 * used depending on whether the value X falls outside the range.
 * <p>
 * This sounds complicated, but that is because I did a poor job of
 * explaining it.  Consider the following example:
 * <p>
 *
<pre>terminators = { 1, ChoiceFormat.nextDouble(1) }
formats = { "file", "files" }</pre>
 *
 * <p>
 * In this case if the actual number tested is one or less, then the word
 * "file" is used as the format value.  If the number tested is greater than
 * one, then "files" is used.  This allows plurals to be handled
 * gracefully.  Note the use of the method <code>nextDouble</code>.  This
 * method selects the next highest double number than its argument.  This
 * effectively makes any double greater than 1.0 cause the "files" string
 * to be selected.  (Note that all terminator values are specified as
 * doubles.
 * <p>
 * Note that in order for this class to work properly, the range terminator
 * array must be sorted in ascending order and the format string array
 * must be the same length as the terminator array.
 *
 * @author Tom Tromey (tromey@cygnus.com)
 * @author Aaron M. Renn (arenn@urbanophile.com)
 * @date March 9, 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.1.
 */
public class ChoiceFormat extends NumberFormat
{
  /**
   * This method sets new range terminators and format strings for this
   * object based on the specified pattern. This pattern is of the form 
   * "term#string|term#string...".  For example "1#Sunday|2#Monday|#Tuesday".
   *
   * @param pattern The pattern of terminators and format strings.
   *
   * @exception IllegalArgumentException If the pattern is not valid
   */
  public void applyPattern (String newPattern)
  {
    // Note: we assume the same kind of quoting rules apply here.
    // This isn't explicitly documented.  But for instance we accept
    // '#' as a literal hash in a format string.
    int index = 0, max = newPattern.length();
    Vector stringVec = new Vector ();
    Vector limitVec = new Vector ();
    StringBuffer buf = new StringBuffer ();
    
    while (true)
      {
	// Find end of double.
	int dstart = index;
	while (index < max)
	  {
	    char c = newPattern.charAt(index);
	    if (c == '#' || c == '\u2064' || c == '<')
	      break;
	    ++index;
	  }
	
	if (index == max)
	  throw new IllegalArgumentException ("unexpected end of text");
	Double d = new Double (newPattern.substring(dstart, index));

	if (newPattern.charAt(index) == '<')
	  d = new Double (nextDouble (d.doubleValue()));

	limitVec.addElement(d);

	// Scan text.
	++index;
	buf.setLength(0);
	while (index < max)
	  {
	    char c = newPattern.charAt(index);
	    if (c == '\'' && index < max + 1
		&& newPattern.charAt(index + 1) == '\'')
	      {
		buf.append(c);
		++index;
	      }
	    else if (c == '\'' && index < max + 2)
	      {
		buf.append(newPattern.charAt(index + 1));
		index += 2;
	      }
	    else if (c == '|')
	      break;
	    else
	      buf.append(c);
	    ++index;
	  }

	stringVec.addElement(buf.toString());
	if (index == max)
	  break;
	++index;
      }

    choiceFormats = new String[stringVec.size()];
    stringVec.copyInto(choiceFormats);

    choiceLimits = new double[limitVec.size()];
    for (int i = 0; i < choiceLimits.length; ++i)
      {
	Double d = (Double) limitVec.elementAt(i);
	choiceLimits[i] = d.doubleValue();
      }
  }

  /**
   * This method initializes a new instance of <code>ChoiceFormat</code> that
   * generates its range terminator and format string arrays from the
   * specified pattern.  This pattern is of the form 
   * "term#string|term#string...".  For example "1#Sunday|2#Monday|#Tuesday".
   * This is the same pattern type used by the <code>applyPattern</code>
   * method.
   *
   * @param pattern The pattern of terminators and format strings.
   *
   * @exception IllegalArgumentException If the pattern is not valid
   */
  public ChoiceFormat (String newPattern)
  {
    super ();
    applyPattern (newPattern);
  }

  /**
   * This method initializes a new instance of <code>ChoiceFormat</code> that
   * will use the specified range terminators and format strings.
   *
   * @param choiceLimits The array of range terminators
   * @param choiceFormats The array of format strings
   */
  public ChoiceFormat (double[] choiceLimits, String[] choiceFormats)
  {
    super ();
    setChoices (choiceLimits, choiceFormats);
  }

  /**
   * This method tests this object for equality with the specified 
   * object.  This will be true if and only if:
   * <ul>
   * <li>The specified object is not <code>null</code>.</li>
   * <li>The specified object is an instance of <code>ChoiceFormat</code>.</li>
   * <li>The termination ranges and format strings are identical to
   *     this object's. </li>
   * </ul>
   *
   * @param obj The object to test for equality against.
   *
   * @return <code>true</code> if the specified object is equal to
   * this one, <code>false</code> otherwise. 
   */
  public boolean equals (Object obj)
  {
    if (! (obj instanceof ChoiceFormat))
      return false;
    ChoiceFormat cf = (ChoiceFormat) obj;
    if (choiceLimits.length != cf.choiceLimits.length)
      return false;
    for (int i = choiceLimits.length - 1; i >= 0; --i)
      {
	if (choiceLimits[i] != cf.choiceLimits[i]
	    || !choiceFormats[i].equals(cf.choiceFormats[i]))
	  return false;
      }
    return true;
  }

  /**
   * This method appends the appropriate format string to the specified
   * <code>StringBuffer</code> based on the supplied <code>long</code>
   * argument.
   *
   * @param number The number used for determine (based on the range
   *               terminators) which format string to append. 
   * @param sb The <code>StringBuffer</code> to append the format string to.
   * @param status Unused.
   *
   * @return The <code>StringBuffer</code> with the format string appended.
   */
  public StringBuffer format (long num, StringBuffer appendBuf,
			      FieldPosition pos)
  {
    return format ((double) num, appendBuf, pos);
  }

  /**
   * This method appends the appropriate format string to the specified
   * <code>StringBuffer</code> based on the supplied <code>double</code>
   * argument.
   *
   * @param number The number used for determine (based on the range
   *               terminators) which format string to append. 
   * @param sb The <code>StringBuffer</code> to append the format string to.
   * @param status Unused.
   *
   * @return The <code>StringBuffer</code> with the format string appended.
   */
  public StringBuffer format (double num, StringBuffer appendBuf,
			      FieldPosition pos)
  {
    if (choiceLimits.length == 0)
      return appendBuf;

    int index = 0;
    if (! Double.isNaN(num) && num >= choiceLimits[0])
      {
	for (; index < choiceLimits.length - 1; ++index)
	  {
	    if (choiceLimits[index] <= num && num < choiceLimits[index + 1])
	      break;
	  }
      }

    return appendBuf.append(choiceFormats[index]);
  }

  /**
   * This method returns the list of format strings in use.
   *
   * @return The list of format objects.
   */
  public Object[] getFormats ()
  {
    return (Object[]) choiceFormats.clone();
  }

  /**
   * This method returns the list of range terminators in use.
   *
   * @return The list of range terminators.
   */
  public double[] getLimits ()
  {
    return (double[]) choiceLimits.clone();
  }

  /**
   * This method returns a hash value for this object
   * 
   * @return A hash value for this object.
   */
  public int hashCode ()
  {
    int hash = 0;
    for (int i = 0; i < choiceLimits.length; ++i)
      {
	long v = Double.doubleToLongBits(choiceLimits[i]);
	hash ^= (v ^ (v >>> 32));
	hash ^= choiceFormats[i].hashCode();
      }
    return hash;
  }

  /**
   * This method returns the lowest possible double greater than the 
   * specified double.  If the specified double value is equal to
   * <code>Double.NaN</code> then that is the value returned.
   *
   * @param d The specified double
   *
   * @return The lowest double value greater than the specified double.
   */
  public static final double nextDouble (double d)
  {
    return nextDouble (d, true);
  }

  /**
   * This method returns a double that is either the next highest double
   * or next lowest double compared to the specified double depending on the
   * value of the passed boolean parameter.  If the boolean parameter is
   * <code>true</code>, then the lowest possible double greater than the 
   * specified double will be returned.  Otherwise the highest possible
   * double less than the specified double will be returned.
   *
   * @param d The specified double
   * @param positive <code>true</code> to return the next highest
   *                 double, <code>false</code> otherwise. 
   *
   * @return The next highest or lowest double value.
   */
  public static double nextDouble (double d, boolean next)
  {
    if (Double.isInfinite(d) || Double.isNaN(d))
      return d;

    long bits = Double.doubleToLongBits(d);

    long mantMask = (1L << mantissaBits) - 1;
    long mantissa = bits & mantMask;

    long expMask = (1L << exponentBits) - 1;
    long exponent = (bits >>> mantissaBits) & expMask;

    if (next ^ (bits < 0)) // Increment magnitude
      {
	if (mantissa == (1L << mantissaBits) - 1)
	  {
	    mantissa = 0L;
	    exponent++;
	     
	    // Check for absolute overflow.
	    if (exponent >= (1L << mantissaBits))
	      return (bits > 0) ? Double.POSITIVE_INFINITY 
		: Double.NEGATIVE_INFINITY;		      
	  }
	else
	  mantissa++;
      }
    else // Decrement magnitude
      {
	if (exponent == 0L && mantissa == 0L)
	  {
	    // The only case where there is a change of sign
	    return next ? Double.MIN_VALUE : -Double.MIN_VALUE;
	  }
	else
	  {
	    if (mantissa == 0L)
	      {
		mantissa = (1L << mantissaBits) - 1;
		exponent--;
	      }
	    else
	      mantissa--;
	  }
      }

    long result = bits < 0 ? 1 : 0;
    result = (result << exponentBits) | exponent;
    result = (result << mantissaBits) | mantissa;
    return Double.longBitsToDouble(result);
  }

  /**
   * I'm not sure what this method is really supposed to do, as it is
   * not documented.
   */
  public Number parse (String sourceStr, ParsePosition pos)
  {
    int index = pos.getIndex();
    for (int i = 0; i < choiceLimits.length; ++i)
      {
	if (sourceStr.startsWith(choiceFormats[i], index))
	  {
	    pos.setIndex(index + choiceFormats[i].length());
	    return new Double (choiceLimits[i]);
	  }
      }
    pos.setErrorIndex(index);
    return new Double (Double.NaN);
  }

  /**
   * This method returns the highest possible double less than the 
   * specified double.  If the specified double value is equal to
   * <code>Double.NaN</code> then that is the value returned.
   *
   * @param d The specified double
   *
   * @return The highest double value less than the specified double.
   */
  public static final double previousDouble (double d)
  {
    return nextDouble (d, false);
  }

  /**
   * This method sets new range terminators and format strings for this
   * object.
   *
   * @param choiceLimits The new range terminators
   * @param choiceFormats The new choice formats
   */
  public void setChoices (double[] choiceLimits, String[] choiceFormats)
  {
    if (choiceLimits == null || choiceFormats == null)
      throw new NullPointerException ();
    if (choiceLimits.length != choiceFormats.length)
      throw new IllegalArgumentException ();
    this.choiceFormats = (String[]) choiceFormats.clone();
    this.choiceLimits = (double[]) choiceLimits.clone();
  }

  private void quoteString (StringBuffer dest, String text)
  {
    int max = text.length();
    for (int i = 0; i < max; ++i)
      {
	char c = text.charAt(i);
	if (c == '\'')
	  {
	    dest.append(c);
	    dest.append(c);
	  }
	else if (c == '#' || c == '|' || c == '\u2064' || c == '<')
	  {
	    dest.append('\'');
	    dest.append(c);
	    dest.append('\'');
	  }
	else
	  dest.append(c);
      }
  }

  /**
   * This method returns the range terminator list and format string list
   * as a <code>String</code> suitable for using with the 
   * <code>applyPattern</code> method.
   *
   * @return A pattern string for this object
   */
  public String toPattern ()
  {
    StringBuffer result = new StringBuffer ();
    for (int i = 0; i < choiceLimits.length; ++i)
      {
	result.append(choiceLimits[i]);
	result.append('#');
	quoteString (result, choiceFormats[i]);
      }
    return result.toString();
  }

  /**
   * This is the list of format strings.  Note that this variable is
   * specified by the serialization spec of this class.
   */
  private String[] choiceFormats;

  /**
   * This is the list of range terminator values.  Note that this variable is
   * specified by the serialization spec of this class.
   */
  private double[] choiceLimits;

  // Number of mantissa bits in double.
  private static final int mantissaBits = 52;
  // Number of exponent bits in a double.
  private static final int exponentBits = 11;

  private static final long serialVersionUID = 1795184449645032964L;
}
