/*
**********************************************************************
* Copyright (c) 2004-2012, International Business Machines
* Corporation and others.  All Rights Reserved.
**********************************************************************
* Author: Alan Liu
* Created: April 6, 2004
* Since: ICU 3.0
**********************************************************************
*/
package com.ibm.icu.text;

import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.text.AttributedCharacterIterator;
import java.text.AttributedCharacterIterator.Attribute;
import java.text.AttributedString;
import java.text.CharacterIterator;
import java.text.ChoiceFormat;
import java.text.FieldPosition;
import java.text.Format;
import java.text.ParseException;
import java.text.ParsePosition;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

import com.ibm.icu.impl.PatternProps;
import com.ibm.icu.impl.Utility;
import com.ibm.icu.text.MessagePattern.ArgType;
import com.ibm.icu.text.MessagePattern.Part;
import com.ibm.icu.text.PluralFormat.PluralSelector;
import com.ibm.icu.text.PluralRules.PluralType;
import com.ibm.icu.util.ULocale;
import com.ibm.icu.util.ULocale.Category;

/**
 * {@icuenhanced java.text.MessageFormat}.{@icu _usage_}
 *
 * <p>MessageFormat prepares strings for display to users,
 * with optional arguments (variables/placeholders).
 * The arguments can occur in any order, which is necessary for translation
 * into languages with different grammars.
 *
 * <p>A MessageFormat is constructed from a <em>pattern</em> string
 * with arguments in {curly braces} which will be replaced by formatted values.
 *
 * <p><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). 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 and the
 * subformats used for inserted arguments.
 *
 * <p>Arguments can be named (using identifiers) or numbered (using small ASCII-digit integers).
 * Some of the API methods work only with argument numbers and throw an exception
 * if the pattern has named arguments (see {@link #usesNamedArguments()}).
 *
 * <p>An argument might not specify any format type. In this case,
 * a Number value is formatted with a default (for the locale) NumberFormat,
 * a Date value is formatted with a default (for the locale) DateFormat,
 * and for any other value its toString() value is used.
 *
 * <p>An argument might specify a "simple" type for which the specified
 * Format object is created, cached and used.
 *
 * <p>An argument might have a "complex" type with nested MessageFormat sub-patterns.
 * During formatting, one of these sub-messages is selected according to the argument value
 * and recursively formatted.
 *
 * <p>After construction, a custom Format object can be set for
 * a top-level argument, overriding the default formatting and parsing behavior
 * for that argument.
 * However, custom formatting can be achieved more simply by writing
 * a typeless argument in the pattern string
 * and supplying it with a preformatted string value.
 *
 * <p>When formatting, MessageFormat takes a collection of argument values
 * and writes an output string.
 * The argument values may be passed as an array
 * (when the pattern contains only numbered arguments)
 * or as a Map (which works for both named and numbered arguments).
 *
 * <p>Each argument is matched with one of the input values by array index or map key
 * and formatted according to its pattern specification
 * (or using a custom Format object if one was set).
 * A numbered pattern argument is matched with a map key that contains that number
 * as an ASCII-decimal-digit string (without leading zero).
 *
 * <h4><a name="patterns">Patterns and Their Interpretation</a></h4>
 *
 * <code>MessageFormat</code> uses patterns of the following form:
 * <blockquote><pre>
 * message = messageText (argument messageText)*
 * argument = noneArg | simpleArg | complexArg
 * complexArg = choiceArg | pluralArg | selectArg | selectordinalArg
 *
 * noneArg = '{' argNameOrNumber '}'
 * simpleArg = '{' argNameOrNumber ',' argType [',' argStyle] '}'
 * choiceArg = '{' argNameOrNumber ',' "choice" ',' choiceStyle '}'
 * pluralArg = '{' argNameOrNumber ',' "plural" ',' pluralStyle '}'
 * selectArg = '{' argNameOrNumber ',' "select" ',' selectStyle '}'
 * selectordinalArg = '{' argNameOrNumber ',' "selectordinal" ',' pluralStyle '}'
 *
 * choiceStyle: see {@link ChoiceFormat}
 * pluralStyle: see {@link PluralFormat}
 * selectStyle: see {@link SelectFormat}
 *
 * argNameOrNumber = argName | argNumber
 * argName = [^[[:Pattern_Syntax:][:Pattern_White_Space:]]]+
 * argNumber = '0' | ('1'..'9' ('0'..'9')*)
 *
 * argType = "number" | "date" | "time" | "spellout" | "ordinal" | "duration"
 * argStyle = "short" | "medium" | "long" | "full" | "integer" | "currency" | "percent" | argStyleText
 * </pre></blockquote>
 *
 * <ul>
 *   <li>messageText can contain quoted literal strings including syntax characters.
 *       A quoted literal string begins with an ASCII apostrophe and a syntax character
 *       (usually a {curly brace}) and continues until the next single apostrophe.
 *       A double ASCII apostrohpe inside or outside of a quoted string represents
 *       one literal apostrophe.
 *   <li>Quotable syntax characters are the {curly braces} in all messageText parts,
 *       plus the '#' sign in a messageText immediately inside a pluralStyle,
 *       and the '|' symbol in a messageText immediately inside a choiceStyle.
 *   <li>See also {@link MessagePattern.ApostropheMode}
 *   <li>In argStyleText, every single ASCII apostrophe begins and ends quoted literal text,
 *       and unquoted {curly braces} must occur in matched pairs.
 * </ul>
 *
 * <p>Recommendation: Use the real apostrophe (single quote) character \u2019 for
 * human-readable text, and 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>The <code>choice</code> argument type is deprecated.
 * Use <code>plural</code> arguments for proper plural selection,
 * and <code>select</code> arguments for simple selection among a fixed set of choices.
 *
 * <p>The <code>argType</code> and <code>argStyle</code> 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. Any <code>argStyleText</code> must
 * be a valid pattern string for the Format subclass used.
 *
 * <p><table border=1>
 *    <tr>
 *       <th>argType
 *       <th>argStyle
 *       <th>resulting Format object
 *    <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>argStyleText</i>
 *       <td><code>new DecimalFormat(argStyleText, 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>argStyleText</i>
 *       <td><code>new SimpleDateFormat(argStyleText, 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>argStyleText</i>
 *       <td><code>new SimpleDateFormat(argStyleText, getLocale())
 *    <tr>
 *       <td><code>spellout</code>
 *       <td><i>argStyleText (optional)</i>
 *       <td><code>new RuleBasedNumberFormat(getLocale(), RuleBasedNumberFormat.SPELLOUT)
 *           <br/>&nbsp;&nbsp;&nbsp;&nbsp;.setDefaultRuleset(argStyleText);</code>
 *    <tr>
 *       <td><code>ordinal</code>
 *       <td><i>argStyleText (optional)</i>
 *       <td><code>new RuleBasedNumberFormat(getLocale(), RuleBasedNumberFormat.ORDINAL)
 *           <br/>&nbsp;&nbsp;&nbsp;&nbsp;.setDefaultRuleset(argStyleText);</code>
 *    <tr>
 *       <td><code>duration</code>
 *       <td><i>argStyleText (optional)</i>
 *       <td><code>new RuleBasedNumberFormat(getLocale(), RuleBasedNumberFormat.DURATION)
 *           <br/>&nbsp;&nbsp;&nbsp;&nbsp;.setDefaultRuleset(argStyleText);</code>
 * </table>
 * <p>
 *
 * <h4><a name="diffsjdk">Differences from java.text.MessageFormat</a></h4>
 *
 * <p>The ICU MessageFormat supports both named and numbered arguments,
 * while the JDK MessageFormat only supports numbered arguments.
 * Named arguments make patterns more readable.
 *
 * <p>ICU implements a more user-friendly apostrophe quoting syntax.
 * In message text, an apostrophe only begins quoting literal text
 * if it immediately precedes a syntax character (mostly {curly braces}).<br>
 * In the JDK MessageFormat, an apostrophe always begins quoting,
 * which requires common text like "don't" and "aujourd'hui"
 * to be written with doubled apostrophes like "don''t" and "aujourd''hui".
 * For more details see {@link MessagePattern.ApostropheMode}.
 *
 * <p>ICU does not create a ChoiceFormat object for a choiceArg, pluralArg or selectArg
 * but rather handles such arguments itself.
 * The JDK MessageFormat does create and use a ChoiceFormat object
 * (<code>new ChoiceFormat(argStyleText)</code>).
 * The JDK does not support plural and select arguments at all.
 *
 * <h4>Usage Information</h4>
 *
 * <p>Here are some examples of usage:
 * <blockquote>
 * <pre>
 * Object[] arguments = {
 *     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 = { 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 messages that include plural forms, you can use a plural argument:
 * <pre>
 * MessageFormat msgFmt = new MessageFormat(
 *     "{num_files, plural, " +
 *     "=0{There are no files on disk \"{disk_name}\".}" +
 *     "=1{There is one file on disk \"{disk_name}\".}" +
 *     "other{There are # files on disk \"{disk_name}\".}}",
 *     ULocale.ENGLISH);
 * Map args = new HashMap();
 * args.put("num_files", 0);
 * args.put("disk_name", "MyDisk");
 * System.out.println(msgFmt.format(args));
 * args.put("num_files", 3);
 * System.out.println(msgFmt.format(args));
 * 
 * <em>output</em>:
 * There are no files on disk "MyDisk".
 * There are 3 files on "MyDisk".
 * </pre>
 * See {@link PluralFormat} and {@link PluralRules} for details.
 *
 * <h4><a name="synchronization">Synchronization</a></h4>
 *
 * <p>MessageFormats 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
 * @see          PluralFormat
 * @see          SelectFormat
 * @author       Mark Davis
 * @author       Markus Scherer
 * @stable ICU 3.0
 */
