/* 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., 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 gnu.java.text.FormatCharacterIterator;

import java.io.InvalidObjectException;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;

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)
        {
          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"))
		format = NumberFormat.getIntegerInstance(loc);
              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)
                {
                  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
    @SuppressWarnings("unused")
    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, CPStringBuilder 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,
                                       CPStringBuilder 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, CPStringBuilder buffer,
                                List<MessageFormatElement> elts, Locale locale)
  {
    MessageFormatElement mfe = new MessageFormatElement ();
    elts.add(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 newPattern The Pattern
   */
  public void applyPattern (String newPattern)
  {
    pattern = newPattern;

    CPStringBuilder tempBuffer = new CPStringBuilder ();

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

    List<MessageFormatElement> elts = new ArrayList<MessageFormatElement>();
    while (index < newPattern.length())
      index = scanFormat (newPattern, index, tempBuffer, elts, locale);

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

  /**
   * 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 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 pattern 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 arguments The array containing the objects to be formatted.
   * @param appendBuf 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<MessageFormat.Field, Integer> hash_argument =
	      new HashMap<MessageFormat.Field, Integer>();
	    int position = output_iterator.getEndIndex();
	    
	    hash_argument.put (MessageFormat.Field.ARGUMENT,
			       Integer.valueOf(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();

    ArrayList<Object> results = new ArrayList<Object>(elements.length);
    // 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 = 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;
	    if (elements[i].trailer.length() > 0)
	      next_index = sourceStr.indexOf(elements[i].trailer, index);
	    else
	      next_index = sourceStr.length();
	    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())
	  {
	    // Emulate padding behaviour of Vector.setSize() with ArrayList
	    results.ensureCapacity(elements[i].argNumber + 1);
	    for (int a = results.size(); a <= elements[i].argNumber; ++a)
	      results.add(a, null);
	  }
	results.set(elements[i].argNumber, value);

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

    return results.toArray(new Object[results.size()]);
  }

  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 variableNum The index.
   * @param newFormat The Format object.
   */
  public void setFormat (int variableNum, Format newFormat)
  {
    elements[variableNum].setFormat = newFormat;
  }

  /**
   * Sets the formats for the arguments.
   *
   * @param newFormats 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 loc 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;
}
