/*
 *******************************************************************************
 * Copyright (C) 2004-2008, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 */
package com.ibm.icu.text;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.FieldPosition;
import java.text.Format;
import java.text.ParseException;
import java.text.ParsePosition;
import java.util.Locale;

import com.ibm.icu.util.ULocale;

/**
 * <code>MessageFormat</code> provides a means to produce concatenated
 * messages in language-neutral way. Use this to construct messages
 * displayed for end users.
 *
 * <p>
 * <code>MessageFormat</code> takes a set of objects, formats them, then
 * inserts the formatted strings into the pattern at the appropriate places.
 *
 * <p>
 * <strong>Note:</strong>
 * <code>MessageFormat</code> differs from the other <code>Format</code>
 * classes in that you create a <code>MessageFormat</code> object with one
 * of its constructors (not with a <code>getInstance</code> style factory
 * method). The factory methods aren't necessary because <code>MessageFormat</code>
 * itself doesn't implement locale specific behavior. Any locale specific
 * behavior is defined by the pattern that you provide as well as the
 * subformats used for inserted arguments.
 *
 * <h4><a name="patterns">Patterns and Their Interpretation</a></h4>
 *
 * <code>MessageFormat</code> uses patterns of the following form:
 * <blockquote><pre>
 * <i>MessageFormatPattern:</i>
 *         <i>String</i>
 *         <i>MessageFormatPattern</i> <i>FormatElement</i> <i>String</i>
 *
 * <i>FormatElement:</i>
 *         { <i>ArgumentIndex</i> }
 *         { <i>ArgumentIndex</i> , <i>FormatType</i> }
 *         { <i>ArgumentIndex</i> , <i>FormatType</i> , <i>FormatStyle</i> }
 *
 * <i>FormatType: one of </i>
 *         number date time choice
 *
 * <i>FormatStyle:</i>
 *         short
 *         medium
 *         long
 *         full
 *         integer
 *         currency
 *         percent
 *         <i>SubformatPattern</i>
 *
 * <i>String:</i>
 *         <i>StringPart<sub>opt</sub></i>
 *         <i>String</i> <i>StringPart</i>
 *
 * <i>StringPart:</i>
 *         ''
 *         ' <i>QuotedString</i> '
 *         <i>UnquotedString</i>
 *
 * <i>SubformatPattern:</i>
 *         <i>SubformatPatternPart<sub>opt</sub></i>
 *         <i>SubformatPattern</i> <i>SubformatPatternPart</i>
 *
 * <i>SubFormatPatternPart:</i>
 *         ' <i>QuotedPattern</i> '
 *         <i>UnquotedPattern</i>
 * </pre></blockquote>
 *
 * <p>
 * Within a <i>String</i>, <code>"''"</code> represents a single
 * quote. A <i>QuotedString</i> can contain arbitrary characters
 * except single quotes; the surrounding single quotes are removed.
 * An <i>UnquotedString</i> can contain arbitrary characters
 * except single quotes and left curly brackets. Thus, a string that
 * should result in the formatted message "'{0}'" can be written as
 * <code>"'''{'0}''"</code> or <code>"'''{0}'''"</code>.
 * <p>
 * Within a <i>SubformatPattern</i>, different rules apply.
 * A <i>QuotedPattern</i> can contain arbitrary characters
 * except single quotes; but the surrounding single quotes are
 * <strong>not</strong> removed, so they may be interpreted by the
 * subformat. For example, <code>"{1,number,$'#',##}"</code> will
 * produce a number format with the pound-sign quoted, with a result
 * such as: "$#31,45".
 * An <i>UnquotedPattern</i> can contain arbitrary characters
 * except single quotes, but curly braces within it must be balanced.
 * For example, <code>"ab {0} de"</code> and <code>"ab '}' de"</code>
 * are valid subformat patterns, but <code>"ab {0'}' de"</code> and
 * <code>"ab } de"</code> are not.
 * <p>
 * <dl><dt><b>Warning:</b><dd>The rules for using quotes within message
 * format patterns unfortunately have shown to be somewhat confusing.
 * In particular, it isn't always obvious to localizers whether single
 * quotes need to be doubled or not. Make sure to inform localizers about
 * the rules, and tell them (for example, by using comments in resource
 * bundle source files) which strings will be processed by MessageFormat.
 * Note that localizers may need to use single quotes in translated
 * strings where the original version doesn't have them.
 * <br>Note also that the simplest way to avoid the problem is to
 * use the real apostrophe (single quote) character \u2019 (') for
 * human-readable text, and to use the ASCII apostrophe (\u0027 ' )
 * only in program syntax, like quoting in MessageFormat.
 * See the annotations for U+0027 Apostrophe in The Unicode Standard.</p>
 * </dl>
 * <p>
 * The <i>ArgumentIndex</i> value is a non-negative integer written
 * using the digits '0' through '9', and represents an index into the
 * <code>arguments</code> array passed to the <code>format</code> methods
 * or the result array returned by the <code>parse</code> methods.
 * <p>
 * The <i>FormatType</i> and <i>FormatStyle</i> values are used to create
 * a <code>Format</code> instance for the format element. The following
 * table shows how the values map to Format instances. Combinations not
 * shown in the table are illegal. A <i>SubformatPattern</i> must
 * be a valid pattern string for the Format subclass used.
 * <p>
 * <table border=1>
 *    <tr>
 *       <th>Format Type
 *       <th>Format Style
 *       <th>Subformat Created
 *    <tr>
 *       <td colspan=2><i>(none)</i>
 *       <td><code>null</code>
 *    <tr>
 *       <td rowspan=5><code>number</code>
 *       <td><i>(none)</i>
 *       <td><code>NumberFormat.getInstance(getLocale())</code>
 *    <tr>
 *       <td><code>integer</code>
 *       <td><code>NumberFormat.getIntegerInstance(getLocale())</code>
 *    <tr>
 *       <td><code>currency</code>
 *       <td><code>NumberFormat.getCurrencyInstance(getLocale())</code>
 *    <tr>
 *       <td><code>percent</code>
 *       <td><code>NumberFormat.getPercentInstance(getLocale())</code>
 *    <tr>
 *       <td><i>SubformatPattern</i>
 *       <td><code>new DecimalFormat(subformatPattern, new DecimalFormatSymbols(getLocale()))</code>
 *    <tr>
 *       <td rowspan=6><code>date</code>
 *       <td><i>(none)</i>
 *       <td><code>DateFormat.getDateInstance(DateFormat.DEFAULT, getLocale())</code>
 *    <tr>
 *       <td><code>short</code>
 *       <td><code>DateFormat.getDateInstance(DateFormat.SHORT, getLocale())</code>
 *    <tr>
 *       <td><code>medium</code>
 *       <td><code>DateFormat.getDateInstance(DateFormat.DEFAULT, getLocale())</code>
 *    <tr>
 *       <td><code>long</code>
 *       <td><code>DateFormat.getDateInstance(DateFormat.LONG, getLocale())</code>
 *    <tr>
 *       <td><code>full</code>
 *       <td><code>DateFormat.getDateInstance(DateFormat.FULL, getLocale())</code>
 *    <tr>
 *       <td><i>SubformatPattern</i>
 *       <td><code>new SimpleDateFormat(subformatPattern, getLocale())
 *    <tr>
 *       <td rowspan=6><code>time</code>
 *       <td><i>(none)</i>
 *       <td><code>DateFormat.getTimeInstance(DateFormat.DEFAULT, getLocale())</code>
 *    <tr>
 *       <td><code>short</code>
 *       <td><code>DateFormat.getTimeInstance(DateFormat.SHORT, getLocale())</code>
 *    <tr>
 *       <td><code>medium</code>
 *       <td><code>DateFormat.getTimeInstance(DateFormat.DEFAULT, getLocale())</code>
 *    <tr>
 *       <td><code>long</code>
 *       <td><code>DateFormat.getTimeInstance(DateFormat.LONG, getLocale())</code>
 *    <tr>
 *       <td><code>full</code>
 *       <td><code>DateFormat.getTimeInstance(DateFormat.FULL, getLocale())</code>
 *    <tr>
 *       <td><i>SubformatPattern</i>
 *       <td><code>new SimpleDateFormat(subformatPattern, getLocale())
 *    <tr>
 *       <td><code>choice</code>
 *       <td><i>SubformatPattern</i>
 *       <td><code>new ChoiceFormat(subformatPattern)</code>
 * </table>
 * <p>
 *
 * <h4>Usage Information</h4>
 *
 * <p>
 * Here are some examples of usage:
 * <blockquote>
 * <pre>
 * Object[] arguments = {
 *     new Integer(7),
 *     new Date(System.currentTimeMillis()),
 *     "a disturbance in the Force"
 * };
 *
 * String result = MessageFormat.format(
 *     "At {1,time} on {1,date}, there was {2} on planet {0,number,integer}.",
 *     arguments);
 *
 * <em>output</em>: At 12:30 PM on Jul 3, 2053, there was a disturbance
 *           in the Force on planet 7.
 *
 * </pre>
 * </blockquote>
 * Typically, the message format will come from resources, and the
 * arguments will be dynamically set at runtime.
 *
 * <p>
 * Example 2:
 * <blockquote>
 * <pre>
 * Object[] testArgs = {new Long(3), "MyDisk"};
 *
 * MessageFormat form = new MessageFormat(
 *     "The disk \"{1}\" contains {0} file(s).");
 *
 * System.out.println(form.format(testArgs));
 *
 * // output, with different testArgs
 * <em>output</em>: The disk "MyDisk" contains 0 file(s).
 * <em>output</em>: The disk "MyDisk" contains 1 file(s).
 * <em>output</em>: The disk "MyDisk" contains 1,273 file(s).
 * </pre>
 * </blockquote>
 *
 * <p>
 * For more sophisticated patterns, you can use a <code>ChoiceFormat</code> to get
 * output such as:
 * <blockquote>
 * <pre>
 * MessageFormat form = new MessageFormat("The disk \"{1}\" contains {0}.");
 * double[] filelimits = {0,1,2};
 * String[] filepart = {"no files","one file","{0,number} files"};
 * ChoiceFormat fileform = new ChoiceFormat(filelimits, filepart);
 * form.setFormatByArgumentIndex(0, fileform);
 *
 * Object[] testArgs = {new Long(12373), "MyDisk"};
 *
 * System.out.println(form.format(testArgs));
 *
 * // output, with different testArgs
 * output: The disk "MyDisk" contains no files.
 * output: The disk "MyDisk" contains one file.
 * output: The disk "MyDisk" contains 1,273 files.
 * </pre>
 * </blockquote>
 * You can either do this programmatically, as in the above example,
 * or by using a pattern (see
 * {@link ChoiceFormat}
 * for more information) as in:
 * <blockquote>
 * <pre>
 * form.applyPattern(
 *    "There {0,choice,0#are no files|1#is one file|1&lt;are {0,number,integer} files}.");
 * </pre>
 * </blockquote>
 * <p>
 * <strong>Note:</strong> As we see above, the string produced
 * by a <code>ChoiceFormat</code> in <code>MessageFormat</code> is treated specially;
 * occurances of '{' are used to indicated subformats, and cause recursion.
 * If you create both a <code>MessageFormat</code> and <code>ChoiceFormat</code>
 * programmatically (instead of using the string patterns), then be careful not to
 * produce a format that recurses on itself, which will cause an infinite loop.
 * <p>
 * When a single argument is parsed more than once in the string, the last match
 * will be the final result of the parsing.  For example,
 * <pre>
 * MessageFormat mf = new MessageFormat("{0,number,#.##}, {0,number,#.#}");
 * Object[] objs = {new Double(3.1415)};
 * String result = mf.format( objs );
 * // result now equals "3.14, 3.1"
 * objs = null;
 * objs = mf.parse(result, new ParsePosition(0));
 * // objs now equals {new Double(3.1)}
 * </pre>
 * <p>
 * Likewise, parsing with a MessageFormat object using patterns containing
 * multiple occurances of the same argument would return the last match.  For
 * example,
 * <pre>
 * MessageFormat mf = new MessageFormat("{0}, {0}, {0}");
 * String forParsing = "x, y, z";
 * Object[] objs = mf.parse(forParsing, new ParsePosition(0));
 * // result now equals {new String("z")}
 * </pre>
 *
 * <h4><a name="synchronization">Synchronization</a></h4>
 *
 * <p>
 * Message formats are not synchronized.
 * It is recommended to create separate format instances for each thread.
 * If multiple threads access a format concurrently, it must be synchronized
 * externally.
 *
 * @see          java.util.Locale
 * @see          Format
 * @see          NumberFormat
 * @see          DecimalFormat
 * @see          ChoiceFormat
 * @author       Mark Davis
 * @stable ICU 3.0
 */
