/* MessageFormat.java - Localized message formatting.
   Copyright (C) 1999, 2001 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.

As a special exception, if you link this library with other files to
produce an executable, this library does not by itself cause the
resulting executable to be covered by the GNU General Public License.
This exception does not however invalidate any other reasons why the
executable file might be covered by the GNU General Public License. */


package java.text;

import java.util.Date;
import java.util.Locale;
import java.util.Vector;

/**
 * @author Tom Tromey <tromey@cygnus.com>
 * @author Jorge Aliss <jaliss@hotmail.com>
 * @date March 3, 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, except serialization.
 *          and parsing.
 */
final class MessageFormatElement
{
  // Argument number.
  int argNumber;
  // Formatter to be used.  This is the format set by setFormat.
  Format setFormat;
  // Formatter to be used based on the type.
  Format format;

  // Argument will be checked to make sure it is an instance of this
  // class.
  Class formatClass;

  // Formatter type.
  String type;
  // Formatter style.
  String style;

  // Text to follow this element.
  String trailer;

  // Recompute the locale-based formatter.
  void setLocale (Locale loc)
  {
    if (type == null)
      ;
    else if (type.equals("number"))
      {
	formatClass = java.lang.Number.class;

	if (style == null)
	  format = NumberFormat.getInstance(loc);
	else if (style.equals("currency"))
	  format = NumberFormat.getCurrencyInstance(loc);
	else if (style.equals("percent"))
	  format = NumberFormat.getPercentInstance(loc);
	else if (style.equals("integer"))
	  {
	    NumberFormat nf = NumberFormat.getNumberInstance(loc);
	    nf.setMaximumFractionDigits(0);
	    nf.setGroupingUsed(false);
	    format = nf;
	  }
	else
	  {
	    format = NumberFormat.getNumberInstance(loc);
	    DecimalFormat df = (DecimalFormat) format;
	    df.applyPattern(style);
	  }
      }
    else if (type.equals("time") || type.equals("date"))
      {
	formatClass = java.util.Date.class;

	int val = DateFormat.DEFAULT;
	if (style == null)
	  ;
	else if (style.equals("short"))
	  val = DateFormat.SHORT;
	else if (style.equals("medium"))
	  val = DateFormat.MEDIUM;
	else if (style.equals("long"))
	  val = DateFormat.LONG;
	else if (style.equals("full"))
	  val = DateFormat.FULL;

	if (type.equals("time"))
	  format = DateFormat.getTimeInstance(val, loc);
	else
	  format = DateFormat.getDateInstance(val, loc);

	if (style != null && val == DateFormat.DEFAULT)
	  {
	    SimpleDateFormat sdf = (SimpleDateFormat) format;
	    sdf.applyPattern(style);
	  }
      }
    else if (type.equals("choice"))
      {
	formatClass = java.lang.Number.class;

	if (style == null)
	  throw new
	    IllegalArgumentException ("style required for choice format");
	format = new ChoiceFormat (style);
      }
  }
}

public class MessageFormat extends Format
{
  // Helper that returns the text up to the next format opener.  The
  // text is put into BUFFER.  Returns index of character after end of
  // string.  Throws IllegalArgumentException on error.
  private static final int scanString (String pat, int index,
				       StringBuffer buffer)
  {
    int max = pat.length();
    buffer.setLength(0);
    for (; index < max; ++index)
      {
	char c = pat.charAt(index);
	if (c == '\'' && index + 2 < max && pat.charAt(index + 2) == '\'')
	  {
	    buffer.append(pat.charAt(index + 1));
	    index += 2;
	  }
	else if (c == '\'' && index + 1 < max
		 && pat.charAt(index + 1) == '\'')
	  {
	    buffer.append(c);
	    ++index;
	  }
	else if (c == '{')
	  break;
	else if (c == '}')
	  throw new IllegalArgumentException ();
	else
	  buffer.append(c);
      }
    return index;
  }

