/*
**********************************************************************
* Copyright (c) 2004-2016, 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.PluralRules.FixedDecimal;
import com.ibm.icu.text.PluralRules.PluralType;
import com.ibm.icu.util.ICUUncheckedIOException;
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).
 *
 * <h3><a name="patterns">Patterns and Their Interpretation</a></h3>
 *
 * <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.
 *
 * <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())</code>
 *    <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())</code>
 *    <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>
 *
 * <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.
        stockDateFormatter = null;
        stockNumberFormatter = 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.
     *
     * <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 : (DateFormat) stockDateFormatter.clone();
        other.stockNumberFormatter =
                stockNumberFormatter == null ? null : (NumberFormat) 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 DateFormat stockDateFormatter;
    private transient NumberFormat stockNumberFormatter;

    private transient PluralSelectorProvider pluralProvider;
    private transient PluralSelectorProvider ordinalProvider;

    private DateFormat getStockDateFormatter() {
        if (stockDateFormatter == null) {
            stockDateFormatter = DateFormat.getDateTimeInstance(
                    DateFormat.SHORT, DateFormat.SHORT, ulocale);//fix
        }
        return stockDateFormatter;
    }
    private NumberFormat getStockNumberFormatter() {
        if (stockNumberFormatter == null) {
            stockNumberFormatter = NumberFormat.getInstance(ulocale);
        }
        return stockNumberFormatter;
    }

    // *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  null 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, PluralSelectorContext 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(pluralNumber.forReplaceNumber) {
                    // number-offset was already formatted.
                    dest.formatAndAppend(pluralNumber.formatter,
                            pluralNumber.number, pluralNumber.numberString);
                } else {
                    dest.formatAndAppend(getStockNumberFormatter(), pluralNumber.number);
                }
                continue;
            }
            if(type!=Part.Type.ARG_START) {
                continue;
            }
            int argLimit=msgPattern.getLimitPartIndex(i);
            ArgType argType=part.getArgType();
            part=msgPattern.getPart(++i);
            Object arg;
            boolean noArg=false;
            Object argId=null;
            String argName=msgPattern.getSubstring(part);
            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=true;
                }
            } else {
                argId = argName;
                if(argsMap!=null && argsMap.containsKey(argName)) {
                    arg=argsMap.get(argName);
                } else {
                    arg=null;
                    noArg=true;
                }
            }
            ++i;
            int prevDestLength=dest.length;
            Format formatter = null;
            if (noArg) {
                dest.append("{"+argName+"}");
            } else if (arg == null) {
                dest.append("null");
            } else if(pluralNumber!=null && pluralNumber.numberArgIndex==(i-2)) {
                if(pluralNumber.offset == 0) {
                    // The number was already formatted with this formatter.
                    dest.formatAndAppend(pluralNumber.formatter, pluralNumber.number, pluralNumber.numberString);
                } else {
                    // Do not use the formatted (number-offset) string for a named argument
                    // that formats the number without subtracting the offset.
                    dest.formatAndAppend(pluralNumber.formatter, arg);
                }
            } 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, null, 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
                    dest.formatAndAppend(getStockNumberFormatter(), arg);
                 } else if (arg instanceof Date) {
                    // format a Date if can
                    dest.formatAndAppend(getStockDateFormatter(), 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, null, args, argsMap, dest);
            } else if(argType.hasPluralStyle()) {
                if (!(arg instanceof Number)) {
                    throw new IllegalArgumentException("'" + arg + "' is not a Number");
                }
                PluralSelectorProvider selector;
                if(argType == ArgType.PLURAL) {
                    if (pluralProvider == null) {
                        pluralProvider = new PluralSelectorProvider(this, PluralType.CARDINAL);
                    }
                    selector = pluralProvider;
                } else {
                    if (ordinalProvider == null) {
                        ordinalProvider = new PluralSelectorProvider(this, PluralType.ORDINAL);
                    }
                    selector = ordinalProvider;
                }
                Number number = (Number)arg;
                double offset=msgPattern.getPluralOffset(i);
                PluralSelectorContext context =
                        new PluralSelectorContext(i, argName, number, offset);
                int subMsgStart=PluralFormat.findSubMessage(
                        msgPattern, i, selector, context, number.doubleValue());
                formatComplexSubMessage(subMsgStart, context, args, argsMap, dest);
            } else if(argType==ArgType.SELECT) {
                int subMsgStart=SelectFormat.findSubMessage(msgPattern, i, arg.toString());
                formatComplexSubMessage(subMsgStart, null, 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, PluralSelectorContext 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(pluralNumber.forReplaceNumber) {
                        // number-offset was already formatted.
                        sb.append(pluralNumber.numberString);
                    } else {
                        sb.append(getStockNumberFormatter().format(pluralNumber.number));
                    }
                }
                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, null, 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
            }
        }
    }

    /**
     * Finds the "other" sub-message.
     * @param partIndex the index of the first PluralFormat argument style part.
     * @return the "other" sub-message start part index.
     */
    private int findOtherSubMessage(int partIndex) {
        int count=msgPattern.countParts();
        MessagePattern.Part part=msgPattern.getPart(partIndex);
        if(part.getType().hasNumericValue()) {
            ++partIndex;
        }
        // Iterate over (ARG_SELECTOR [ARG_INT|ARG_DOUBLE] message) tuples
        // until ARG_LIMIT or end of plural-only pattern.
        do {
            part=msgPattern.getPart(partIndex++);
            MessagePattern.Part.Type type=part.getType();
            if(type==MessagePattern.Part.Type.ARG_LIMIT) {
                break;
            }
            assert type==MessagePattern.Part.Type.ARG_SELECTOR;
            // part is an ARG_SELECTOR followed by an optional explicit value, and then a message
            if(msgPattern.partSubstringMatches(part, "other")) {
                return partIndex;
            }
            if(msgPattern.getPartType(partIndex).hasNumericValue()) {
                ++partIndex;  // skip the numeric-value part of "=1" etc.
            }
            partIndex=msgPattern.getLimitPartIndex(partIndex);
        } while(++partIndex<count);
        return 0;
    }

    /**
     * Returns the ARG_START index of the first occurrence of the plural number in a sub-message.
     * Returns -1 if it is a REPLACE_NUMBER.
     * Returns 0 if there is neither.
     */
    private int findFirstPluralNumberArg(int msgStart, String argName) {
        for(int i=msgStart+1;; ++i) {
            Part part=msgPattern.getPart(i);
            Part.Type type=part.getType();
            if(type==Part.Type.MSG_LIMIT) {
                return 0;
            }
            if(type==Part.Type.REPLACE_NUMBER) {
                return -1;
            }
            if(type==Part.Type.ARG_START) {
                ArgType argType=part.getArgType();
                if(argName.length()!=0 && (argType==ArgType.NONE || argType==ArgType.SIMPLE)) {
                    part=msgPattern.getPart(i+1);  // ARG_NUMBER or ARG_NAME
                    if(msgPattern.partSubstringMatches(part, argName)) {
                        return i;
                    }
                }
                i=msgPattern.getLimitPartIndex(i);
            }
        }
    }

    /**
     * Mutable input/output values for the PluralSelectorProvider.
     * Separate so that it is possible to make MessageFormat Freezable.
     */
    private static final class PluralSelectorContext {
        private PluralSelectorContext(int start, String name, Number num, double off) {
            startIndex = start;
            argName = name;
            // number needs to be set even when select() is not called.
            // Keep it as a Number/Formattable:
            // For format() methods, and to preserve information (e.g., BigDecimal).
            if(off == 0) {
                number = num;
            } else {
                number = num.doubleValue() - off;
            }
            offset = off;
        }
        @Override
        public String toString() {
            throw new AssertionError("PluralSelectorContext being formatted, rather than its number");
        }

        // Input values for plural selection with decimals.
        int startIndex;
        String argName;
        /** argument number - plural offset */
        Number number;
        double offset;
        // Output values for plural selection with decimals.
        /** -1 if REPLACE_NUMBER, 0 arg not found, >0 ARG_START index */
        int numberArgIndex;
        Format formatter;
        /** formatted argument number - plural offset */
        String numberString;
        /** true if number-offset was formatted with the stock number formatter */
        boolean forReplaceNumber;
    }

    /**
     * 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(MessageFormat mf, PluralType type) {
            msgFormat = mf;
            this.type = type;
        }
        public String select(Object ctx, double number) {
            if(rules == null) {
                rules = PluralRules.forLocale(msgFormat.ulocale, type);
            }
            // Select a sub-message according to how the number is formatted,
            // which is specified in the selected sub-message.
            // We avoid this circle by looking at how
            // the number is formatted in the "other" sub-message
            // which must always be present and usually contains the number.
            // Message authors should be consistent across sub-messages.
            PluralSelectorContext context = (PluralSelectorContext)ctx;
            int otherIndex = msgFormat.findOtherSubMessage(context.startIndex);
            context.numberArgIndex = msgFormat.findFirstPluralNumberArg(otherIndex, context.argName);
            if(context.numberArgIndex > 0 && msgFormat.cachedFormatters != null) {
                context.formatter = msgFormat.cachedFormatters.get(context.numberArgIndex);
            }
            if(context.formatter == null) {
                context.formatter = msgFormat.getStockNumberFormatter();
                context.forReplaceNumber = true;
            }
            assert context.number.doubleValue() == number;  // argument number minus the offset
            context.numberString = context.formatter.format(context.number);
            if(context.formatter instanceof DecimalFormat) {
                FixedDecimal dec = ((DecimalFormat)context.formatter).getFixedDecimal(number);
                return rules.select(dec);
            } else {
                return rules.select(number);
            }
        }
        private MessageFormat msgFormat;
        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, null, 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 {@link java.text.MessageFormat}.
     *
     * <p>See the class description for more about apostrophes and quoting,
     * and differences between ICU and {@link java.text.MessageFormat}.
     *
     * <p>{@link java.text.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 ICUUncheckedIOException(e);
            }
        }

        public void append(CharSequence s, int start, int limit) {
            try {
                app.append(s, start, limit);
                length += limit - start;
            } catch(IOException e) {
                throw new ICUUncheckedIOException(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 ICUUncheckedIOException(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);
                }
            }
        }

        public void formatAndAppend(Format formatter, Object arg, String argString) {
            if (attributes == null && argString != null) {
                append(argString);
            } else {
                formatAndAppend(formatter, arg);
            }
        }

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