public class MessageFormat extends Format {
    static final long serialVersionUID = 1L;

    /**
     * @internal
     */
    public final java.text.MessageFormat messageFormat;
        
    /**
     * @internal
     * @param delegate the DateFormat to which to delegate
     */
    public MessageFormat(java.text.MessageFormat delegate) {
        this.messageFormat = delegate;
    }

    /**
     * Constructs a MessageFormat for the default locale and the
     * specified pattern.
     * The constructor first sets the locale, then parses the pattern and
     * creates a list of subformats for the format elements contained in it.
     * Patterns and their interpretation are specified in the
     * <a href="#patterns">class description</a>.
     *
     * @param pattern the pattern for this message format
     * @exception IllegalArgumentException if the pattern is invalid
     * @stable ICU 3.0
     */
    public MessageFormat(String pattern) {
        this(new java.text.MessageFormat(pattern));
    }

    /**
     * Constructs a MessageFormat for the specified locale and
     * pattern.
     * The constructor first sets the locale, then parses the pattern and
     * creates a list of subformats for the format elements contained in it.
     * Patterns and their interpretation are specified in the
     * <a href="#patterns">class description</a>.
     *
     * @param pattern the pattern for this message format
     * @param locale the locale for this message format
     * @exception IllegalArgumentException if the pattern is invalid
     * @stable ICU 3.0
     */
    public MessageFormat(String pattern, Locale locale) {
        // locale is ignored
        this(new java.text.MessageFormat(pattern));
    }