  // This helper retrieves a single part of a format element.  Returns
  // the index of the terminating character.
  private static final int scanFormatElement (String pat, int index,
					      StringBuffer buffer,
					      char term)
  {
    int max = pat.length();
    buffer.setLength(0);
    int brace_depth = 1;

    for (; index < max; ++index)
      {
	char c = pat.charAt(index);
	if (c == '\'' && index + 2 < max && pat.charAt(index + 2) == '\'')
	  {
	    buffer.append(c);
	    buffer.append(pat.charAt(index + 1));
	    buffer.append(c);
	    index += 2;
	  }
	else if (c == '\'' && index + 1 < max
		 && pat.charAt(index + 1) == '\'')
	  {
	    buffer.append(c);
	    ++index;
	  }
	else if (c == '{')
	  {
	    buffer.append(c);
	    ++brace_depth;
	  }
	else if (c == '}')
	  {
	    if (--brace_depth == 0)
	      break;
	    buffer.append(c);
	  }
	// Check for TERM after braces, because TERM might be `}'.
	else if (c == term)
	  break;
	else
	  buffer.append(c);
      }
    return index;
  }

  // This is used to parse a format element and whatever non-format
  // text might trail it.
  private static final int scanFormat (String pat, int index,
				       StringBuffer buffer, Vector elts,
				       Locale locale)
  {
    MessageFormatElement mfe = new MessageFormatElement ();
    elts.addElement(mfe);

    int max = pat.length();

    // Skip the opening `{'.
    ++index;

    // Fetch the argument number.
    index = scanFormatElement (pat, index, buffer, ',');
    try
      {
	mfe.argNumber = Integer.parseInt(buffer.toString());
      }
    catch (NumberFormatException nfx)
      {
	throw new IllegalArgumentException ();
      }

    // Extract the element format.
    if (index < max && pat.charAt(index) == ',')
      {
	index = scanFormatElement (pat, index + 1, buffer, ',');
	mfe.type = buffer.toString();

	// Extract the style.
	if (index < max && pat.charAt(index) == ',')
	  {
	    index = scanFormatElement (pat, index + 1, buffer, '}');
	    mfe.style = buffer.toString ();
	  }
      }

    // Advance past the last terminator.
    if (index >= max || pat.charAt(index) != '}')
      throw new IllegalArgumentException ();
    ++index;

    // Now fetch trailing string.
    index = scanString (pat, index, buffer);
    mfe.trailer = buffer.toString ();

    mfe.setLocale(locale);

    return index;
  }

  /**
   * Applies the specified pattern to this MessageFormat.
   *
   * @param aPattern The Pattern
   */
  public void applyPattern (String newPattern)
  {
    pattern = newPattern;

    StringBuffer tempBuffer = new StringBuffer ();

    int index = scanString (newPattern, 0, tempBuffer);
    leader = tempBuffer.toString();

    Vector elts = new Vector ();
    while (index < newPattern.length())
      index = scanFormat (newPattern, index, tempBuffer, elts, locale);

    elements = new MessageFormatElement[elts.size()];
    elts.copyInto(elements);
  }

  /**
   * Overrides Format.clone()
   */
  public Object clone ()
  {
    MessageFormat c = (MessageFormat) super.clone ();
    c.elements = (MessageFormatElement[]) elements.clone ();
    return c;
  }

  /**
   * Overrides Format.equals(Object obj)
   */
  public boolean equals (Object obj)
  {
    if (! (obj instanceof MessageFormat))
      return false;
    MessageFormat mf = (MessageFormat) obj;
    return (pattern.equals(mf.pattern)
	    && locale.equals(mf.locale));
  }

