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

import java.io.InvalidObjectException;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Vector;

public class MessageFormat extends Format
{
  /**
   * @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.
   */
  private static 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;
	  boolean styleIsPattern = false;
	  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;
	  else
	    styleIsPattern = true;

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

	  if (styleIsPattern)
	    {
	      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);
        }
    }
  }

  private static final long serialVersionUID = 6479157306784022952L;

  public static class Field extends Format.Field
  {
    static final long serialVersionUID = 7899943957617360810L;

    /**
     * This is the attribute set for all characters produced
     * by MessageFormat during a formatting.
     */
    public static final MessageFormat.Field ARGUMENT = new MessageFormat.Field("argument");

    // For deserialization
    private Field()
    {
      super("");
    }
    
    protected Field(String s)
    {
      super(s);
    }

    /**
     * invoked to resolve the true static constant by
     * comparing the deserialized object to know name.
     *
     * @return object constant
     */
    protected Object readResolve() throws InvalidObjectException
    {
      if (getName().equals(ARGUMENT.getName()))
	return ARGUMENT;

      throw new InvalidObjectException("no such MessageFormat field called " + getName());
    }

  }

  // 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 int scanString(String pat, int index, StringBuffer buffer)
  {
    int max = pat.length();
    buffer.setLength(0);
    boolean quoted = false;
    for (; index < max; ++index)
      {
	char c = pat.charAt(index);
	if (quoted)
	  {
	    // In a quoted context, a single quote ends the quoting.
	    if (c == '\'')
	      quoted = false;
	    else
	      buffer.append(c);
	  }
	// Check for '', which is a single quote.
	else if (c == '\'' && index + 1 < max && pat.charAt(index + 1) == '\'')
	  {
	    buffer.append(c);
	    ++index;
	  }
	else if (c == '\'')
	  {
	    // Start quoting.
	    quoted = true;
	  }
	else if (c == '{')
	  break;
	else
	  buffer.append(c);
      }
    // Note that we explicitly allow an unterminated quote.  This is
    // done for compatibility.
    return index;
  }

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

    for (; index < max; ++index)
      {
	char c = pat.charAt(index);
	// First see if we should turn off quoting.
	if (quoted)
	  {
	    if (c == '\'')
	      quoted = false;
	    // In both cases we fall through to inserting the
	    // character here.
	  }
	// See if we have just a plain quote to insert.
	else if (c == '\'' && index + 1 < max
		 && pat.charAt(index + 1) == '\'')
	  {
	    buffer.append(c);
	    ++index;
	  }
	// See if quoting should turn on.
	else if (c == '\'')
	  quoted = true;
	else if (c == '{')
	  ++brace_depth;
	else if (c == '}')
	  {
	    if (--brace_depth == 0)
	      break;
	  }
	// Check for TERM after braces, because TERM might be `}'.
	else if (c == term)
	  break;
	// All characters, including opening and closing quotes, are
	// inserted here.
	buffer.append(c);
      }
    return index;
  }

  // This is used to parse a format element and whatever non-format
  // text might trail it.
  private static 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)
      {
	IllegalArgumentException iae = new IllegalArgumentException(pat);
	iae.initCause(nfx);
	throw iae;
      }

    // 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("Missing '}' at end of message format");
    ++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 AttributedCharacterIterator formatToCharacterIterator (Object arguments)
  {
    Object[] arguments_array = (Object[])arguments;
    FormatCharacterIterator iterator = new FormatCharacterIterator();
    
    formatInternal(arguments_array, new StringBuffer(), null, iterator);
  
    return iterator;
  }

  /**
   * 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.formatInternal(arguments, sb, fp, null).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 fp)
  {
    return formatInternal(arguments, appendBuf, fp, null);
  }

  private StringBuffer formatInternal (Object arguments[],
                                       StringBuffer appendBuf,
				       FieldPosition fp,
				       FormatCharacterIterator output_iterator)
  {
    appendBuf.append(leader);
    if (output_iterator != null)
      output_iterator.append(leader);

    for (int i = 0; i < elements.length; ++i)
      {
	Object thisArg = null;
	boolean unavailable = false;
	if (arguments == null || elements[i].argNumber >= arguments.length)
	  unavailable = true;
	else
	  thisArg = arguments[elements[i].argNumber];

	AttributedCharacterIterator iterator = null;

	Format formatter = null;

	if (fp != null && i == fp.getField() && fp.getFieldAttribute() == Field.ARGUMENT)
	  fp.setBeginIndex(appendBuf.length());

	if (unavailable)
	  appendBuf.append("{" + elements[i].argNumber + "}");
	else
	  {
	    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("Wrong format class");
	    
	        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 (fp != null && fp.getField() == i && fp.getFieldAttribute() == Field.ARGUMENT)
	  fp.setEndIndex(appendBuf.length());

	if (formatter != null)
	  {
	    // Special-case ChoiceFormat.
	    if (formatter instanceof ChoiceFormat)
	      {
		StringBuffer buf = new StringBuffer ();
		formatter.format(thisArg, buf, fp);
		MessageFormat mf = new MessageFormat ();
		mf.setLocale(locale);
		mf.applyPattern(buf.toString());
		mf.format(arguments, appendBuf, fp);
	      }
	    else
	      {
		if (output_iterator != null)
		  iterator = formatter.formatToCharacterIterator(thisArg);
		else
		  formatter.format(thisArg, appendBuf, fp);
	      }

	    elements[i].format = formatter;
	  }

	if (output_iterator != null)
	  {
	    HashMap hash_argument = new HashMap();
	    int position = output_iterator.getEndIndex();
	    
	    hash_argument.put (MessageFormat.Field.ARGUMENT,
			       new Integer(elements[i].argNumber));

	    
	    if (iterator != null)
	      {
		output_iterator.append(iterator);
		output_iterator.addAttributes(hash_argument, position, 
					      output_iterator.getEndIndex());
	      }	
	    else
	      output_iterator.append(thisArg.toString(), hash_argument);
	    
	    output_iterator.append(elements[i].trailer);
	  }
	
	appendBuf.append(elements[i].trailer);
      }
    
    return appendBuf;
  }

  /**
   * Returns the pattern with the formatted objects.  The first argument
   * must be a array of Objects.
   * This is equivalent to format((Object[]) objectArray, appendBuf, fpos)
   *
   * @param objectArray The object array to be formatted.
   * @param appendBuf The StringBuffer where the text is appened.
   * @param fpos A FieldPosition object (it is ignored).
   */
  public final StringBuffer format (Object objectArray, StringBuffer appendBuf,
				    FieldPosition fpos)
  {
    return format ((Object[])objectArray, appendBuf, fpos);
  }

  /**
   * 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 pattern The Pattern
   */
  public MessageFormat(String pattern)
  {
    this(pattern, Locale.getDefault());
  }

  /**
   * Creates a new MessageFormat object with
   * the specified pattern
   *
   * @param pattern The Pattern
   * @param locale The Locale to use
   *
   * @since 1.4
   */
  public MessageFormat(String pattern, Locale locale)
  {
    this.locale = locale;
    applyPattern (pattern);
  }

  /**
   * Parse a string <code>sourceStr</code> against the pattern specified
   * to the MessageFormat constructor.
   *
   * @param sourceStr the string to be parsed.
   * @param pos the current parse position (and eventually the error position).
   * @return the array of parsed objects sorted according to their argument number
   * in the 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("Not enough format objects");

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

  /**
   * Return the formatters used sorted by argument index. It uses the
   * internal table to fill in this array: if a format has been
   * set using <code>setFormat</code> or <code>setFormatByArgumentIndex</code>
   * then it returns it at the right index. If not it uses the detected
   * formatters during a <code>format</code> call. If nothing is known
   * about that argument index it just puts null at that position.
   * To get useful informations you may have to call <code>format</code>
   * at least once.
   *
   * @return an array of formatters sorted by argument index.
   */
  public Format[] getFormatsByArgumentIndex()
  {
    int argNumMax = 0;
    // First, find the greatest argument number.
    for (int i=0;i<elements.length;i++)
      if (elements[i].argNumber > argNumMax)
	argNumMax = elements[i].argNumber;

    Format[] formats = new Format[argNumMax];
    for (int i=0;i<elements.length;i++)
      {
	if (elements[i].setFormat != null)
	  formats[elements[i].argNumber] = elements[i].setFormat;
	else if (elements[i].format != null)
	  formats[elements[i].argNumber] = elements[i].format;
      }
    return formats;
  }

  /**
   * Set the format to used using the argument index number.
   *
   * @param argumentIndex the argument index.
   * @param newFormat the format to use for this argument.
   */
  public void setFormatByArgumentIndex(int argumentIndex,
				       Format newFormat)
  {
    for (int i=0;i<elements.length;i++)
      {
	if (elements[i].argNumber == argumentIndex)
	  elements[i].setFormat = newFormat;
      }
  }

  /**
   * Set the format for argument using a specified array of formatters
   * which is sorted according to the argument index. If the number of
   * elements in the array is fewer than the number of arguments only
   * the arguments specified by the array are touched.
   *
   * @param newFormats array containing the new formats to set.
   *
   * @throws NullPointerException if newFormats is null
   */
  public void setFormatsByArgumentIndex(Format[] newFormats)
  {
    for (int i=0;i<newFormats.length;i++)
      {
	// Nothing better than that can exist here.
	setFormatByArgumentIndex(i, newFormats[i]);
      }
  }

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