    /**
     * Constructs a MessageFormat for the specified locale and
     * pattern.
     * The constructor first sets the locale, then parses the pattern and
     * creates a list of subformats for the format elements contained in it.
     * Patterns and their interpretation are specified in the
     * <a href="#patterns">class description</a>.
     *
     * @param pattern the pattern for this message format
     * @param locale the locale for this message format
     * @exception IllegalArgumentException if the pattern is invalid
     * @stable ICU 3.2
     */
    public MessageFormat(String pattern, ULocale locale) {
        // locale is ignored
        this(pattern);
    }

    /**
     * Sets the locale to be used when creating or comparing subformats.
     * This affects subsequent calls to the {@link #applyPattern applyPattern}
     * and {@link #toPattern toPattern} methods as well as to the
     * <code>format</code> and
     * {@link #formatToCharacterIterator formatToCharacterIterator} methods.
     *
     * @param locale the locale to be used when creating or comparing subformats
     * @stable ICU 3.0
     */
    public void setLocale(Locale locale) {
        messageFormat.setLocale(locale);
    }

    /**
     * Sets the locale to be used when creating or comparing subformats.
     * This affects subsequent calls to the {@link #applyPattern applyPattern}
     * and {@link #toPattern toPattern} methods as well as to the
     * <code>format</code> and
     * {@link #formatToCharacterIterator formatToCharacterIterator} methods.
     *
     * @param locale the locale to be used when creating or comparing subformats
     * @stable ICU 3.2
     */
    public void setLocale(ULocale locale) {
        messageFormat.setLocale(locale.toLocale());
    }

