/* 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., 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.lang.CPStringBuilder;

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 newPattern 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 ();
    final CPStringBuilder buf = new CPStringBuilder ();

    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 = Double.valueOf (newPattern.substring(dstart, index));

        if (newPattern.charAt(index) == '<')
          d = Double.valueOf (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 newPattern 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 num The number used for determine (based on the range
   *               terminators) which format string to append.
   * @param appendBuf The <code>StringBuffer</code> to append the format string
   *                  to.
   * @param pos 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 num The number used for determine (based on the range
   *               terminators) which format string to append.
   * @param appendBuf The <code>StringBuffer</code> to append the format string to.
   * @param pos 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 next <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 Double.valueOf (choiceLimits[i]);
          }
      }
    pos.setErrorIndex(index);
    return Double.valueOf (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 (CPStringBuilder 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 ()
  {
    CPStringBuilder result = new CPStringBuilder ();
    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;
}