  /**
   * A convinience method to format patterns.
   *
   * @param aPattern The pattern used when formatting.
   * @param arguments The array containing the objects to be formatted.
   */
  public static String format (String pattern, Object arguments[])
  {
    MessageFormat mf = new MessageFormat (pattern);
    StringBuffer sb = new StringBuffer ();
    FieldPosition fp = new FieldPosition (NumberFormat.INTEGER_FIELD);
    return mf.format(arguments, sb, fp).toString();
  }

  /**
   * Returns the pattern with the formatted objects.
   *
   * @param source The array containing the objects to be formatted.
   * @param result The StringBuffer where the text is appened.
   * @param fp A FieldPosition object (it is ignored).
   */
  public final StringBuffer format (Object arguments[], StringBuffer appendBuf,
				    FieldPosition ignore)
  {
    appendBuf.append(leader);

    for (int i = 0; i < elements.length; ++i)
      {
	if (elements[i].argNumber >= arguments.length)
	  throw new IllegalArgumentException ();
	Object thisArg = arguments[elements[i].argNumber];

	Format formatter = null;
	if (elements[i].setFormat != null)
	  formatter = elements[i].setFormat;
	else if (elements[i].format != null)
	  {
	    if (elements[i].formatClass != null
		&& ! elements[i].formatClass.isInstance(thisArg))
	      throw new IllegalArgumentException ();
	    formatter = elements[i].format;
	  }
	else if (thisArg instanceof Number)
	  formatter = NumberFormat.getInstance(locale);
	else if (thisArg instanceof Date)
	  formatter = DateFormat.getTimeInstance(DateFormat.DEFAULT, locale);
	else
	  appendBuf.append(thisArg);

	if (formatter != null)
	  {
	    // Special-case ChoiceFormat.
	    if (formatter instanceof ChoiceFormat)
	      {
		StringBuffer buf = new StringBuffer ();
		// FIXME: don't actually know what is correct here.
		// Can a sub-format refer to any argument, or just
		// the single argument passed to it?  Must test
		// against JDK.
		formatter.format(thisArg, buf, ignore);
		MessageFormat mf = new MessageFormat ();
		mf.setLocale(locale);
		mf.applyPattern(buf.toString());
		formatter = mf;
	      }
	    formatter.format(thisArg, appendBuf, ignore);
	  }

	appendBuf.append(elements[i].trailer);
      }

    return appendBuf;
  }

  /**
   * Returns the pattern with the formatted objects.
   *
   * @param source The object to be formatted.
   * @param result The StringBuffer where the text is appened.
   * @param fp A FieldPosition object (it is ignored).
   */
  public final StringBuffer format (Object singleArg, StringBuffer appendBuf,
				    FieldPosition ignore)
  {
    Object[] args;

    if (singleArg instanceof Object[])
      {
	// This isn't specified in any manual, but it follows the
	// JDK implementation.
	args = (Object[]) singleArg;
      }
    else
      {
	args = new Object[1];
	args[0] = singleArg;
      }
    return format (args, appendBuf, ignore);
  }

  /**
   * Returns an array with the Formats for
   * the arguments.
   */
  public Format[] getFormats ()
  {
    Format[] f = new Format[elements.length];
    for (int i = elements.length - 1; i >= 0; --i)
      f[i] = elements[i].setFormat;
    return f;
  }

  /**
   * Returns the locale.
   */
  public Locale getLocale ()
  {
    return locale;
  }

  /**
   * Overrides Format.hashCode()
   */
  public int hashCode ()
  {
    // FIXME: not a very good hash.
    return pattern.hashCode() + locale.hashCode();
  }

  private MessageFormat ()
  {
  }

  /**
   * Creates a new MessageFormat object with
   * the specified pattern
   *
   * @param aPattern The Pattern
   */
  public MessageFormat (String pattern)
  {
    locale = Locale.getDefault();
    applyPattern (pattern);
  }