    /**
     * Gets the locale that's used when creating or comparing subformats.
     *
     * @return the locale used when creating or comparing subformats
     * @stable ICU 3.0
     */
    public Locale getLocale() {
        return messageFormat.getLocale();
    }

    /**
     * Gets the locale that's used when creating or comparing subformats.
     *
     * @return the locale used when creating or comparing subformats
     * @stable ICU 3.2
     */
    public ULocale getULocale() {
        return ULocale.forLocale(messageFormat.getLocale());
    }

    /**
     * Sets the pattern used by this message format.
     * The method parses the pattern and creates a list of subformats
     * for the format elements contained in it.
     * Patterns and their interpretation are specified in the
     * <a href="#patterns">class description</a>.
     * 
     * @param pattern the pattern for this message format
     * @exception IllegalArgumentException if the pattern is invalid
     * @stable ICU 3.0
     */
   public void applyPattern(String pattern) {
       messageFormat.applyPattern(pattern);
   }

   /**
    * Returns a pattern representing the current state of the message format.
    * The string is constructed from internal information and therefore
    * does not necessarily equal the previously applied pattern. 
    *
    * @return a pattern representing the current state of the message format
    * @stable ICU 3.0
    */
   public String toPattern() {
       return messageFormat.toPattern();
   }
 
   /**
    * Sets the formats to use for the values passed into
    * <code>format</code> methods or returned from <code>parse</code>
    * methods. The indices of elements in <code>newFormats</code>
    * correspond to the argument indices used in the previously set
    * pattern string.
    * The order of formats in <code>newFormats</code> thus corresponds to
    * the order of elements in the <code>arguments</code> array passed
    * to the <code>format</code> methods or the result array returned
    * by the <code>parse</code> methods.
    * <p>
    * If an argument index is used for more than one format element
    * in the pattern string, then the corresponding new format is used
    * for all such format elements. If an argument index is not used
    * for any format element in the pattern string, then the
    * corresponding new format is ignored. If fewer formats are provided
    * than needed, then only the formats for argument indices less
    * than <code>newFormats.length</code> are replaced.
    *
    * @param newFormats the new formats to use
    * @exception NullPointerException if <code>newFormats</code> is null
    * @stable ICU 3.0
    * @throws UnsupportedOperationException if the underlying JVM does not
    * support this method.
    */
   public void setFormatsByArgumentIndex(Format[] newFormats) {
	   if (sfsbai == null) {
		   synchronized (missing) {
			   try {
				   Class[] params = { Format[].class };
				   sfsbai = java.text.MessageFormat.class.getMethod("setFormatsByArgumentIndex", params);
			   }
			   catch (NoSuchMethodException e) {
				   sfsbai = missing;
			   }
		   }
	   }
	   if (sfsbai != missing) {
		   try {
			   Format[] unwrapped = new Format[newFormats.length];
			   for (int i = 0; i < newFormats.length; ++i) {
				   unwrapped[i] = unwrap(newFormats[i]);
			   }
			   Object[] args = { unwrapped };
			   ((Method)sfsbai).invoke(messageFormat, args);
			   return;
		   }
		   catch (IllegalAccessException e) {
			   // can't happen
		   }
		   catch (InvocationTargetException e) {
			   // can't happen
		   }
	   }
	   throw new UnsupportedOperationException();
    }
   private static Object sfsbai;
   
