/* ChoiceFormat.java -- Format over a range of numbers
   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2012
   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<String> stringVec = new Vector<String> ();
    Vector<Double> limitVec = new Vector<Double> ();
    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 = 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;
}