  public Object[] parse (String sourceStr, ParsePosition pos)
  {
    // Check initial text.
    int index = pos.getIndex();
    if (! sourceStr.startsWith(leader, index))
      {
	pos.setErrorIndex(index);
	return null;
      }
    index += leader.length();

    Vector results = new Vector (elements.length, 1);
    // Now check each format.
    for (int i = 0; i < elements.length; ++i)
      {
	Format formatter = null;
	if (elements[i].setFormat != null)
	  formatter = elements[i].setFormat;
	else if (elements[i].format != null)
	  formatter = elements[i].format;

	Object value = null;
	if (formatter instanceof ChoiceFormat)
	  {
	    // We must special-case a ChoiceFormat because it might
	    // have recursive formatting.
	    ChoiceFormat cf = (ChoiceFormat) formatter;
	    String[] formats = (String[]) cf.getFormats();
	    double[] limits = (double[]) cf.getLimits();
	    MessageFormat subfmt = new MessageFormat ();
	    subfmt.setLocale(locale);
	    ParsePosition subpos = new ParsePosition (index);

	    int j;
	    for (j = 0; value == null && j < limits.length; ++j)
	      {
		subfmt.applyPattern(formats[j]);
		subpos.setIndex(index);
		value = subfmt.parse(sourceStr, subpos);
	      }
	    if (value != null)
	      {
		index = subpos.getIndex();
		value = new Double (limits[j]);
	      }
	  }
	else if (formatter != null)
	  {
	    pos.setIndex(index);
	    value = formatter.parseObject(sourceStr, pos);
	    if (value != null)
	      index = pos.getIndex();
	  }
	else
	  {
	    // We have a String format.  This can lose in a number
	    // of ways, but we give it a shot.
	    int next_index = sourceStr.indexOf(elements[i].trailer, index);
	    if (next_index == -1)
	      {
		pos.setErrorIndex(index);
		return null;
	      }
	    value = sourceStr.substring(index, next_index);
	    index = next_index;
	  }

	if (value == null
	    || ! sourceStr.startsWith(elements[i].trailer, index))
	  {
	    pos.setErrorIndex(index);
	    return null;
	  }

	if (elements[i].argNumber >= results.size())
	  results.setSize(elements[i].argNumber + 1);
	results.setElementAt(value, elements[i].argNumber);

	index += elements[i].trailer.length();
      }

    Object[] r = new Object[results.size()];
    results.copyInto(r);
    return r;
  }

  public Object[] parse (String sourceStr) throws ParseException
  {
    ParsePosition pp = new ParsePosition (0);
    Object[] r = parse (sourceStr, pp);
    if (r == null)
      throw new ParseException ("couldn't parse string", pp.getErrorIndex());
    return r;
  }

  public Object parseObject (String sourceStr, ParsePosition pos)
  {
    return parse (sourceStr, pos);
  }

  /**
   * Sets the format for the argument at an specified
   * index.
   *
   * @param index The index.
   * @format The Format object.
   */
  public void setFormat (int variableNum, Format newFormat)
  {
    elements[variableNum].setFormat = newFormat;
  }

  /**
   * Sets the formats for the arguments.
   *
   * @param formats An array of Format objects.
   */
  public void setFormats (Format[] newFormats)
  {
    if (newFormats.length < elements.length)
      throw new IllegalArgumentException ();
    int len = Math.min(newFormats.length, elements.length);
    for (int i = 0; i < len; ++i)
      elements[i].setFormat = newFormats[i];
  }

  /**
   * Sets the locale.
   *
   * @param locale A Locale
   */
  public void setLocale (Locale loc)
  {
    locale = loc;
    if (elements != null)
      {
	for (int i = 0; i < elements.length; ++i)
	  elements[i].setLocale(loc);
      }
  }

  /**
   * Returns the pattern.
   */
  public String toPattern ()
  {
    return pattern;
  }

  // The pattern string.
  private String pattern;
  // The locale.
  private Locale locale;
  // Variables.
  private MessageFormatElement[] elements;
  // Leader text.
  private String leader;
}