   /**
    * Sets the formats to use for the format elements in the
    * previously set pattern string.
    * The order of formats in <code>newFormats</code> corresponds to
    * the order of format elements in the pattern string.
    * <p>
    * If more formats are provided than needed by the pattern string,
    * the remaining ones are ignored. If fewer formats are provided
    * than needed, then only the first <code>newFormats.length</code>
    * formats are replaced.
    * <p>
    * Since the order of format elements in a pattern string often
    * changes during localization, it is generally better to use the
    * {@link #setFormatsByArgumentIndex setFormatsByArgumentIndex}
    * method, which assumes an order of formats corresponding to the
    * order of elements in the <code>arguments</code> array passed to
    * the <code>format</code> methods or the result array returned by
    * the <code>parse</code> methods.
    *
    * @param newFormats the new formats to use
    * @exception NullPointerException if <code>newFormats</code> is null
    * @stable ICU 3.0
    */
   public void setFormats(Format[] newFormats) {
       messageFormat.setFormats(newFormats);
   }

   /**
    * Sets the format to use for the format elements within the
    * previously set pattern string that use the given argument
    * index.
    * The argument index is part of the format element definition and
    * represents an index into the <code>arguments</code> array passed
    * to the <code>format</code> methods or the result array returned
    * by the <code>parse</code> methods.
    * <p>
    * If the argument index is used for more than one format element
    * in the pattern string, then the new format is used for all such
    * format elements. If the argument index is not used for any format
    * element in the pattern string, then the new format is ignored.
    *
    * @param argumentIndex the argument index for which to use the new format
    * @param newFormat the new format to use
    * @stable ICU 3.0
    * @throws UnsupportedOperationException if the underlying JVM does not
    * support this method.
    */
   public void setFormatByArgumentIndex(int argumentIndex, Format newFormat) {
	   if (sfbai == null) {
		   synchronized (missing) {
			   try {
				   Class[] params = { Integer.TYPE, Format.class };
				   sfbai = java.text.MessageFormat.class.getMethod("setFormatByArgumentIndex", params);
			   }
			   catch (NoSuchMethodException e) {
				   sfbai = missing;
			   }
		   }
	   }
	   if (sfbai != missing) {
		   try {
			   Object[] args = { new Integer(argumentIndex), newFormat };
			   ((Method)sfbai).invoke(messageFormat, args);
			   return;
		   }
		   catch (IllegalAccessException e) {
			   // can't happen
		   }
		   catch (InvocationTargetException e) {
			   // can't happen
		   }
	   }
	   throw new UnsupportedOperationException();
   }
   private static Object sfbai;

   /**
    * Sets the format to use for the format element with the given
    * format element index within the previously set pattern string.
    * The format element index is the zero-based number of the format
    * element counting from the start of the pattern string.
    * <p>
    * Since the order of format elements in a pattern string often
    * changes during localization, it is generally better to use the
    * {@link #setFormatByArgumentIndex setFormatByArgumentIndex}
    * method, which accesses format elements based on the argument
    * index they specify.
    *
    * @param formatElementIndex the index of a format element within the pattern
    * @param newFormat the format to use for the specified format element
    * @exception ArrayIndexOutOfBoundsException if formatElementIndex is equal to or
    *            larger than the number of format elements in the pattern string
    * @stable ICU 3.0
    */
   public void setFormat(int formatElementIndex, Format newFormat) {
       messageFormat.setFormat(formatElementIndex, unwrap(newFormat));
   }