public class MessageFormat extends UFormat {

    // Incremented by 1 for ICU 4.8's new format.
    static final long serialVersionUID = 7136212545847378652L;

    /**
     * Constructs a MessageFormat for the default <code>FORMAT</code> locale and the
     * specified pattern.
     * Sets the locale and calls applyPattern(pattern).
     *
     * @param pattern the pattern for this message format
     * @exception IllegalArgumentException if the pattern is invalid
     * @see Category#FORMAT
     * @stable ICU 3.0
     */
    public MessageFormat(String pattern) {
        this.ulocale = ULocale.getDefault(Category.FORMAT);
        applyPattern(pattern);
    }

    /**
     * Constructs a MessageFormat for the specified locale and
     * pattern.
     * Sets the locale and calls applyPattern(pattern).
     *
     * @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) {
        this(pattern, ULocale.forLocale(locale));
    }

    /**
     * Constructs a MessageFormat for the specified locale and
     * pattern.
     * Sets the locale and calls applyPattern(pattern).
     *
     * @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) {
        this.ulocale = locale;
        applyPattern(pattern);
    }

    /**
     * Sets the locale to be used for creating argument Format objects.
     * This affects subsequent calls to the {@link #applyPattern applyPattern}
     * method 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) {
        setLocale(ULocale.forLocale(locale));
    }

    /**
     * Sets the locale to be used for creating argument Format objects.
     * This affects subsequent calls to the {@link #applyPattern applyPattern}
     * method 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) {
        /* Save the pattern, and then reapply so that */
        /* we pick up any changes in locale specific */
        /* elements */
        String existingPattern = toPattern();                       /*ibm.3550*/
        this.ulocale = locale;
        // Invalidate all stock formatters. They are no longer valid since
        // the locale has changed.
        stockNumberFormatter = stockDateFormatter = null;
        pluralProvider = null;
        ordinalProvider = null;
        applyPattern(existingPattern);                              /*ibm.3550*/
    }

    /**
     * Returns 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 ulocale.toLocale();
    }

    /**
     * {@icu} Returns the locale that's used when creating argument Format objects.
     *
     * @return the locale used when creating or comparing subformats
     * @stable ICU 3.2
     */
    public ULocale getULocale() {
        return ulocale;
    }
    
    /**
     * Sets the pattern used by this message format.
     * Parses the pattern and caches Format objects for simple argument types.
     * Patterns and their interpretation are specified in the
     * <a href="#patterns">class description</a>.
     *
     * @param pttrn the pattern for this message format
     * @throws IllegalArgumentException if the pattern is invalid
     * @stable ICU 3.0
     */
    public void applyPattern(String pttrn) {
        try {
            if (msgPattern == null) {
                msgPattern = new MessagePattern(pttrn);
            } else {
                msgPattern.parse(pttrn);
            }
            // Cache the formats that are explicitly mentioned in the message pattern.
            cacheExplicitFormats();
        } catch(RuntimeException e) {
            resetPattern();
            throw e;
        }
    }

    /**
     * {@icu} Sets the ApostropheMode and the pattern used by this message format.
     * Parses the pattern and caches Format objects for simple argument types.
     * Patterns and their interpretation are specified in the
     * <a href="#patterns">class description</a>.
     * <p>
     * This method is best used only once on a given object to avoid confusion about the mode,
     * and after constructing the object with an empty pattern string to minimize overhead.
     *
     * @param pattern the pattern for this message format
     * @param aposMode the new ApostropheMode
     * @throws IllegalArgumentException if the pattern is invalid
     * @see MessagePattern.ApostropheMode
     * @stable ICU 4.8
     */
    public void applyPattern(String pattern, MessagePattern.ApostropheMode aposMode) {
        if (msgPattern == null) {
            msgPattern = new MessagePattern(aposMode);
        } else if (aposMode != msgPattern.getApostropheMode()) {
            msgPattern.clearPatternAndSetApostropheMode(aposMode);
        }
        applyPattern(pattern);
    }

    /**
     * {@icu}
     * @return this instance's ApostropheMode.
     * @stable ICU 4.8
     */
    public MessagePattern.ApostropheMode getApostropheMode() {
        if (msgPattern == null) {
            msgPattern = new MessagePattern();  // Sets the default mode.
        }
        return msgPattern.getApostropheMode();
    }

    /**
     * Returns the applied pattern string.
     * @return the pattern string
     * @throws IllegalStateException after custom Format objects have been set
     *         via setFormat() or similar APIs
     * @stable ICU 3.0
     */
    public String toPattern() {
        // Return the original, applied pattern string, or else "".
        // Note: This does not take into account
        // - changes from setFormat() and similar methods, or
        // - normalization of apostrophes and arguments, for example,
        //   whether some date/time/number formatter was created via a pattern
        //   but is equivalent to the "medium" default format.
        if (customFormatArgStarts != null) {
            throw new IllegalStateException(
                    "toPattern() is not supported after custom Format objects "+
                    "have been set via setFormat() or similar APIs");
        }
        if (msgPattern == null) {
            return "";
        }
        String originalPattern = msgPattern.getPatternString();
        return originalPattern == null ? "" : originalPattern;
    }

    /**
     * Returns the part index of the next ARG_START after partIndex, or -1 if there is none more.
     * @param partIndex Part index of the previous ARG_START (initially 0).
     */
    private int nextTopLevelArgStart(int partIndex) {
        if (partIndex != 0) {
            partIndex = msgPattern.getLimitPartIndex(partIndex);
        }
        for (;;) {
            MessagePattern.Part.Type type = msgPattern.getPartType(++partIndex);
            if (type == MessagePattern.Part.Type.ARG_START) {
                return partIndex;
            }
            if (type == MessagePattern.Part.Type.MSG_LIMIT) {
                return -1;
            }
        }
    }

    private boolean argNameMatches(int partIndex, String argName, int argNumber) {
        Part part = msgPattern.getPart(partIndex);
        return part.getType() == MessagePattern.Part.Type.ARG_NAME ?
            msgPattern.partSubstringMatches(part, argName) :
            part.getValue() == argNumber;  // ARG_NUMBER
    }

    private String getArgName(int partIndex) {
        Part part = msgPattern.getPart(partIndex);
        if (part.getType() == MessagePattern.Part.Type.ARG_NAME) {
            return msgPattern.getSubstring(part);
        } else {
            return Integer.toString(part.getValue());
        }
    }

    /**
     * Sets the Format objects 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.
     *
     * This method is only supported if the format does not use
     * named arguments, otherwise an IllegalArgumentException is thrown.
     *
     * @param newFormats the new formats to use
     * @throws NullPointerException if <code>newFormats</code> is null
     * @throws IllegalArgumentException if this formatter uses named arguments
     * @stable ICU 3.0
     */
    public void setFormatsByArgumentIndex(Format[] newFormats) {
        if (msgPattern.hasNamedArguments()) {
            throw new IllegalArgumentException(
                    "This method is not available in MessageFormat objects " +
                    "that use alphanumeric argument names.");
        }
        for (int partIndex = 0; (partIndex = nextTopLevelArgStart(partIndex)) >= 0;) {
            int argNumber = msgPattern.getPart(partIndex + 1).getValue();
            if (argNumber < newFormats.length) {
                setCustomArgStartFormat(partIndex, newFormats[argNumber]);
            }
        }
    }

    /**
     * {@icu} Sets the Format objects to use for the values passed into
     * <code>format</code> methods or returned from <code>parse</code>
     * methods. The keys in <code>newFormats</code> are the argument
     * names in the previously set pattern string, and the values
     * are the formats.
     * <p>
     * Only argument names from the pattern string are considered.
     * Extra keys in <code>newFormats</code> that do not correspond
     * to an argument name are ignored.  Similarly, if there is no
     * format in newFormats for an argument name, the formatter
     * for that argument remains unchanged.
     * <p>
     * This may be called on formats that do not use named arguments.
     * In this case the map will be queried for key Strings that
     * represent argument indices, e.g. "0", "1", "2" etc.
     *
     * @param newFormats a map from String to Format providing new
     *        formats for named arguments.
     * @stable ICU 3.8
     */
    public void setFormatsByArgumentName(Map<String, Format> newFormats) {
        for (int partIndex = 0; (partIndex = nextTopLevelArgStart(partIndex)) >= 0;) {
            String key = getArgName(partIndex + 1);
            if (newFormats.containsKey(key)) {
                setCustomArgStartFormat(partIndex, newFormats.get(key));
            }
        }
    }

    /**
     * Sets the Format objects 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) {
        int formatNumber = 0;
        for (int partIndex = 0;
                formatNumber < newFormats.length &&
                (partIndex = nextTopLevelArgStart(partIndex)) >= 0;) {
            setCustomArgStartFormat(partIndex, newFormats[formatNumber]);
            ++formatNumber;
        }
    }

    /**
     * Sets the Format object 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.
     *
     * This method is only supported when exclusively numbers are used for
     * argument names. Otherwise an IllegalArgumentException is thrown.
     *
     * @param argumentIndex the argument index for which to use the new format
     * @param newFormat the new format to use
     * @throws IllegalArgumentException if this format uses named arguments
     * @stable ICU 3.0
     */
    public void setFormatByArgumentIndex(int argumentIndex, Format newFormat) {
        if (msgPattern.hasNamedArguments()) {
            throw new IllegalArgumentException(
                    "This method is not available in MessageFormat objects " +
                    "that use alphanumeric argument names.");
        }
        for (int partIndex = 0; (partIndex = nextTopLevelArgStart(partIndex)) >= 0;) {
            if (msgPattern.getPart(partIndex + 1).getValue() == argumentIndex) {
                setCustomArgStartFormat(partIndex, newFormat);
            }
        }
    }

    /**
     * {@icu} Sets the Format object to use for the format elements within the
     * previously set pattern string that use the given argument
     * name.
     * <p>
     * If the argument name 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 name is not used for any format
     * element in the pattern string, then the new format is ignored.
     * <p>
     * This API may be used on formats that do not use named arguments.
     * In this case <code>argumentName</code> should be a String that names
     * an argument index, e.g. "0", "1", "2"... etc.  If it does not name
     * a valid index, the format will be ignored.  No error is thrown.
     *
     * @param argumentName the name of the argument to change
     * @param newFormat the new format to use
     * @stable ICU 3.8
     */
    public void setFormatByArgumentName(String argumentName, Format newFormat) {
        int argNumber = MessagePattern.validateArgumentName(argumentName);
        if (argNumber < MessagePattern.ARG_NAME_NOT_NUMBER) {
            return;
        }
        for (int partIndex = 0; (partIndex = nextTopLevelArgStart(partIndex)) >= 0;) {
            if (argNameMatches(partIndex + 1, argumentName, argNumber)) {
                setCustomArgStartFormat(partIndex, newFormat);
            }
        }
    }

    /**
     * Sets the Format object 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) {
        int formatNumber = 0;
        for (int partIndex = 0; (partIndex = nextTopLevelArgStart(partIndex)) >= 0;) {
            if (formatNumber == formatElementIndex) {
                setCustomArgStartFormat(partIndex, newFormat);
                return;
            }
            ++formatNumber;
        }
        throw new ArrayIndexOutOfBoundsException(formatElementIndex);
    }

    /**
     * Returns the Format objects 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.
     *
     * This method is only supported when exclusively numbers are used for
     * argument names. Otherwise an IllegalArgumentException is thrown.
     *
     * @return the formats used for the arguments within the pattern
     * @throws IllegalArgumentException if this format uses named arguments
     * @stable ICU 3.0
     */
    public Format[] getFormatsByArgumentIndex() {
        if (msgPattern.hasNamedArguments()) {
            throw new IllegalArgumentException(
                    "This method is not available in MessageFormat objects " +
                    "that use alphanumeric argument names.");
        }
        ArrayList<Format> list = new ArrayList<Format>();
        for (int partIndex = 0; (partIndex = nextTopLevelArgStart(partIndex)) >= 0;) {
            int argNumber = msgPattern.getPart(partIndex + 1).getValue();
            while (argNumber >= list.size()) {
                list.add(null);
            }
            list.set(argNumber, cachedFormatters == null ? null : cachedFormatters.get(partIndex));
        }
        return list.toArray(new Format[list.size()]);
    }

    /**
     * Returns the Format objects 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()}
     * 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.
     *
     * This method is only supported when exclusively numbers are used for
     * argument names. Otherwise an IllegalArgumentException is thrown.
     *
     * @return the formats used for the format elements in the pattern
     * @throws IllegalArgumentException if this format uses named arguments
     * @stable ICU 3.0
     */
    public Format[] getFormats() {
        ArrayList<Format> list = new ArrayList<Format>();
        for (int partIndex = 0; (partIndex = nextTopLevelArgStart(partIndex)) >= 0;) {
            list.add(cachedFormatters == null ? null : cachedFormatters.get(partIndex));
        }
        return list.toArray(new Format[list.size()]);
    }

    /**
     * {@icu} Returns the top-level argument names. For more details, see
     * {@link #setFormatByArgumentName(String, Format)}.
     * @return a Set of argument names
     * @stable ICU 4.8
     */
    public Set<String> getArgumentNames() {
        Set<String> result = new HashSet<String>();
        for (int partIndex = 0; (partIndex = nextTopLevelArgStart(partIndex)) >= 0;) {
            result.add(getArgName(partIndex + 1));
        }
        return result;
    }

    /**
     * {@icu} Returns the first top-level format associated with the given argument name.
     * For more details, see {@link #setFormatByArgumentName(String, Format)}.
     * @param argumentName The name of the desired argument.
     * @return the Format associated with the name, or null if there isn't one.
     * @stable ICU 4.8
     */
    public Format getFormatByArgumentName(String argumentName) {
        if (cachedFormatters == null) {
            return null;
        }
        int argNumber = MessagePattern.validateArgumentName(argumentName);
        if (argNumber < MessagePattern.ARG_NAME_NOT_NUMBER) {
            return null;
        }
        for (int partIndex = 0; (partIndex = nextTopLevelArgStart(partIndex)) >= 0;) {
            if (argNameMatches(partIndex + 1, argumentName, argNumber)) {
                return cachedFormatters.get(partIndex);
            }
        }
        return null;
    }

    /**
     * Formats an array of objects and appends the <code>MessageFormat</code>'s
     * pattern, with arguments 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.  When
     * an argument is unavailable no substitution is performed.
     * <p>
     * <table border=1>
     *    <tr>
     *       <th>argType or Format
     *       <th>value object
     *       <th>Formatted Text
     *    <tr>
     *       <td><i>any</i>
     *       <td><i>unavailable</i>
     *       <td><code>"{" + argNameOrNumber + "}"</code>
     *    <tr>
     *       <td><i>any</i>
     *       <td><code>null</code>
     *       <td><code>"null"</code>
     *    <tr>
     *       <td>custom Format <code>!= null</code>
     *       <td><i>any</i>
     *       <td><code>customFormat.format(argument)</code>
     *    <tr>
     *       <td>noneArg, or custom Format <code>== null</code>
     *       <td><code>instanceof Number</code>
     *       <td><code>NumberFormat.getInstance(getLocale()).format(argument)</code>
     *    <tr>
     *       <td>noneArg, or custom Format <code>== null</code>
     *       <td><code>instanceof Date</code>
     *       <td><code>DateFormat.getDateTimeInstance(DateFormat.SHORT,
     *           DateFormat.SHORT, getLocale()).format(argument)</code>
     *    <tr>
     *       <td>noneArg, or custom Format <code>== null</code>
     *       <td><code>instanceof String</code>
     *       <td><code>argument</code>
     *    <tr>
     *       <td>noneArg, or custom Format <code>== null</code>
     *       <td><i>any</i>
     *       <td><code>argument.toString()</code>
     *    <tr>
     *       <td>complexArg
     *       <td><i>any</i>
     *       <td>result of recursive formatting of a selected sub-message
     * </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.
     *
     * This method is only supported when the format does not use named
     * arguments, otherwise an IllegalArgumentException is thrown.
     *
     * @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.
     * @throws IllegalArgumentException if a value in the
     *         <code>arguments</code> array is not of the type
     *         expected by the corresponding argument or custom Format object.
     * @throws IllegalArgumentException if this format uses named arguments
     * @stable ICU 3.0
     */
    public final StringBuffer format(Object[] arguments, StringBuffer result,
                                     FieldPosition pos)
    {
        format(arguments, null, new AppendableWrapper(result), pos);
        return result;
    }

    /**
     * Formats a map of objects and appends the <code>MessageFormat</code>'s
     * pattern, with arguments 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> value corresopnding to the format element's
     * argument name.
     * <p>
     * A numbered pattern argument is matched with a map key that contains that number
     * as an ASCII-decimal-digit string (without leading zero).
     * <p>
     * An argument is <i>unavailable</i> if <code>arguments</code> is
     * <code>null</code> or does not have a value corresponding to an argument
     * name in the pattern.  When an argument is unavailable no substitution
     * is performed.
     *
     * @param arguments a map 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.
     * @throws IllegalArgumentException if a value in the
     *         <code>arguments</code> array is not of the type
     *         expected by the corresponding argument or custom Format object.
     * @return the passed-in StringBuffer
     * @stable ICU 3.8
     */
    public final StringBuffer format(Map<String, Object> arguments, StringBuffer result,
                                     FieldPosition pos) {
        format(null, arguments, new AppendableWrapper(result), pos);
        return result;
    }

    /**
     * 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>
     *
     * @throws IllegalArgumentException if the pattern is invalid
     * @throws IllegalArgumentException if a value in the
     *         <code>arguments</code> array is not of the type
     *         expected by the corresponding argument or custom Format object.
     * @throws IllegalArgumentException if this format uses named arguments
     * @stable ICU 3.0
     */
    public static String format(String pattern, Object... arguments) {
        MessageFormat temp = new MessageFormat(pattern);
        return temp.format(arguments);
    }

    /**
     * Creates a MessageFormat with the given pattern and uses it to
     * format the given arguments.  The pattern must identifyarguments
     * by name instead of by number.
     * <p>
     * @throws IllegalArgumentException if the pattern is invalid
     * @throws IllegalArgumentException if a value in the
     *         <code>arguments</code> array is not of the type
     *         expected by the corresponding argument or custom Format object.
     * @see #format(Map, StringBuffer, FieldPosition)
     * @see #format(String, Object[])
     * @stable ICU 3.8
     */
    public static String format(String pattern, Map<String, Object> arguments) {
        MessageFormat temp = new MessageFormat(pattern);
        return temp.format(arguments);
    }

    /**
     * {@icu} Returns true if this MessageFormat uses named arguments,
     * and false otherwise.  See class description.
     *
     * @return true if named arguments are used.
     * @stable ICU 3.8
     */
    public boolean usesNamedArguments() {
        return msgPattern.hasNamedArguments();
    }

    // Overrides
    /**
     * Formats a map or 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 either of
     * <blockquote>
     *     <code>{@link #format(java.lang.Object[], java.lang.StringBuffer,
     *     java.text.FieldPosition) format}((Object[]) arguments, result, pos)</code>
     *     <code>{@link #format(java.util.Map, java.lang.StringBuffer,
     *     java.text.FieldPosition) format}((Map) arguments, result, pos)</code>
     * </blockquote>
     * A map must be provided if this format uses named arguments, otherwise
     * an IllegalArgumentException will be thrown.
     * @param arguments a map or array of objects to be formatted
     * @param result where text is appended
     * @param pos On input: an alignment field, if desired
     *            On output: the offsets of the alignment field
     * @throws IllegalArgumentException if an argument in
     *         <code>arguments</code> is not of the type
     *         expected by the format element(s) that use it
     * @throws IllegalArgumentException if <code>arguments<code> is
     *         an array of Object and this format uses named arguments
     * @stable ICU 3.0
     */
    public final StringBuffer format(Object arguments, StringBuffer result,
                                     FieldPosition pos)
    {
        format(arguments, new AppendableWrapper(result), pos);
        return result;
    }

    /**
     * Formats an array of objects and inserts them into the
     * <code>MessageFormat</code>'s pattern, producing an
     * <code>AttributedCharacterIterator</code>.
     * You can use the returned <code>AttributedCharacterIterator</code>
     * to build the resulting String, as well as to determine information
     * about the resulting String.
     * <p>
     * The text of the returned <code>AttributedCharacterIterator</code> is
     * the same that would be returned by
     * <blockquote>
     *     <code>{@link #format(java.lang.Object[], java.lang.StringBuffer,
     *     java.text.FieldPosition) format}(arguments, new StringBuffer(), null).toString()</code>
     * </blockquote>
     * <p>
     * In addition, the <code>AttributedCharacterIterator</code> contains at
     * least attributes indicating where text was generated from an
     * argument in the <code>arguments</code> array. The keys of these attributes are of
     * type <code>MessageFormat.Field</code>, their values are
     * <code>Integer</code> objects indicating the index in the <code>arguments</code>
     * array of the argument from which the text was generated.
     * <p>
     * The attributes/value from the underlying <code>Format</code>
     * instances that <code>MessageFormat</code> uses will also be
     * placed in the resulting <code>AttributedCharacterIterator</code>.
     * This allows you to not only find where an argument is placed in the
     * resulting String, but also which fields it contains in turn.
     *
     * @param arguments an array of objects to be formatted and substituted.
     * @return AttributedCharacterIterator describing the formatted value.
     * @exception NullPointerException if <code>arguments</code> is null.
     * @throws IllegalArgumentException if a value in the
     *         <code>arguments</code> array is not of the type
     *         expected by the corresponding argument or custom Format object.
     * @stable ICU 3.8
     */
    public AttributedCharacterIterator formatToCharacterIterator(Object arguments) {
        if (arguments == null) {
            throw new NullPointerException(
                   "formatToCharacterIterator must be passed non-null object");
        }
        StringBuilder result = new StringBuilder();
        AppendableWrapper wrapper = new AppendableWrapper(result);
        wrapper.useAttributes();
        format(arguments, wrapper, null);
        AttributedString as = new AttributedString(result.toString());
        for (AttributeAndPosition a : wrapper.attributes) {
            as.addAttribute(a.key, a.value, a.start, a.limit);
        }
        return as.getIterator();
    }

    /**
     * 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.
     *
     * @throws IllegalArgumentException if this format uses named arguments
     * @stable ICU 3.0
     */
    public Object[] parse(String source, ParsePosition pos) {
        if (msgPattern.hasNamedArguments()) {
            throw new IllegalArgumentException(
                    "This method is not available in MessageFormat objects " +
                    "that use named argument.");
        }
        
        // Count how many slots we need in the array.
        int maxArgId = -1;
        for (int partIndex = 0; (partIndex = nextTopLevelArgStart(partIndex)) >= 0;) {
            int argNumber=msgPattern.getPart(partIndex + 1).getValue();
            if (argNumber > maxArgId) {
                maxArgId = argNumber;
            }
        }
        Object[] resultArray = new Object[maxArgId + 1];

        int backupStartPos = pos.getIndex();
        parse(0, source, pos, resultArray, null);
        if (pos.getIndex() == backupStartPos) { // unchanged, returned object is null
            return null;
        }

        return resultArray;
    }
    
    /**
     * {@icu} Parses the string, returning the results in a Map.
     * This is similar to the version that returns an array
     * of Object.  This supports both named and numbered
     * arguments-- if numbered, the keys in the map are the
     * corresponding ASCII-decimal-digit strings (e.g. "0", "1", "2"...).
     *
     * @param source the text to parse
     * @param pos the position at which to start parsing.  on return,
     *        contains the result of the parse.
     * @return a Map containing key/value pairs for each parsed argument.
     * @stable ICU 3.8
     */
    public Map<String, Object> parseToMap(String source, ParsePosition pos)  {
        Map<String, Object> result = new HashMap<String, Object>();
        int backupStartPos = pos.getIndex();
        parse(0, source, pos, null, result);
        if (pos.getIndex() == backupStartPos) {
            return null;
        }
        return result;        
    }
    
    /**
     * 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.
     * @exception IllegalArgumentException if this format uses named arguments
     * @stable ICU 3.0
     */
    public Object[] parse(String source) throws ParseException {
        ParsePosition pos = new ParsePosition(0);
        Object[] result = parse(source, pos);
        if (pos.getIndex() == 0) // unchanged, returned object is null
            throw new ParseException("MessageFormat parse error!",
                                     pos.getErrorIndex());

        return result;
    }

    /**
     * Parses the string, filling either the Map or the Array.
     * This is a private method that all the public parsing methods call.
     * This supports both named and numbered
     * arguments-- if numbered, the keys in the map are the
     * corresponding ASCII-decimal-digit strings (e.g. "0", "1", "2"...).
     *
     * @param msgStart index in the message pattern to start from.
     * @param source the text to parse
     * @param pos the position at which to start parsing.  on return,
     *        contains the result of the parse.
     * @param args if not null, the parse results will be filled here (The pattern
     *        has to have numbered arguments in order for this to not be null).
     * @param argsMap if not null, the parse results will be filled here.
     */
    private void parse(int msgStart, String source, ParsePosition pos,
                       Object[] args, Map<String, Object> argsMap) {
        if (source == null) {
            return;
        }
        String msgString=msgPattern.getPatternString();
        int prevIndex=msgPattern.getPart(msgStart).getLimit();
        int sourceOffset = pos.getIndex();
        ParsePosition tempStatus = new ParsePosition(0);

        for(int i=msgStart+1; ; ++i) {
            Part part=msgPattern.getPart(i);
            Part.Type type=part.getType();
            int index=part.getIndex();
            // Make sure the literal string matches.
            int len = index - prevIndex;
            if (len == 0 || msgString.regionMatches(prevIndex, source, sourceOffset, len)) {
                sourceOffset += len;
                prevIndex += len;
            } else {
                pos.setErrorIndex(sourceOffset);
                return; // leave index as is to signal error
            }
            if(type==Part.Type.MSG_LIMIT) {
                // Things went well! Done.
                pos.setIndex(sourceOffset);
                return;
            }
            if(type==Part.Type.SKIP_SYNTAX || type==Part.Type.INSERT_CHAR) {
                prevIndex=part.getLimit();
                continue;
            }
            // We do not support parsing Plural formats. (No REPLACE_NUMBER here.)
            assert type==Part.Type.ARG_START : "Unexpected Part "+part+" in parsed message.";
            int argLimit=msgPattern.getLimitPartIndex(i);
            
            ArgType argType=part.getArgType();
            part=msgPattern.getPart(++i);
            // Compute the argId, so we can use it as a key.
            Object argId=null;
            int argNumber = 0;
            String key = null;
            if(args!=null) {
                argNumber=part.getValue();  // ARG_NUMBER
                argId = Integer.valueOf(argNumber);
            } else {
                if(part.getType()==MessagePattern.Part.Type.ARG_NAME) {
                    key=msgPattern.getSubstring(part);
                } else /* ARG_NUMBER */ {
                    key=Integer.toString(part.getValue());
                }
                argId = key;
            }

            ++i;
            Format formatter = null;
            boolean haveArgResult = false;
            Object argResult = null;
            if(cachedFormatters!=null && (formatter=cachedFormatters.get(i - 2))!=null) {
                // Just parse using the formatter.
                tempStatus.setIndex(sourceOffset);
                argResult = formatter.parseObject(source, tempStatus);
                if (tempStatus.getIndex() == sourceOffset) {
                    pos.setErrorIndex(sourceOffset);
                    return; // leave index as is to signal error
                }
                haveArgResult = true;
                sourceOffset = tempStatus.getIndex();
            } else if(
                    argType==ArgType.NONE ||
                    (cachedFormatters!=null && cachedFormatters.containsKey(i - 2))) {
                // Match as a string.
                // if at end, use longest possible match
                // otherwise uses first match to intervening string
                // does NOT recursively try all possibilities
                String stringAfterArgument = getLiteralStringUntilNextArgument(argLimit);
                int next;
                if (stringAfterArgument.length() != 0) {
                    next = source.indexOf(stringAfterArgument, sourceOffset);
                } else {
                    next = source.length();
                }
                if (next < 0) {
                    pos.setErrorIndex(sourceOffset);
                    return; // leave index as is to signal error
                } else {
                    String strValue = source.substring(sourceOffset, next);
                    if (!strValue.equals("{" + argId.toString() + "}")) {
                        haveArgResult = true;
                        argResult = strValue;
                    }
                    sourceOffset = next;
                }
            } else if(argType==ArgType.CHOICE) {
                tempStatus.setIndex(sourceOffset);
                double choiceResult = parseChoiceArgument(msgPattern, i, source, tempStatus);
                if (tempStatus.getIndex() == sourceOffset) {
                    pos.setErrorIndex(sourceOffset);
                    return; // leave index as is to signal error
                }
                argResult = choiceResult;
                haveArgResult = true;
                sourceOffset = tempStatus.getIndex();
            } else if(argType.hasPluralStyle() || argType==ArgType.SELECT) {
                // No can do!
                throw new UnsupportedOperationException(
                        "Parsing of plural/select/selectordinal argument is not supported.");
            } else {
                // This should never happen.
                throw new IllegalStateException("unexpected argType "+argType);
            }
            if (haveArgResult) {
                if (args != null) {
                    args[argNumber] = argResult;
                } else if (argsMap != null) {
                    argsMap.put(key, argResult);
                }
            }
            prevIndex=msgPattern.getPart(argLimit).getLimit();
            i=argLimit;
        }
    }

    /**
     * {@icu} Parses text from the beginning of the given string to produce a map from
     * argument to values. 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 A <code>Map</code> parsed from the string.
     * @throws ParseException if the beginning of the specified string cannot
     *         be parsed.
     * @see #parseToMap(String, ParsePosition)
     * @stable ICU 3.8
     */
    public Map<String, Object> parseToMap(String source) throws ParseException {
        ParsePosition pos = new ParsePosition(0);
        Map<String, Object> result = new HashMap<String, Object>();
        parse(0, source, pos, null, result);
        if (pos.getIndex() == 0) // unchanged, returned object is null
            throw new ParseException("MessageFormat parse error!",
                                     pos.getErrorIndex());

        return result;
    }

    /**
     * Parses text from a string to produce an object array or Map.
     * <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> parsed from the string, either an
     *         array of Object, or a Map, depending on whether named
     *         arguments are used.  This can be queried using <code>usesNamedArguments</code>.
     *         In case of error, returns null.
     * @throws NullPointerException if <code>pos</code> is null.
     * @stable ICU 3.0
     */
    public Object parseObject(String source, ParsePosition pos) {
        if (!msgPattern.hasNamedArguments()) {
            return parse(source, pos);
        } else {
            return parseToMap(source, pos);
        }
    }

    /**
     * {@inheritDoc}
     * @stable ICU 3.0
     */
    @Override
    public Object clone() {
        MessageFormat other = (MessageFormat) super.clone();

        if (customFormatArgStarts != null) {
            other.customFormatArgStarts = new HashSet<Integer>();
            for (Integer key : customFormatArgStarts) {
                other.customFormatArgStarts.add(key);
            }
        } else {
            other.customFormatArgStarts = null;
        }
        
        if (cachedFormatters != null) {
            other.cachedFormatters = new HashMap<Integer, Format>();
            Iterator<Map.Entry<Integer, Format>> it = cachedFormatters.entrySet().iterator();
            while (it.hasNext()){
                Map.Entry<Integer, Format> entry = it.next();
                other.cachedFormatters.put(entry.getKey(), entry.getValue());
            }
        } else {
            other.cachedFormatters = null;
        }
        
        other.msgPattern = msgPattern == null ? null : (MessagePattern)msgPattern.clone();
        other.stockDateFormatter = stockDateFormatter == null ? null : (Format) stockDateFormatter.clone();
        other.stockNumberFormatter = stockNumberFormatter == null ? null : (Format) stockNumberFormatter.clone();

        other.pluralProvider = null;
        other.ordinalProvider = null;
        return other;
    }

    /**
     * {@inheritDoc}
     * @stable ICU 3.0
     */
    @Override
    public boolean equals(Object obj) {
        if (this == obj)                      // quick check
            return true;
        if (obj == null || getClass() != obj.getClass())
            return false;
        MessageFormat other = (MessageFormat) obj;
        return Utility.objectEquals(ulocale, other.ulocale)
                && Utility.objectEquals(msgPattern, other.msgPattern)
                && Utility.objectEquals(cachedFormatters, other.cachedFormatters)
                && Utility.objectEquals(customFormatArgStarts, other.customFormatArgStarts);
        // Note: It might suffice to only compare custom formatters
        // rather than all formatters.
    }

    /**
     * {@inheritDoc}
     * @stable ICU 3.0
     */
    @Override
    public int hashCode() {
        return msgPattern.getPatternString().hashCode(); // enough for reasonable distribution
    }

    /**
     * Defines constants that are used as attribute keys in the
     * <code>AttributedCharacterIterator</code> returned
     * from <code>MessageFormat.formatToCharacterIterator</code>.
     *
     * @stable ICU 3.8
     */
    public static class Field extends Format.Field {

        private static final long serialVersionUID = 7510380454602616157L;

        /**
         * Create a <code>Field</code> with the specified name.
         *
         * @param name The name of the attribute
         *
         * @stable ICU 3.8
         */
        protected Field(String name) {
            super(name);
        }

        /**
         * Resolves instances being deserialized to the predefined constants.
         *
         * @return resolved MessageFormat.Field constant
         * @throws InvalidObjectException if the constant could not be resolved.
         *
         * @stable ICU 3.8
         */
        protected Object readResolve() throws InvalidObjectException {
            if (this.getClass() != MessageFormat.Field.class) {
                throw new InvalidObjectException(
                    "A subclass of MessageFormat.Field must implement readResolve.");
            }
            if (this.getName().equals(ARGUMENT.getName())) {
                return ARGUMENT;
            } else {
                throw new InvalidObjectException("Unknown attribute name.");
            }
        }

        /**
         * Constant identifying a portion of a message that was generated
         * from an argument passed into <code>formatToCharacterIterator</code>.
         * The value associated with the key will be an <code>Integer</code>
         * indicating the index in the <code>arguments</code> array of the
         * argument from which the text was generated.
         *
         * @stable ICU 3.8
         */
        public static final Field ARGUMENT = new Field("message argument field");
    }

    // ===========================privates============================

    // *Important*: All fields must be declared *transient* so that we can fully
    // control serialization!
    // See for example Joshua Bloch's "Effective Java", chapter 10 Serialization.

    /**
     * The locale to use for formatting numbers and dates.
     */
    private transient ULocale ulocale;

    /**
     * The MessagePattern which contains the parsed structure of the pattern string.
     */
    private transient MessagePattern msgPattern;
    /**
     * Cached formatters so we can just use them whenever needed instead of creating
     * them from scratch every time.
     */
    private transient Map<Integer, Format> cachedFormatters;
    /**
     * Set of ARG_START part indexes where custom, user-provided Format objects
     * have been set via setFormat() or similar API.
     */
    private transient Set<Integer> customFormatArgStarts;

    /**
     * Stock formatters. Those are used when a format is not explicitly mentioned in
     * the message. The format is inferred from the argument.
     */
    private transient Format stockDateFormatter;
    private transient Format stockNumberFormatter;

    private transient PluralSelectorProvider pluralProvider;
    private transient PluralSelectorProvider ordinalProvider;

    // *Important*: All fields must be declared *transient*.
    // See the longer comment above ulocale.

    /**
     * Formats the arguments and writes the result into the
     * AppendableWrapper, updates the field position.
     *
     * <p>Exactly one of args and argsMap must be null, the other non-null.
     *
     * @param msgStart      Index to msgPattern part to start formatting from.
     * @param pluralNumber  Zero except when formatting a plural argument sub-message
     *                      where a '#' is replaced by the format string for this number.
     * @param args          The formattable objects array. Non-null iff numbered values are used.
     * @param argsMap       The key-value map of formattable objects. Non-null iff named values are used.
     * @param dest          Output parameter to receive the result.
     *                      The result (string & attributes) is appended to existing contents.
     * @param fp            Field position status.
     */
    private void format(int msgStart, double pluralNumber,
                        Object[] args, Map<String, Object> argsMap,
                        AppendableWrapper dest, FieldPosition fp) {
        String msgString=msgPattern.getPatternString();
        int prevIndex=msgPattern.getPart(msgStart).getLimit();
        for(int i=msgStart+1;; ++i) {
            Part part=msgPattern.getPart(i);
            Part.Type type=part.getType();
            int index=part.getIndex();
            dest.append(msgString, prevIndex, index);
            if(type==Part.Type.MSG_LIMIT) {
                return;
            }
            prevIndex=part.getLimit();
            if(type==Part.Type.REPLACE_NUMBER) {
                if (stockNumberFormatter == null) {
                    stockNumberFormatter = NumberFormat.getInstance(ulocale);
                }
                dest.formatAndAppend(stockNumberFormatter, pluralNumber);
                continue;
            }
            if(type!=Part.Type.ARG_START) {
                continue;
            }
            int argLimit=msgPattern.getLimitPartIndex(i);
            ArgType argType=part.getArgType();
            part=msgPattern.getPart(++i);
            Object arg;
            String noArg=null;
            Object argId=null;
            if(args!=null) {
                int argNumber=part.getValue();  // ARG_NUMBER
                if (dest.attributes != null) {
                    // We only need argId if we add it into the attributes.
                    argId = Integer.valueOf(argNumber);
                }
                if(0<=argNumber && argNumber<args.length) {
                    arg=args[argNumber];
                } else {
                    arg=null;
                    noArg="{"+argNumber+"}";
                }
            } else {
                String key;
                if(part.getType()==MessagePattern.Part.Type.ARG_NAME) {
                    key=msgPattern.getSubstring(part);
                } else /* ARG_NUMBER */ {
                    key=Integer.toString(part.getValue());
                }
                argId = key;
                if(argsMap!=null && argsMap.containsKey(key)) {
                    arg=argsMap.get(key);
                } else {
                    arg=null;
                    noArg="{"+key+"}";
                }
            }
            ++i;
            int prevDestLength=dest.length;
            Format formatter = null;
            if (noArg != null) {
                dest.append(noArg);
            } else if (arg == null) {
                dest.append("null");
            } else if(cachedFormatters!=null && (formatter=cachedFormatters.get(i - 2))!=null) {
                // Handles all ArgType.SIMPLE, and formatters from setFormat() and its siblings.
                if (    formatter instanceof ChoiceFormat ||
                        formatter instanceof PluralFormat ||
                        formatter instanceof SelectFormat) {
                    // We only handle nested formats here if they were provided via setFormat() or its siblings.
                    // Otherwise they are not cached and instead handled below according to argType.
                    String subMsgString = formatter.format(arg);
                    if (subMsgString.indexOf('{') >= 0 ||
                            (subMsgString.indexOf('\'') >= 0 && !msgPattern.jdkAposMode())) {
                        MessageFormat subMsgFormat = new MessageFormat(subMsgString, ulocale);
                        subMsgFormat.format(0, 0, args, argsMap, dest, null);
                    } else if (dest.attributes == null) {
                        dest.append(subMsgString);
                    } else {
                        // This formats the argument twice, once above to get the subMsgString
                        // and then once more here.
                        // It only happens in formatToCharacterIterator()
                        // on a complex Format set via setFormat(),
                        // and only when the selected subMsgString does not need further formatting.
                        // This imitates ICU 4.6 behavior.
                        dest.formatAndAppend(formatter, arg);
                    }
                } else {
                    dest.formatAndAppend(formatter, arg);
                }
            } else if(
                    argType==ArgType.NONE ||
                    (cachedFormatters!=null && cachedFormatters.containsKey(i - 2))) {
                // ArgType.NONE, or
                // any argument which got reset to null via setFormat() or its siblings.
                if (arg instanceof Number) {
                    // format number if can
                    if (stockNumberFormatter == null) {
                        stockNumberFormatter = NumberFormat.getInstance(ulocale);
                    }
                    dest.formatAndAppend(stockNumberFormatter, arg);
                 } else if (arg instanceof Date) {
                    // format a Date if can
                    if (stockDateFormatter == null) {
                        stockDateFormatter = DateFormat.getDateTimeInstance(
                                DateFormat.SHORT, DateFormat.SHORT, ulocale);//fix
                    }
                    dest.formatAndAppend(stockDateFormatter, arg);
                } else {
                    dest.append(arg.toString());
                }
            } else if(argType==ArgType.CHOICE) {
                if (!(arg instanceof Number)) {
                    throw new IllegalArgumentException("'" + arg + "' is not a Number");
                }
                double number = ((Number)arg).doubleValue();
                int subMsgStart=findChoiceSubMessage(msgPattern, i, number);
                formatComplexSubMessage(subMsgStart, 0, args, argsMap, dest);
            } else if(argType.hasPluralStyle()) {
                if (!(arg instanceof Number)) {
                    throw new IllegalArgumentException("'" + arg + "' is not a Number");
                }
                double number = ((Number)arg).doubleValue();
                PluralSelector selector;
                if(argType == ArgType.PLURAL) {
                    if (pluralProvider == null) {
                        pluralProvider = new PluralSelectorProvider(ulocale, PluralType.CARDINAL);
                    }
                    selector = pluralProvider;
                } else {
                    if (ordinalProvider == null) {
                        ordinalProvider = new PluralSelectorProvider(ulocale, PluralType.ORDINAL);
                    }
                    selector = ordinalProvider;
                }
                int subMsgStart=PluralFormat.findSubMessage(msgPattern, i, selector, number);
                double offset=msgPattern.getPluralOffset(i);
                formatComplexSubMessage(subMsgStart, number-offset, args, argsMap, dest);
            } else if(argType==ArgType.SELECT) {
                int subMsgStart=SelectFormat.findSubMessage(msgPattern, i, arg.toString());
                formatComplexSubMessage(subMsgStart, 0, args, argsMap, dest);
            } else {
                // This should never happen.
                throw new IllegalStateException("unexpected argType "+argType);
            }
            fp = updateMetaData(dest, prevDestLength, fp, argId);
            prevIndex=msgPattern.getPart(argLimit).getLimit();
            i=argLimit;
        }
    }

    private void formatComplexSubMessage(
            int msgStart, double pluralNumber,
            Object[] args, Map<String, Object> argsMap,
            AppendableWrapper dest) {
        if (!msgPattern.jdkAposMode()) {
            format(msgStart, pluralNumber, args, argsMap, dest, null);
            return;
        }
        // JDK compatibility mode: (see JDK MessageFormat.format() API docs)
        // - remove SKIP_SYNTAX; that is, remove half of the apostrophes
        // - if the result string contains an open curly brace '{' then
        //   instantiate a temporary MessageFormat object and format again;
        //   otherwise just append the result string
        String msgString = msgPattern.getPatternString();
        String subMsgString;
        StringBuilder sb = null;
        int prevIndex = msgPattern.getPart(msgStart).getLimit();
        for (int i = msgStart;;) {
            Part part = msgPattern.getPart(++i);
            Part.Type type = part.getType();
            int index = part.getIndex();
            if (type == Part.Type.MSG_LIMIT) {
                if (sb == null) {
                    subMsgString = msgString.substring(prevIndex, index);
                } else {
                    subMsgString = sb.append(msgString, prevIndex, index).toString();
                }
                break;
            } else if (type == Part.Type.REPLACE_NUMBER || type == Part.Type.SKIP_SYNTAX) {
                if (sb == null) {
                    sb = new StringBuilder();
                }
                sb.append(msgString, prevIndex, index);
                if (type == Part.Type.REPLACE_NUMBER) {
                    if (stockNumberFormatter == null) {
                        stockNumberFormatter = NumberFormat.getInstance(ulocale);
                    }
                    sb.append(stockNumberFormatter.format(pluralNumber));
                }
                prevIndex = part.getLimit();
            } else if (type == Part.Type.ARG_START) {
                if (sb == null) {
                    sb = new StringBuilder();
                }
                sb.append(msgString, prevIndex, index);
                prevIndex = index;
                i = msgPattern.getLimitPartIndex(i);
                index = msgPattern.getPart(i).getLimit();
                MessagePattern.appendReducedApostrophes(msgString, prevIndex, index, sb);
                prevIndex = index;
            }
        }
        if (subMsgString.indexOf('{') >= 0) {
            MessageFormat subMsgFormat = new MessageFormat("", ulocale);
            subMsgFormat.applyPattern(subMsgString, MessagePattern.ApostropheMode.DOUBLE_REQUIRED);
            subMsgFormat.format(0, 0, args, argsMap, dest, null);
        } else {
            dest.append(subMsgString);
        }
    }

    /**
     * Read as much literal string from the pattern string as possible. This stops
     * as soon as it finds an argument, or it reaches the end of the string.
     * @param from Index in the pattern string to start from.
     * @return A substring from the pattern string representing the longest possible
     *         substring with no arguments. 
     */
    private String getLiteralStringUntilNextArgument(int from) {
        StringBuilder b = new StringBuilder();
        String msgString=msgPattern.getPatternString();
        int prevIndex=msgPattern.getPart(from).getLimit();
        for(int i=from+1;; ++i) {
            Part part=msgPattern.getPart(i);
            Part.Type type=part.getType();
            int index=part.getIndex();
            b.append(msgString, prevIndex, index);
            if(type==Part.Type.ARG_START || type==Part.Type.MSG_LIMIT) {
                return b.toString();
            }
            assert type==Part.Type.SKIP_SYNTAX || type==Part.Type.INSERT_CHAR :
                    "Unexpected Part "+part+" in parsed message.";
            prevIndex=part.getLimit();
        }
    }

    private FieldPosition updateMetaData(AppendableWrapper dest, int prevLength,
                                         FieldPosition fp, Object argId) {
        if (dest.attributes != null && prevLength < dest.length) {
            dest.attributes.add(new AttributeAndPosition(argId, prevLength, dest.length));
        }
        if (fp != null && Field.ARGUMENT.equals(fp.getFieldAttribute())) {
            fp.setBeginIndex(prevLength);
            fp.setEndIndex(dest.length);
            return null;
        }
        return fp;
    }

    // This lives here because ICU4J does not have its own ChoiceFormat class.
    /**
     * Finds the ChoiceFormat sub-message for the given number.
     * @param pattern A MessagePattern.
     * @param partIndex the index of the first ChoiceFormat argument style part.
     * @param number a number to be mapped to one of the ChoiceFormat argument's intervals
     * @return the sub-message start part index.
     */
    private static int findChoiceSubMessage(MessagePattern pattern, int partIndex, double number) {
        int count=pattern.countParts();
        int msgStart;
        // Iterate over (ARG_INT|DOUBLE, ARG_SELECTOR, message) tuples
        // until ARG_LIMIT or end of choice-only pattern.
        // Ignore the first number and selector and start the loop on the first message.
        partIndex+=2;
        for(;;) {
            // Skip but remember the current sub-message.
            msgStart=partIndex;
            partIndex=pattern.getLimitPartIndex(partIndex);
            if(++partIndex>=count) {
                // Reached the end of the choice-only pattern.
                // Return with the last sub-message.
                break;
            }
            Part part=pattern.getPart(partIndex++);
            Part.Type type=part.getType();
            if(type==Part.Type.ARG_LIMIT) {
                // Reached the end of the ChoiceFormat style.
                // Return with the last sub-message.
                break;
            }
            // part is an ARG_INT or ARG_DOUBLE
            assert type.hasNumericValue();
            double boundary=pattern.getNumericValue(part);
            // Fetch the ARG_SELECTOR character.
            int selectorIndex=pattern.getPatternIndex(partIndex++);
            char boundaryChar=pattern.getPatternString().charAt(selectorIndex);
            if(boundaryChar=='<' ? !(number>boundary) : !(number>=boundary)) {
                // The number is in the interval between the previous boundary and the current one.
                // Return with the sub-message between them.
                // The !(a>b) and !(a>=b) comparisons are equivalent to
                // (a<=b) and (a<b) except they "catch" NaN.
                break;
            }
        }
        return msgStart;
    }

    // Ported from C++ ChoiceFormat::parse().
    private static double parseChoiceArgument(
            MessagePattern pattern, int partIndex,
            String source, ParsePosition pos) {
        // find the best number (defined as the one with the longest parse)
        int start = pos.getIndex();
        int furthest = start;
        double bestNumber = Double.NaN;
        double tempNumber = 0.0;
        while (pattern.getPartType(partIndex) != Part.Type.ARG_LIMIT) {
            tempNumber = pattern.getNumericValue(pattern.getPart(partIndex));
            partIndex += 2;  // skip the numeric part and ignore the ARG_SELECTOR
            int msgLimit = pattern.getLimitPartIndex(partIndex);
            int len = matchStringUntilLimitPart(pattern, partIndex, msgLimit, source, start);
            if (len >= 0) {
                int newIndex = start + len;
                if (newIndex > furthest) {
                    furthest = newIndex;
                    bestNumber = tempNumber;
                    if (furthest == source.length()) {
                        break;
                    }
                }
            }
            partIndex = msgLimit + 1;
        }
        if (furthest == start) {
            pos.setErrorIndex(start);
        } else {
            pos.setIndex(furthest);
        }
        return bestNumber;
    }

    /**
     * Matches the pattern string from the end of the partIndex to
     * the beginning of the limitPartIndex,
     * including all syntax except SKIP_SYNTAX,
     * against the source string starting at sourceOffset.
     * If they match, returns the length of the source string match.
     * Otherwise returns -1.
     */
    private static int matchStringUntilLimitPart(
            MessagePattern pattern, int partIndex, int limitPartIndex,
            String source, int sourceOffset) {
        int matchingSourceLength = 0;
        String msgString = pattern.getPatternString();
        int prevIndex = pattern.getPart(partIndex).getLimit();
        for (;;) {
            Part part = pattern.getPart(++partIndex);
            if (partIndex == limitPartIndex || part.getType() == Part.Type.SKIP_SYNTAX) {
                int index = part.getIndex();
                int length = index - prevIndex;
                if (length != 0 && !source.regionMatches(sourceOffset, msgString, prevIndex, length)) {
                    return -1;  // mismatch
                }
                matchingSourceLength += length;
                if (partIndex == limitPartIndex) {
                    return matchingSourceLength;
                }
                prevIndex = part.getLimit();  // SKIP_SYNTAX
            }
        }
    }

    /**
     * This provider helps defer instantiation of a PluralRules object
     * until we actually need to select a keyword.
     * For example, if the number matches an explicit-value selector like "=1"
     * we do not need any PluralRules.
     */
    private static final class PluralSelectorProvider implements PluralFormat.PluralSelector {
        public PluralSelectorProvider(ULocale loc, PluralType type) {
            locale=loc;
            this.type=type;
        }
        public String select(double number) {
            if(rules == null) {
                rules = PluralRules.forLocale(locale, type);
            }
            return rules.select(number);
        }
        private ULocale locale;
        private PluralRules rules;
        private PluralType type;
    }

    @SuppressWarnings("unchecked")
    private void format(Object arguments, AppendableWrapper result, FieldPosition fp) {
        if ((arguments == null || arguments instanceof Map)) {
            format(null, (Map<String, Object>)arguments, result, fp);
        } else {
            format((Object[])arguments, null, result, fp);
        }
    }

    /**
     * Internal routine used by format.
     *
     * @throws IllegalArgumentException if an argument in the
     *         <code>arguments</code> map is not of the type
     *         expected by the format element(s) that use it.
     */
    private void format(Object[] arguments, Map<String, Object> argsMap,
                        AppendableWrapper dest, FieldPosition fp) {
        if (arguments != null && msgPattern.hasNamedArguments()) {
            throw new IllegalArgumentException(
                "This method is not available in MessageFormat objects " +
                "that use alphanumeric argument names.");
        }
        format(0, 0, arguments, argsMap, dest, fp);
    }

    private void resetPattern() {
        if (msgPattern != null) {
            msgPattern.clear();
        }
        if (cachedFormatters != null) {
            cachedFormatters.clear();
        }
        customFormatArgStarts = null;
    }

    private static final String[] typeList =
        { "number", "date", "time", "spellout", "ordinal", "duration" };
    private static final int
        TYPE_NUMBER = 0,
        TYPE_DATE = 1,
        TYPE_TIME = 2,
        TYPE_SPELLOUT = 3,
        TYPE_ORDINAL = 4,
        TYPE_DURATION = 5;

    private static final String[] modifierList =
        {"", "currency", "percent", "integer"};

    private static final int
        MODIFIER_EMPTY = 0,
        MODIFIER_CURRENCY = 1,
        MODIFIER_PERCENT = 2,
        MODIFIER_INTEGER = 3;

    private static final String[] dateModifierList =
        {"", "short", "medium", "long", "full"};

    private static final int
        DATE_MODIFIER_EMPTY = 0,
        DATE_MODIFIER_SHORT = 1,
        DATE_MODIFIER_MEDIUM = 2,
        DATE_MODIFIER_LONG = 3,
        DATE_MODIFIER_FULL = 4;

    // Creates an appropriate Format object for the type and style passed.
    // Both arguments cannot be null.
    private Format createAppropriateFormat(String type, String style) {
        Format newFormat = null;
        int subformatType  = findKeyword(type, typeList);
        switch (subformatType){
        case TYPE_NUMBER:
            switch (findKeyword(style, modifierList)) {
            case MODIFIER_EMPTY:
                newFormat = NumberFormat.getInstance(ulocale);
                break;
            case MODIFIER_CURRENCY:
                newFormat = NumberFormat.getCurrencyInstance(ulocale);
                break;
            case MODIFIER_PERCENT:
                newFormat = NumberFormat.getPercentInstance(ulocale);
                break;
            case MODIFIER_INTEGER:
                newFormat = NumberFormat.getIntegerInstance(ulocale);
                break;
            default: // pattern
                newFormat = new DecimalFormat(style,
                        new DecimalFormatSymbols(ulocale));
                break;
            }
            break;
        case TYPE_DATE:
            switch (findKeyword(style, dateModifierList)) {
            case DATE_MODIFIER_EMPTY:
                newFormat = DateFormat.getDateInstance(DateFormat.DEFAULT, ulocale);
                break;
            case DATE_MODIFIER_SHORT:
                newFormat = DateFormat.getDateInstance(DateFormat.SHORT, ulocale);
                break;
            case DATE_MODIFIER_MEDIUM:
                newFormat = DateFormat.getDateInstance(DateFormat.DEFAULT, ulocale);
                break;
            case DATE_MODIFIER_LONG:
                newFormat = DateFormat.getDateInstance(DateFormat.LONG, ulocale);
                break;
            case DATE_MODIFIER_FULL:
                newFormat = DateFormat.getDateInstance(DateFormat.FULL, ulocale);
                break;
            default:
                newFormat = new SimpleDateFormat(style, ulocale);
                break;
            }
            break;
        case TYPE_TIME:
            switch (findKeyword(style, dateModifierList)) {
            case DATE_MODIFIER_EMPTY:
                newFormat = DateFormat.getTimeInstance(DateFormat.DEFAULT, ulocale);
                break;
            case DATE_MODIFIER_SHORT:
                newFormat = DateFormat.getTimeInstance(DateFormat.SHORT, ulocale);
                break;
            case DATE_MODIFIER_MEDIUM:
                newFormat = DateFormat.getTimeInstance(DateFormat.DEFAULT, ulocale);
                break;
            case DATE_MODIFIER_LONG:
                newFormat = DateFormat.getTimeInstance(DateFormat.LONG, ulocale);
                break;
            case DATE_MODIFIER_FULL:
                newFormat = DateFormat.getTimeInstance(DateFormat.FULL, ulocale);
                break;
            default:
                newFormat = new SimpleDateFormat(style, ulocale);
                break;
            }
            break;
        case TYPE_SPELLOUT:
            {
                RuleBasedNumberFormat rbnf = new RuleBasedNumberFormat(ulocale,
                        RuleBasedNumberFormat.SPELLOUT);
                String ruleset = style.trim();
                if (ruleset.length() != 0) {
                    try {
                        rbnf.setDefaultRuleSet(ruleset);
                    }
                    catch (Exception e) {
                        // warn invalid ruleset
                    }
                }
                newFormat = rbnf;
            }
            break;
        case TYPE_ORDINAL:
            {
                RuleBasedNumberFormat rbnf = new RuleBasedNumberFormat(ulocale,
                        RuleBasedNumberFormat.ORDINAL);
                String ruleset = style.trim();
                if (ruleset.length() != 0) {
                    try {
                        rbnf.setDefaultRuleSet(ruleset);
                    }
                    catch (Exception e) {
                        // warn invalid ruleset
                    }
                }
                newFormat = rbnf;
            }
            break;
        case TYPE_DURATION:
            {
                RuleBasedNumberFormat rbnf = new RuleBasedNumberFormat(ulocale,
                        RuleBasedNumberFormat.DURATION);
                String ruleset = style.trim();
                if (ruleset.length() != 0) {
                    try {
                        rbnf.setDefaultRuleSet(ruleset);
                    }
                    catch (Exception e) {
                        // warn invalid ruleset
                    }
                }
                newFormat = rbnf;
            }
            break;
        default:
            throw new IllegalArgumentException("Unknown format type \"" + type + "\"");
        }
        return newFormat;
    }

    private static final Locale rootLocale = new Locale("");  // Locale.ROOT only @since 1.6

    private static final int findKeyword(String s, String[] list) {
        s = PatternProps.trimWhiteSpace(s).toLowerCase(rootLocale);
        for (int i = 0; i < list.length; ++i) {
            if (s.equals(list[i]))
                return i;
        }
        return -1;
    }

    /**
     * Custom serialization, new in ICU 4.8.
     * We do not want to use default serialization because we only have a small
     * amount of persistent state which is better expressed explicitly
     * rather than via writing field objects.
     * @param out The output stream.
     * @serialData Writes the locale as a BCP 47 language tag string,
     * the MessagePattern.ApostropheMode as an object,
     * and the pattern string (null if none was applied).
     * Followed by an int with the number of (int formatIndex, Object formatter) pairs,
     * and that many such pairs, corresponding to previous setFormat() calls for custom formats.
     * Followed by an int with the number of (int, Object) pairs,
     * and that many such pairs, for future (post-ICU 4.8) extension of the serialization format.
     */
    private void writeObject(java.io.ObjectOutputStream out) throws IOException {
        out.defaultWriteObject();
        // ICU 4.8 custom serialization.
        // locale as a BCP 47 language tag
        out.writeObject(ulocale.toLanguageTag());
        // ApostropheMode
        if (msgPattern == null) {
            msgPattern = new MessagePattern();
        }
        out.writeObject(msgPattern.getApostropheMode());
        // message pattern string
        out.writeObject(msgPattern.getPatternString());
        // custom formatters
        if (customFormatArgStarts == null || customFormatArgStarts.isEmpty()) {
            out.writeInt(0);
        } else {
            out.writeInt(customFormatArgStarts.size());
            int formatIndex = 0;
            for (int partIndex = 0; (partIndex = nextTopLevelArgStart(partIndex)) >= 0;) {
                if (customFormatArgStarts.contains(partIndex)) {
                    out.writeInt(formatIndex);
                    out.writeObject(cachedFormatters.get(partIndex));
                }
                ++formatIndex;
            }
        }
        // number of future (int, Object) pairs
        out.writeInt(0);
    }

    /**
     * Custom deserialization, new in ICU 4.8. See comments on writeObject().
     * @throws InvalidObjectException if the objects read from the stream is invalid.
     */
    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        in.defaultReadObject();
        // ICU 4.8 custom deserialization.
        String languageTag = (String)in.readObject();
        ulocale = ULocale.forLanguageTag(languageTag);
        MessagePattern.ApostropheMode aposMode = (MessagePattern.ApostropheMode)in.readObject();
        if (msgPattern == null || aposMode != msgPattern.getApostropheMode()) {
            msgPattern = new MessagePattern(aposMode);
        }
        String msg = (String)in.readObject();
        if (msg != null) {
            applyPattern(msg);
        }
        // custom formatters
        for (int numFormatters = in.readInt(); numFormatters > 0; --numFormatters) {
            int formatIndex = in.readInt();
            Format formatter = (Format)in.readObject();
            setFormat(formatIndex, formatter);
        }
        // skip future (int, Object) pairs
        for (int numPairs = in.readInt(); numPairs > 0; --numPairs) {
            in.readInt();
            in.readObject();
        }
    }

    private void cacheExplicitFormats() {
        if (cachedFormatters != null) {
            cachedFormatters.clear();
        }
        customFormatArgStarts = null;
        // The last two "parts" can at most be ARG_LIMIT and MSG_LIMIT
        // which we need not examine.
        int limit = msgPattern.countParts() - 2;
        // This loop starts at part index 1 because we do need to examine
        // ARG_START parts. (But we can ignore the MSG_START.)
        for(int i=1; i < limit; ++i) {
            Part part = msgPattern.getPart(i);
            if(part.getType()!=Part.Type.ARG_START) {
                continue;
            }
            ArgType argType=part.getArgType();
            if(argType != ArgType.SIMPLE) {
                continue;
            }
            int index = i;
            i += 2;
            String explicitType = msgPattern.getSubstring(msgPattern.getPart(i++));
            String style = "";
            if ((part = msgPattern.getPart(i)).getType() == MessagePattern.Part.Type.ARG_STYLE) {
                style = msgPattern.getSubstring(part);
                ++i;
            }
            Format formatter = createAppropriateFormat(explicitType, style);
            setArgStartFormat(index, formatter);
        }
    }

    /**
     * Sets a formatter for a MessagePattern ARG_START part index.
     */
    private void setArgStartFormat(int argStart, Format formatter) {
        if (cachedFormatters == null) {
            cachedFormatters = new HashMap<Integer, Format>();
        }
        cachedFormatters.put(argStart, formatter);
    }

    /**
     * Sets a custom formatter for a MessagePattern ARG_START part index.
     * "Custom" formatters are provided by the user via setFormat() or similar APIs.
     */
    private void setCustomArgStartFormat(int argStart, Format formatter) {
        setArgStartFormat(argStart, formatter);
        if (customFormatArgStarts == null) {
            customFormatArgStarts = new HashSet<Integer>();
        }
        customFormatArgStarts.add(argStart);
    }

    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;

    /**
     * {@icu} Converts an 'apostrophe-friendly' pattern into a standard
     * pattern.
     * <em>This is obsolete for ICU 4.8 and higher MessageFormat pattern strings.</em>
     * It can still be useful together with the JDK MessageFormat.
     *
     * <p>See the class description for more about apostrophes and quoting,
     * and differences between ICU and the JDK.
     *
     * <p>The JDK MessageFormat and ICU 4.6 and earlier MessageFormat
     * treat all ASCII 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.
     *
     * <p><b>Note</b>: This method only works on top-level messageText,
     * not messageText nested inside a complexArg.
     *
     * @param pattern the 'apostrophe-friendly' pattern to convert
     * @return the standard equivalent of the original pattern
     * @stable ICU 3.4
     */
    public static String autoQuoteApostrophe(String pattern) {
        StringBuilder buf = new StringBuilder(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;
            ///CLOVER:OFF
            default: // Never happens.
                break;
            ///CLOVER:ON
            }
            buf.append(c);
        }
        // End of scan
        if (state == STATE_SINGLE_QUOTE || state == STATE_IN_QUOTE) {
            buf.append(SINGLE_QUOTE);
        }
        return new String(buf);
    }

    /**
     * Convenience wrapper for Appendable, tracks the result string length.
     * Also, Appendable throws IOException, and we turn that into a RuntimeException
     * so that we need no throws clauses.
     */
    private static final class AppendableWrapper {
        public AppendableWrapper(StringBuilder sb) {
            app = sb;
            length = sb.length();
            attributes = null;
        }

        public AppendableWrapper(StringBuffer sb) {
            app = sb;
            length = sb.length();
            attributes = null;
        }

        public void useAttributes() {
            attributes = new ArrayList<AttributeAndPosition>();
        }

        public void append(CharSequence s) {
            try {
                app.append(s);
                length += s.length();
            } catch(IOException e) {
                throw new RuntimeException(e);
            }
        }

        public void append(CharSequence s, int start, int limit) {
            try {
                app.append(s, start, limit);
                length += limit - start;
            } catch(IOException e) {
                throw new RuntimeException(e);
            }
        }

        public void append(CharacterIterator iterator) {
            length += append(app, iterator);
        }

        public static int append(Appendable result, CharacterIterator iterator) {
            try {
                int start = iterator.getBeginIndex();
                int limit = iterator.getEndIndex();
                int length = limit - start;
                if (start < limit) {
                    result.append(iterator.first());
                    while (++start < limit) {
                        result.append(iterator.next());
                    }
                }
                return length;
            } catch(IOException e) {
                throw new RuntimeException(e);
            }
        }

        public void formatAndAppend(Format formatter, Object arg) {
            if (attributes == null) {
                append(formatter.format(arg));
            } else {
                AttributedCharacterIterator formattedArg = formatter.formatToCharacterIterator(arg);
                int prevLength = length;
                append(formattedArg);
                // Copy all of the attributes from formattedArg to our attributes list.
                formattedArg.first();
                int start = formattedArg.getIndex();  // Should be 0 but might not be.
                int limit = formattedArg.getEndIndex();  // == start + length - prevLength
                int offset = prevLength - start;  // Adjust attribute indexes for the result string.
                while (start < limit) {
                    Map<Attribute, Object> map = formattedArg.getAttributes();
                    int runLimit = formattedArg.getRunLimit();
                    if (map.size() != 0) {
                        for (Map.Entry<Attribute, Object> entry : map.entrySet()) {
                           attributes.add(
                               new AttributeAndPosition(
                                   entry.getKey(), entry.getValue(),
                                   offset + start, offset + runLimit));
                        }
                    }
                    start = runLimit;
                    formattedArg.setIndex(start);
                }
            }
        }

        private Appendable app;
        private int length;
        private List<AttributeAndPosition> attributes;
    }

    private static final class AttributeAndPosition {
        /**
         * Defaults the field to Field.ARGUMENT.
         */
        public AttributeAndPosition(Object fieldValue, int startIndex, int limitIndex) {
            init(Field.ARGUMENT, fieldValue, startIndex, limitIndex);
        }

        public AttributeAndPosition(Attribute field, Object fieldValue, int startIndex, int limitIndex) {
            init(field, fieldValue, startIndex, limitIndex);
        }

        public void init(Attribute field, Object fieldValue, int startIndex, int limitIndex) {
            key = field;
            value = fieldValue;
            start = startIndex;
            limit = limitIndex;
        }

        private Attribute key;
        private Object value;
        private int start;
        private int limit;
    }
}