   /**
    * Gets the formats used for the values passed into
    * <code>format</code> methods or returned from <code>parse</code>
    * methods. The indices of elements in the returned array
    * correspond to the argument indices used in the previously set
    * pattern string.
    * The order of formats in the returned array thus corresponds to
    * the order of elements in the <code>arguments</code> array passed
    * to the <code>format</code> methods or the result array returned
    * by the <code>parse</code> methods.
    * <p>
    * If an argument index is used for more than one format element
    * in the pattern string, then the format used for the last such
    * format element is returned in the array. If an argument index
    * is not used for any format element in the pattern string, then
    * null is returned in the array.
    *
    * @return the formats used for the arguments within the pattern
    * @stable ICU 3.0
    * @throws UnsupportedOperationException if the underlying JVM does not 
    * support this method.
    */
   public Format[] getFormatsByArgumentIndex() {
	   if (gfbai == null) {
		   synchronized (missing) {
			   try {
				   gfbai = java.text.MessageFormat.class.getMethod("getFormatsByArgumentIndex", null);
			   }
			   catch (NoSuchMethodException e) {
				   gfbai = missing;
			   }
		   }
	   }
	   if (gfbai != missing) {
		   try {
			   Format[] result = (Format[])((Method)gfbai).invoke(messageFormat, null);
			   for (int i = 0; i < result.length; ++i) {
				   result[i] = wrap(result[i]);
			   }
			   return result;
		   }
		   catch (IllegalAccessException e) {
			   // can't happen
		   }
		   catch (InvocationTargetException e) {
			   // can't happen
		   }
	   }
	   throw new UnsupportedOperationException();
   }
   private static Object gfbai;
   private static final Object missing = new Object();

   /**
    * Gets the formats used for the format elements in the
    * previously set pattern string.
    * The order of formats in the returned array corresponds to
    * the order of format elements in the pattern string.
    * <p>
    * Since the order of format elements in a pattern string often
    * changes during localization, it's generally better to use the
    * {@link #getFormatsByArgumentIndex getFormatsByArgumentIndex}
    * method, which assumes an order of formats corresponding to the
    * order of elements in the <code>arguments</code> array passed to
    * the <code>format</code> methods or the result array returned by
    * the <code>parse</code> methods.
    *
    * @return the formats used for the format elements in the pattern
    * @stable ICU 3.0
    */
   public Format[] getFormats() {
       Format[] result = messageFormat.getFormats();
       for (int i = 0; i < result.length; ++i) {
           result[i] = wrap(result[i]);
       }
       return result;
   }

   /**
    * Formats an array of objects and appends the <code>MessageFormat</code>'s
    * pattern, with format elements replaced by the formatted objects, to the
    * provided <code>StringBuffer</code>.
    * <p>
    * The text substituted for the individual format elements is derived from
    * the current subformat of the format element and the
    * <code>arguments</code> element at the format element's argument index
    * as indicated by the first matching line of the following table. An
    * argument is <i>unavailable</i> if <code>arguments</code> is
    * <code>null</code> or has fewer than argumentIndex+1 elements.
    * <p>
    * <table border=1>
    *    <tr>
    *       <th>Subformat
    *       <th>Argument
    *       <th>Formatted Text
    *    <tr>
    *       <td><i>any</i>
    *       <td><i>unavailable</i>
    *       <td><code>"{" + argumentIndex + "}"</code>
    *    <tr>
    *       <td><i>any</i>
    *       <td><code>null</code>
    *       <td><code>"null"</code>
    *    <tr>
    *       <td><code>instanceof ChoiceFormat</code>
    *       <td><i>any</i>
    *       <td><code>subformat.format(argument).indexOf('{') >= 0 ?<br>
    *           (new MessageFormat(subformat.format(argument), getLocale())).format(argument) :
    *           subformat.format(argument)</code>
    *    <tr>
    *       <td><code>!= null</code>
    *       <td><i>any</i>
    *       <td><code>subformat.format(argument)</code>
    *    <tr>
    *       <td><code>null</code>
    *       <td><code>instanceof Number</code>
    *       <td><code>NumberFormat.getInstance(getLocale()).format(argument)</code>
    *    <tr>
    *       <td><code>null</code>
    *       <td><code>instanceof Date</code>
    *       <td><code>DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, getLocale()).format(argument)</code>
    *    <tr>
    *       <td><code>null</code>
    *       <td><code>instanceof String</code>
    *       <td><code>argument</code>
    *    <tr>
    *       <td><code>null</code>
    *       <td><i>any</i>
    *       <td><code>argument.toString()</code>
    * </table>
    * <p>
    * If <code>pos</code> is non-null, and refers to
    * <code>Field.ARGUMENT</code>, the location of the first formatted
    * string will be returned.
    *
    * @param arguments an array of objects to be formatted and substituted.
    * @param result where text is appended.
    * @param pos On input: an alignment field, if desired.
    *            On output: the offsets of the alignment field.
    * @exception IllegalArgumentException if an argument in the
    *            <code>arguments</code> array is not of the type
    *            expected by the format element(s) that use it.
    * @stable ICU 3.0
    */
   public final StringBuffer format(Object[] arguments, StringBuffer result,
       FieldPosition pos)
   {
       return messageFormat.format(arguments, result, pos);
   }

   /**
    * Creates a MessageFormat with the given pattern and uses it
    * to format the given arguments. This is equivalent to
    * <blockquote>
    *     <code>(new {@link #MessageFormat(String) MessageFormat}(pattern)).{@link #format(java.lang.Object[], java.lang.StringBuffer, java.text.FieldPosition) format}(arguments, new StringBuffer(), null).toString()</code>
    * </blockquote>
    *
    * @exception IllegalArgumentException if the pattern is invalid,
    *            or if an argument in the <code>arguments</code> array
    *            is not of the type expected by the format element(s)
    *            that use it.
    * @stable ICU 3.0
    */
   public static String format(String pattern, Object[] arguments) {
       return java.text.MessageFormat.format(pattern, arguments);
   }

   // Overrides
   /**
    * Formats an array of objects and appends the <code>MessageFormat</code>'s
    * pattern, with format elements replaced by the formatted objects, to the
    * provided <code>StringBuffer</code>.
    * This is equivalent to
    * <blockquote>
    *     <code>{@link #format(java.lang.Object[], java.lang.StringBuffer, java.text.FieldPosition) format}((Object[]) arguments, result, pos)</code>
    * </blockquote>
    *
    * @param arguments an array of objects to be formatted and substituted.
    * @param result where text is appended.
    * @param pos On input: an alignment field, if desired.
    *            On output: the offsets of the alignment field.
    * @exception IllegalArgumentException if an argument in the
    *            <code>arguments</code> array is not of the type
    *            expected by the format element(s) that use it.
    * @stable ICU 3.0
    */
   public final StringBuffer format(Object arguments, StringBuffer result,
       FieldPosition pos)
   {
       return messageFormat.format(arguments, result, pos);
   }


   /**
    * Parses the string.
    *
    * <p>Caveats: The parse may fail in a number of circumstances.
    * For example:
    * <ul>
    * <li>If one of the arguments does not occur in the pattern.
    * <li>If the format of an argument loses information, such as
    *     with a choice format where a large number formats to "many".
    * <li>Does not yet handle recursion (where
    *     the substituted strings contain {n} references.)
    * <li>Will not always find a match (or the correct match)
    *     if some part of the parse is ambiguous.
    *     For example, if the pattern "{1},{2}" is used with the
    *     string arguments {"a,b", "c"}, it will format as "a,b,c".
    *     When the result is parsed, it will return {"a", "b,c"}.
    * <li>If a single argument is parsed more than once in the string,
    *     then the later parse wins.
    * </ul>
    * When the parse fails, use ParsePosition.getErrorIndex() to find out
    * where in the string did the parsing failed.  The returned error
    * index is the starting offset of the sub-patterns that the string
    * is comparing with.  For example, if the parsing string "AAA {0} BBB"
    * is comparing against the pattern "AAD {0} BBB", the error index is
    * 0. When an error occurs, the call to this method will return null.
    * If the source is null, return an empty array.
    * @stable ICU 3.0
    */
   public Object[] parse(String source, ParsePosition pos) {
       return messageFormat.parse(source, pos);
   }

   /**
    * Parses text from the beginning of the given string to produce an object
    * array.
    * The method may not use the entire text of the given string.
    * <p>
    * See the {@link #parse(String, ParsePosition)} method for more information
    * on message parsing.
    *
    * @param source A <code>String</code> whose beginning should be parsed.
    * @return An <code>Object</code> array parsed from the string.
    * @exception ParseException if the beginning of the specified string
    *            cannot be parsed.
    * @stable ICU 3.0
    */
   public Object[] parse(String source) throws ParseException {
       return messageFormat.parse(source);
   }

   /**
    * Parses text from a string to produce an object array.
    * <p>
    * The method attempts to parse text starting at the index given by
    * <code>pos</code>.
    * If parsing succeeds, then the index of <code>pos</code> is updated
    * to the index after the last character used (parsing does not necessarily
    * use all characters up to the end of the string), and the parsed
    * object array is returned. The updated <code>pos</code> can be used to
    * indicate the starting point for the next call to this method.
    * If an error occurs, then the index of <code>pos</code> is not
    * changed, the error index of <code>pos</code> is set to the index of
    * the character where the error occurred, and null is returned.
    * <p>
    * See the {@link #parse(String, ParsePosition)} method for more information
    * on message parsing.
    *
    * @param source A <code>String</code>, part of which should be parsed.
    * @param pos A <code>ParsePosition</code> object with index and error
    *            index information as described above.
    * @return An <code>Object</code> array parsed from the string. In case of
    *         error, returns null.
    * @exception NullPointerException if <code>pos</code> is null.
    * @stable ICU 3.0
    */
   public Object parseObject(String source, ParsePosition pos) {
       return messageFormat.parse(source, pos);
   }

   /**
    * Convert an 'apostrophe-friendly' pattern into a standard
    * pattern.  Standard patterns treat all apostrophes as
    * quotes, which is problematic in some languages, e.g. 
    * French, where apostrophe is commonly used.  This utility
    * assumes that only an unpaired apostrophe immediately before
    * a brace is a true quote.  Other unpaired apostrophes are paired,
    * and the resulting standard pattern string is returned.
    *
    * <p><b>Note</b> it is not guaranteed that the returned pattern
    * is indeed a valid pattern.  The only effect is to convert
    * between patterns having different quoting semantics.
    *
    * @param pattern the 'apostrophe-friendly' patttern to convert
    * @return the standard equivalent of the original pattern
    * @stable ICU 3.4
    */
   public static String autoQuoteApostrophe(String pattern) {
       StringBuffer buf = new StringBuffer(pattern.length()*2);
       int state = STATE_INITIAL;
       int braceCount = 0;
       for (int i = 0, j = pattern.length(); i < j; ++i) {
           char c = pattern.charAt(i);
           switch (state) {
           case STATE_INITIAL:
               switch (c) {
               case SINGLE_QUOTE:
                   state = STATE_SINGLE_QUOTE;
                   break;
               case CURLY_BRACE_LEFT:
                   state = STATE_MSG_ELEMENT;
                   ++braceCount;
                   break;
               }
               break;
           case STATE_SINGLE_QUOTE:
               switch (c) {
               case SINGLE_QUOTE:
                   state = STATE_INITIAL;
                   break;
               case CURLY_BRACE_LEFT:
               case CURLY_BRACE_RIGHT:
                   state = STATE_IN_QUOTE;
                   break;
               default:
                   buf.append(SINGLE_QUOTE);
               state = STATE_INITIAL;
               break;
               }
               break;
           case STATE_IN_QUOTE:
               switch (c) {
               case SINGLE_QUOTE:
                   state = STATE_INITIAL;
                   break;
               }
               break;
           case STATE_MSG_ELEMENT:
               switch (c) {
               case CURLY_BRACE_LEFT:
                   ++braceCount;
                   break;
               case CURLY_BRACE_RIGHT:
                   if (--braceCount == 0) {
                       state = STATE_INITIAL;
                   }
                   break;
               }
               break;
           default: // Never happens.
               break;
           }
           buf.append(c);
       }
       // End of scan
       if (state == STATE_SINGLE_QUOTE || state == STATE_IN_QUOTE) {
           buf.append(SINGLE_QUOTE);
       }
       return new String(buf);
   }
   
   /**
    * Creates and returns a copy of this object.
    *
    * @return a clone of this instance.
    * @stable ICU 3.0
    */
   public Object clone() {
       return new MessageFormat((java.text.MessageFormat)messageFormat.clone());
   }

   /**
    * Equality comparison between two message format objects
    * @stable ICU 3.0
    */
   public boolean equals(Object obj) {
       try {
           return messageFormat.equals(((MessageFormat)obj).messageFormat);
       }
       catch (Exception e) {
           return false;
       }
   }

   /**
    * Generates a hash code for the message format object.
    * @stable ICU 3.0
    */
   public int hashCode() {
       return messageFormat.hashCode();
   }

   /**
    * Return a string suitable for debugging.
    * @return a string suitable for debugging
    * @stable ICU 3.4.2
    */
   public String toString() {
       return messageFormat.toPattern();
   }

   private static Format unwrap(Format f) {
       if (f instanceof DateFormat) {
           return ((DateFormat)f).dateFormat;
       } else if (f instanceof NumberFormat) {
           return ((NumberFormat)f).numberFormat;
       } else if (f instanceof MessageFormat) {
           return ((MessageFormat)f).messageFormat;
       } else {
           return f;
       }
   }

   private static Format wrap(Format f) {
       if (f instanceof java.text.DateFormat) {
           return new DateFormat((java.text.DateFormat)f);
       } else if (f instanceof java.text.DecimalFormat) {
           return new DecimalFormat((java.text.DecimalFormat)f);
       } else if (f instanceof java.text.MessageFormat) {
           return new MessageFormat((java.text.MessageFormat)f);
       } else {
           return f;
       }
   }

   private static final char SINGLE_QUOTE = '\'';
   private static final char CURLY_BRACE_LEFT = '{';
   private static final char CURLY_BRACE_RIGHT = '}';

   private static final int STATE_INITIAL = 0;
   private static final int STATE_SINGLE_QUOTE = 1;
   private static final int STATE_IN_QUOTE = 2;
   private static final int STATE_MSG_ELEMENT = 3;
}
