/* GENERATED SOURCE. DO NOT MODIFY. */
/*
 **********************************************************************
 * Copyright (c) 2004-2015, International Business Machines
 * Corporation and others.  All Rights Reserved.
 **********************************************************************
 * Author: Alan Liu
 * Created: April 20, 2004
 * Since: ICU 3.0
 **********************************************************************
 */
package android.icu.text;

import java.io.Externalizable;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.io.ObjectStreamException;
import java.text.FieldPosition;
import java.text.ParsePosition;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.concurrent.ConcurrentHashMap;

import android.icu.impl.DontCareFieldPosition;
import android.icu.impl.ICUData;
import android.icu.impl.ICUResourceBundle;
import android.icu.impl.SimpleCache;
import android.icu.impl.SimplePatternFormatter;
import android.icu.math.BigDecimal;
import android.icu.text.PluralRules.Factory;
import android.icu.text.PluralRules.StandardPluralCategories;
import android.icu.util.Currency;
import android.icu.util.CurrencyAmount;
import android.icu.util.Measure;
import android.icu.util.MeasureUnit;
import android.icu.util.TimeZone;
import android.icu.util.ULocale;
import android.icu.util.ULocale.Category;
import android.icu.util.UResourceBundle;

// If you update the examples in the doc, don't forget to update MesaureUnitTest.TestExamplesInDocs too.
/**
 * A formatter for Measure objects.
 *
 * <p>To format a Measure object, first create a formatter
 * object using a MeasureFormat factory method.  Then use that
 * object's format or formatMeasures methods.
 * 
 * Here is sample code:
 * <pre>
 *      MeasureFormat fmtFr = MeasureFormat.getInstance(
 *              ULocale.FRENCH, FormatWidth.SHORT);
 *      Measure measure = new Measure(23, MeasureUnit.CELSIUS);
 *      
 *      // Output: 23 °C
 *      System.out.println(fmtFr.format(measure));
 *
 *      Measure measureF = new Measure(70, MeasureUnit.FAHRENHEIT);
 *
 *      // Output: 70 °F
 *      System.out.println(fmtFr.format(measureF));
 *     
 *      MeasureFormat fmtFrFull = MeasureFormat.getInstance(
 *              ULocale.FRENCH, FormatWidth.WIDE);
 *      // Output: 70 pieds et 5,3 pouces
 *      System.out.println(fmtFrFull.formatMeasures(
 *              new Measure(70, MeasureUnit.FOOT),
 *              new Measure(5.3, MeasureUnit.INCH)));
 *              
 *      // Output: 1 pied et 1 pouce
 *      System.out.println(fmtFrFull.formatMeasures(
 *              new Measure(1, MeasureUnit.FOOT),
 *              new Measure(1, MeasureUnit.INCH)));
 *  
 *      MeasureFormat fmtFrNarrow = MeasureFormat.getInstance(
                ULocale.FRENCH, FormatWidth.NARROW);
 *      // Output: 1′ 1″
 *      System.out.println(fmtFrNarrow.formatMeasures(
 *              new Measure(1, MeasureUnit.FOOT),
 *              new Measure(1, MeasureUnit.INCH)));
 *      
 *      
 *      MeasureFormat fmtEn = MeasureFormat.getInstance(ULocale.ENGLISH, FormatWidth.WIDE);
 *      
 *      // Output: 1 inch, 2 feet
 *      fmtEn.formatMeasures(
 *              new Measure(1, MeasureUnit.INCH),
 *              new Measure(2, MeasureUnit.FOOT));
 * </pre>
 * <p>
 * This class does not do conversions from one unit to another. It simply formats
 * whatever units it is given
 * <p>
 * This class is immutable and thread-safe so long as its deprecated subclass,
 * TimeUnitFormat, is never used. TimeUnitFormat is not thread-safe, and is
 * mutable. Although this class has existing subclasses, this class does not support new
 * sub-classes.   
 *
 * @see android.icu.text.UFormat
 * @author Alan Liu
 * @hide All android.icu classes are currently hidden
 */
public class MeasureFormat extends UFormat {


    // Generated by serialver from JDK 1.4.1_01
    static final long serialVersionUID = -7182021401701778240L;

    private final transient ImmutableNumberFormat numberFormat;

    private final transient FormatWidth formatWidth;

    // PluralRules is documented as being immutable which implies thread-safety.
    private final transient PluralRules rules;

    // Measure unit -> format width -> plural form -> pattern ("{0} meters")
    private final transient Map<MeasureUnit, EnumMap<FormatWidth, QuantityFormatter>> unitToStyleToCountToFormat;

    private final transient NumericFormatters numericFormatters;

    private final transient ImmutableNumberFormat currencyFormat;

    private final transient ImmutableNumberFormat integerFormat;

    private final transient Map<MeasureUnit, EnumMap<FormatWidth, SimplePatternFormatter>> unitToStyleToPerUnitPattern;
    
    private final transient EnumMap<FormatWidth, SimplePatternFormatter> styleToPerPattern;

    private static final SimpleCache<ULocale, MeasureFormatData> localeMeasureFormatData
    = new SimpleCache<ULocale, MeasureFormatData>();

    private static final SimpleCache<ULocale, NumericFormatters> localeToNumericDurationFormatters
    = new SimpleCache<ULocale,NumericFormatters>();

    private static final Map<MeasureUnit, Integer> hmsTo012 =
            new HashMap<MeasureUnit, Integer>();

    static {
        hmsTo012.put(MeasureUnit.HOUR, 0);
        hmsTo012.put(MeasureUnit.MINUTE, 1);
        hmsTo012.put(MeasureUnit.SECOND, 2);
    }

    // For serialization: sub-class types.
    private static final int MEASURE_FORMAT = 0;
    private static final int TIME_UNIT_FORMAT = 1;
    private static final int CURRENCY_FORMAT = 2;

    /**
     * Formatting width enum.
     */
    // Be sure to update MeasureUnitTest.TestSerialFormatWidthEnum
    // when adding an enum value.
    public enum FormatWidth {

        /**
         * Spell out everything.
         */
        WIDE("units", ListFormatter.Style.DURATION, NumberFormat.PLURALCURRENCYSTYLE), 

        /**
         * Abbreviate when possible.
         */
        SHORT("unitsShort", ListFormatter.Style.DURATION_SHORT, NumberFormat.ISOCURRENCYSTYLE), 

        /**
         * Brief. Use only a symbol for the unit when possible.
         */
        NARROW("unitsNarrow", ListFormatter.Style.DURATION_NARROW, NumberFormat.CURRENCYSTYLE),

        /**
         * Identical to NARROW except when formatMeasures is called with
         * an hour and minute; minute and second; or hour, minute, and second Measures.
         * In these cases formatMeasures formats as 5:37:23 instead of 5h, 37m, 23s.
         */
        NUMERIC("unitsNarrow", ListFormatter.Style.DURATION_NARROW, NumberFormat.CURRENCYSTYLE);

        // Be sure to update the toFormatWidth and fromFormatWidth() functions
        // when adding an enum value.

        final String resourceKey;
        private final ListFormatter.Style listFormatterStyle;
        private final int currencyStyle;

        private FormatWidth(String resourceKey, ListFormatter.Style style, int currencyStyle) {
            this.resourceKey = resourceKey;
            this.listFormatterStyle = style;
            this.currencyStyle = currencyStyle;
        }

        ListFormatter.Style getListFormatterStyle() {
            return listFormatterStyle;
        }

        int getCurrencyStyle() {
            return currencyStyle;
        }
    }

    /**
     * Create a format from the locale, formatWidth, and format.
     *
     * @param locale the locale.
     * @param formatWidth hints how long formatted strings should be.
     * @return The new MeasureFormat object.
     */
    public static MeasureFormat getInstance(ULocale locale, FormatWidth formatWidth) {
        return getInstance(locale, formatWidth, NumberFormat.getInstance(locale));
    }

    /**
     * Create a format from the JDK locale, formatWidth, and format.
     *
     * @param locale the JDK locale.
     * @param formatWidth hints how long formatted strings should be.
     * @return The new MeasureFormat object.
     */
    public static MeasureFormat getInstance(Locale locale, FormatWidth formatWidth) {
        return getInstance(ULocale.forLocale(locale), formatWidth);
    }

    /**
     * Create a format from the locale, formatWidth, and format.
     *
     * @param locale the locale.
     * @param formatWidth hints how long formatted strings should be.
     * @param format This is defensively copied.
     * @return The new MeasureFormat object.
     */
    public static MeasureFormat getInstance(ULocale locale, FormatWidth formatWidth, NumberFormat format) {
        PluralRules rules = PluralRules.forLocale(locale);
        NumericFormatters formatters = null;
        MeasureFormatData data = localeMeasureFormatData.get(locale);
        if (data == null) {
            data = loadLocaleData(locale);
            localeMeasureFormatData.put(locale, data);
        }
        if (formatWidth == FormatWidth.NUMERIC) {
            formatters = localeToNumericDurationFormatters.get(locale);
            if (formatters == null) {
                formatters = loadNumericFormatters(locale);
                localeToNumericDurationFormatters.put(locale, formatters);
            }
        }
        NumberFormat intFormat = NumberFormat.getInstance(locale);
        intFormat.setMaximumFractionDigits(0);
        intFormat.setMinimumFractionDigits(0);
        intFormat.setRoundingMode(BigDecimal.ROUND_DOWN);
        return new MeasureFormat(
                locale,
                formatWidth,
                new ImmutableNumberFormat(format),
                rules,
                data.unitToStyleToCountToFormat,
                formatters,
                new ImmutableNumberFormat(NumberFormat.getInstance(locale, formatWidth.getCurrencyStyle())),
                new ImmutableNumberFormat(intFormat),
                data.unitToStyleToPerUnitPattern,
                data.styleToPerPattern);
    }

    /**
     * Create a format from the JDK locale, formatWidth, and format.
     *
     * @param locale the JDK locale.
     * @param formatWidth hints how long formatted strings should be.
     * @param format This is defensively copied.
     * @return The new MeasureFormat object.
     */
    public static MeasureFormat getInstance(Locale locale, FormatWidth formatWidth, NumberFormat format) {
        return getInstance(ULocale.forLocale(locale), formatWidth, format);
    }

    /**
     * Able to format Collection&lt;? extends Measure&gt;, Measure[], and Measure
     * by delegating to formatMeasures.
     * If the pos argument identifies a NumberFormat field,
     * then its indices are set to the beginning and end of the first such field
     * encountered. MeasureFormat itself does not supply any fields.
     * 
     * Calling a
     * <code>formatMeasures</code> method is preferred over calling
     * this method as they give better performance.
     * 
     * @param obj must be a Collection<? extends Measure>, Measure[], or Measure object.
     * @param toAppendTo Formatted string appended here.
     * @param pos Identifies a field in the formatted text.
     * @see java.text.Format#format(java.lang.Object, java.lang.StringBuffer, java.text.FieldPosition)
     */
    @Override
    public StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition pos) {
        int prevLength = toAppendTo.length();
        FieldPosition fpos =
                new FieldPosition(pos.getFieldAttribute(), pos.getField());
        if (obj instanceof Collection) {
            Collection<?> coll = (Collection<?>) obj;
            Measure[] measures = new Measure[coll.size()];
            int idx = 0;
            for (Object o : coll) {
                if (!(o instanceof Measure)) {
                    throw new IllegalArgumentException(obj.toString());
                }
                measures[idx++] = (Measure) o;
            }
            toAppendTo.append(formatMeasures(new StringBuilder(), fpos, measures));
        } else if (obj instanceof Measure[]) {
            toAppendTo.append(formatMeasures(new StringBuilder(), fpos, (Measure[]) obj));
        } else if (obj instanceof Measure){
            toAppendTo.append(formatMeasure((Measure) obj, numberFormat, new StringBuilder(), fpos));
        } else {
            throw new IllegalArgumentException(obj.toString());            
        }
        if (fpos.getBeginIndex() != 0 || fpos.getEndIndex() != 0) {
            pos.setBeginIndex(fpos.getBeginIndex() + prevLength);
            pos.setEndIndex(fpos.getEndIndex() + prevLength);
        }
        return toAppendTo;
    }

    /**
     * Parses text from a string to produce a <code>Measure</code>.
     * @see java.text.Format#parseObject(java.lang.String, java.text.ParsePosition)
     * @throws UnsupportedOperationException Not supported.
     * @hide draft / provisional / internal are hidden on Android
     */
    @Override
    public Measure parseObject(String source, ParsePosition pos) {
        throw new UnsupportedOperationException();
    }

    /**
     * Format a sequence of measures. Uses the ListFormatter unit lists.
     * So, for example, one could format “3 feet, 2 inches”.
     * Zero values are formatted (eg, “3 feet, 0 inches”). It is the caller’s
     * responsibility to have the appropriate values in appropriate order,
     * and using the appropriate Number values. Typically the units should be
     * in descending order, with all but the last Measure having integer values
     * (eg, not “3.2 feet, 2 inches”).
     * 
     * @param measures a sequence of one or more measures.
     * @return the formatted string.
     */
    public final String formatMeasures(Measure... measures) {
        return formatMeasures(
                new StringBuilder(),
                DontCareFieldPosition.INSTANCE,
                measures).toString();
    }

    /**
     * Format a range of measures, such as "3.4-5.1 meters". It is the caller’s
     * responsibility to have the appropriate values in appropriate order,
     * and using the appropriate Number values.
     * <br>Note: If the format doesn’t have enough decimals, or lowValue ≥ highValue,
     * the result will be a degenerate range, like “5-5 meters”.
     * <br>Currency Units are not yet supported.
     * 
     * @param lowValue low value in range
     * @param highValue high value in range
     * @return the formatted string.
     * @deprecated This API is ICU internal only.
     * @hide original deprecated method
     * @hide draft / provisional / internal are hidden on Android
     */
    @Deprecated
    public final String formatMeasureRange(Measure lowValue, Measure highValue) {
        MeasureUnit unit = lowValue.getUnit();
        if (!unit.equals(highValue.getUnit())) {
            throw new IllegalArgumentException("Units must match: " + unit + " ≠ " + highValue.getUnit());
        }
        Number lowNumber = lowValue.getNumber();
        Number highNumber = highValue.getNumber();
        final boolean isCurrency = unit instanceof Currency;

        UFieldPosition lowFpos = new UFieldPosition();
        UFieldPosition highFpos = new UFieldPosition();
        StringBuffer lowFormatted = null;
        StringBuffer highFormatted = null;

        if (isCurrency) {
            Currency currency = (Currency) unit;
            int fracDigits = currency.getDefaultFractionDigits();
            int maxFrac = numberFormat.nf.getMaximumFractionDigits();
            int minFrac = numberFormat.nf.getMinimumFractionDigits();
            if (fracDigits != maxFrac || fracDigits != minFrac) {
                DecimalFormat currentNumberFormat = (DecimalFormat) numberFormat.get();
                currentNumberFormat.setMaximumFractionDigits(fracDigits);
                currentNumberFormat.setMinimumFractionDigits(fracDigits);
                lowFormatted = currentNumberFormat.format(lowNumber, new StringBuffer(), lowFpos);
                highFormatted = currentNumberFormat.format(highNumber, new StringBuffer(), highFpos);
            }
        }
        if (lowFormatted == null) {
            lowFormatted = numberFormat.format(lowNumber, new StringBuffer(), lowFpos);
            highFormatted = numberFormat.format(highNumber, new StringBuffer(), highFpos);
        }

        final double lowDouble = lowNumber.doubleValue();
        String keywordLow = rules.select(new PluralRules.FixedDecimal(lowDouble, 
                lowFpos.getCountVisibleFractionDigits(), lowFpos.getFractionDigits()));

        final double highDouble = highNumber.doubleValue();
        String keywordHigh = rules.select(new PluralRules.FixedDecimal(highDouble, 
                highFpos.getCountVisibleFractionDigits(), highFpos.getFractionDigits()));

        final PluralRanges pluralRanges = Factory.getDefaultFactory().getPluralRanges(getLocale());
        StandardPluralCategories resolvedCategory = pluralRanges.get(
                StandardPluralCategories.valueOf(keywordLow), StandardPluralCategories.valueOf(keywordHigh));

        SimplePatternFormatter rangeFormatter = getRangeFormat(getLocale(), formatWidth);
        String formattedNumber = rangeFormatter.format(lowFormatted, highFormatted);

        if (isCurrency) {
            // Nasty hack
            currencyFormat.format(1d); // have to call this for the side effect

            Currency currencyUnit = (Currency) unit;
            StringBuilder result = new StringBuilder();
            appendReplacingCurrency(currencyFormat.getPrefix(lowDouble >= 0), currencyUnit, resolvedCategory, result);
            result.append(formattedNumber);
            appendReplacingCurrency(currencyFormat.getSuffix(highDouble >= 0), currencyUnit, resolvedCategory, result);
            return result.toString();
            //            StringBuffer buffer = new StringBuffer();
            //            CurrencyAmount currencyLow = (CurrencyAmount) lowValue;
            //            CurrencyAmount currencyHigh = (CurrencyAmount) highValue;
            //            FieldPosition pos = new FieldPosition(NumberFormat.INTEGER_FIELD);
            //            currencyFormat.format(currencyLow, buffer, pos);
            //            int startOfInteger = pos.getBeginIndex();
            //            StringBuffer buffer2 = new StringBuffer();
            //            FieldPosition pos2 = new FieldPosition(0);
            //            currencyFormat.format(currencyHigh, buffer2, pos2);
        } else {
            Map<FormatWidth, QuantityFormatter> styleToCountToFormat = unitToStyleToCountToFormat.get(lowValue.getUnit());
            QuantityFormatter countToFormat = styleToCountToFormat.get(formatWidth);
            SimplePatternFormatter formatter = countToFormat.getByVariant(resolvedCategory.toString());
            return formatter.format(formattedNumber);
        }
    }

    private void appendReplacingCurrency(String affix, Currency unit, StandardPluralCategories resolvedCategory, StringBuilder result) {
        String replacement = "¤";
        int pos = affix.indexOf(replacement);
        if (pos < 0) {
            replacement = "XXX";
            pos = affix.indexOf(replacement);
        }
        if (pos < 0) {
            result.append(affix);
        } else {
            // for now, just assume single
            result.append(affix.substring(0,pos));
            // we have a mismatch between the number style and the currency style, so remap
            int currentStyle = formatWidth.getCurrencyStyle();
            if (currentStyle == NumberFormat.ISOCURRENCYSTYLE) {
                result.append(unit.getCurrencyCode());
            } else {
                result.append(unit.getName(currencyFormat.nf.getLocale(ULocale.ACTUAL_LOCALE),
                        currentStyle == NumberFormat.CURRENCYSTYLE ? Currency.SYMBOL_NAME :  Currency.PLURAL_LONG_NAME,
                                resolvedCategory.toString(), null));
            }
            result.append(affix.substring(pos+replacement.length()));
        }
    }
    
    /**
     * Formats a single measure per unit. 
     * 
     * An example of such a formatted string is "3.5 meters per second."
     *
     * @param measure  the measure object. In above example, 3.5 meters.
     * @param perUnit  the per unit. In above example, it is MeasureUnit.SECOND
     * @param appendTo formatted string appended here.
     * @param pos      The field position.
     * @return appendTo.
     * @hide draft / provisional / internal are hidden on Android
     */
    public StringBuilder formatMeasurePerUnit(
            Measure measure,
            MeasureUnit perUnit,
            StringBuilder appendTo,
            FieldPosition pos) {
        MeasureUnit resolvedUnit = MeasureUnit.resolveUnitPerUnit(
                measure.getUnit(), perUnit);
        if (resolvedUnit != null) {
            Measure newMeasure = new Measure(measure.getNumber(), resolvedUnit);
            return formatMeasure(newMeasure, numberFormat, appendTo, pos);
        }
        FieldPosition fpos = new FieldPosition(
                pos.getFieldAttribute(), pos.getField());
        int offset = withPerUnitAndAppend(
                formatMeasure(measure, numberFormat, new StringBuilder(), fpos),
                perUnit,
                appendTo);
        if (fpos.getBeginIndex() != 0 || fpos.getEndIndex() != 0) {
            pos.setBeginIndex(fpos.getBeginIndex() + offset);
            pos.setEndIndex(fpos.getEndIndex() + offset);
        }
        return appendTo;
    }

    /**
     * Formats a sequence of measures.
     * 
     * If the fieldPosition argument identifies a NumberFormat field,
     * then its indices are set to the beginning and end of the first such field
     * encountered. MeasureFormat itself does not supply any fields.
     * 
     * @param appendTo the formatted string appended here.
     * @param fieldPosition Identifies a field in the formatted text.
     * @param measures the measures to format.
     * @return appendTo.
     * @see MeasureFormat#formatMeasures(Measure...)
     */
    public StringBuilder formatMeasures(
            StringBuilder appendTo, FieldPosition fieldPosition, Measure... measures) {
        // fast track for trivial cases
        if (measures.length == 0) {
            return appendTo;
        }
        if (measures.length == 1) {
            return formatMeasure(measures[0], numberFormat, appendTo, fieldPosition);
        }

        if (formatWidth == FormatWidth.NUMERIC) {
            // If we have just hour, minute, or second follow the numeric
            // track.
            Number[] hms = toHMS(measures);
            if (hms != null) {
                return formatNumeric(hms, appendTo);
            }
        }

        ListFormatter listFormatter = ListFormatter.getInstance(
                getLocale(), formatWidth.getListFormatterStyle());
        if (fieldPosition != DontCareFieldPosition.INSTANCE) {
            return formatMeasuresSlowTrack(listFormatter, appendTo, fieldPosition, measures);
        }
        // Fast track: No field position.
        String[] results = new String[measures.length];
        for (int i = 0; i < measures.length; i++) {
            results[i] = formatMeasure(
                    measures[i],
                    i == measures.length - 1 ? numberFormat : integerFormat);
        }
        return appendTo.append(listFormatter.format((Object[]) results));                 

    }   

    /**
     * Two MeasureFormats, a and b, are equal if and only if they have the same formatWidth,
     * locale, and equal number formats.
     */
    @Override
    public final boolean equals(Object other) {
        if (this == other) {
            return true;
        }
        if (!(other instanceof MeasureFormat)) {
            return false;
        }
        MeasureFormat rhs = (MeasureFormat) other;
        // A very slow but safe implementation.
        return getWidth() == rhs.getWidth() 
                && getLocale().equals(rhs.getLocale()) 
                && getNumberFormat().equals(rhs.getNumberFormat());
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final int hashCode() {
        // A very slow but safe implementation.
        return (getLocale().hashCode() * 31 
                + getNumberFormat().hashCode()) * 31 + getWidth().hashCode();
    }

    /**
     * Get the format width this instance is using.
     */
    public MeasureFormat.FormatWidth getWidth() {
        return formatWidth;
    }

    /**
     * Get the locale of this instance.
     */
    public final ULocale getLocale() {
        return getLocale(ULocale.VALID_LOCALE);
    }

    /**
     * Get a copy of the number format.
     */
    public NumberFormat getNumberFormat() {
        return numberFormat.get();
    }

    /**
     * Return a formatter for CurrencyAmount objects in the given
     * locale.
     * @param locale desired locale
     * @return a formatter object
     */
    public static MeasureFormat getCurrencyFormat(ULocale locale) {
        return new CurrencyFormat(locale);
    }

    /**
     * Return a formatter for CurrencyAmount objects in the given
     * JDK locale.
     * @param locale desired JDK locale
     * @return a formatter object
     */
    public static MeasureFormat getCurrencyFormat(Locale locale) {
        return getCurrencyFormat(ULocale.forLocale(locale));
    }

    /**
     * Return a formatter for CurrencyAmount objects in the default
     * <code>FORMAT</code> locale.
     * @return a formatter object
     * @see Category#FORMAT
     */
    public static MeasureFormat getCurrencyFormat() {
        return getCurrencyFormat(ULocale.getDefault(Category.FORMAT));
    }

    // This method changes the NumberFormat object as well to match the new locale.
    MeasureFormat withLocale(ULocale locale) {
        return MeasureFormat.getInstance(locale, getWidth());
    }

    MeasureFormat withNumberFormat(NumberFormat format) {
        return new MeasureFormat(
                getLocale(),
                this.formatWidth,
                new ImmutableNumberFormat(format),
                this.rules,
                this.unitToStyleToCountToFormat,
                this.numericFormatters,
                this.currencyFormat,
                this.integerFormat,
                this.unitToStyleToPerUnitPattern,
                this.styleToPerPattern);
    }

    private MeasureFormat(
            ULocale locale,
            FormatWidth formatWidth,
            ImmutableNumberFormat format,
            PluralRules rules,
            Map<MeasureUnit, EnumMap<FormatWidth, QuantityFormatter>> unitToStyleToCountToFormat,
            NumericFormatters formatters,
            ImmutableNumberFormat currencyFormat,
            ImmutableNumberFormat integerFormat,
            Map<MeasureUnit, EnumMap<FormatWidth, SimplePatternFormatter>> unitToStyleToPerUnitPattern,
            EnumMap<FormatWidth, SimplePatternFormatter> styleToPerPattern) {
        setLocale(locale, locale);
        this.formatWidth = formatWidth;
        this.numberFormat = format;
        this.rules = rules;
        this.unitToStyleToCountToFormat = unitToStyleToCountToFormat;
        this.numericFormatters = formatters;
        this.currencyFormat = currencyFormat;
        this.integerFormat = integerFormat;
        this.unitToStyleToPerUnitPattern = unitToStyleToPerUnitPattern;
        this.styleToPerPattern = styleToPerPattern;
    }

    MeasureFormat() {
        // Make compiler happy by setting final fields to null.
        this.formatWidth = null;
        this.numberFormat = null;
        this.rules = null;
        this.unitToStyleToCountToFormat = null;
        this.numericFormatters = null;
        this.currencyFormat = null;
        this.integerFormat = null;
        this.unitToStyleToPerUnitPattern = null;
        this.styleToPerPattern = null;
    }

    static class NumericFormatters {
        private DateFormat hourMinute;
        private DateFormat minuteSecond;
        private DateFormat hourMinuteSecond;

        public NumericFormatters(
                DateFormat hourMinute,
                DateFormat minuteSecond,
                DateFormat hourMinuteSecond) {
            this.hourMinute = hourMinute;
            this.minuteSecond = minuteSecond;
            this.hourMinuteSecond = hourMinuteSecond;
        }

        public DateFormat getHourMinute() { return hourMinute; }
        public DateFormat getMinuteSecond() { return minuteSecond; }
        public DateFormat getHourMinuteSecond() { return hourMinuteSecond; }
    }

    private static NumericFormatters loadNumericFormatters(
            ULocale locale) {
        ICUResourceBundle r = (ICUResourceBundle)UResourceBundle.
                getBundleInstance(ICUData.ICU_UNIT_BASE_NAME, locale);
        return new NumericFormatters(
                loadNumericDurationFormat(r, "hm"),
                loadNumericDurationFormat(r, "ms"),
                loadNumericDurationFormat(r, "hms"));
    }

    /**
     * Returns formatting data for all MeasureUnits except for currency ones.
     */
    private static MeasureFormatData loadLocaleData(
            ULocale locale) {
        QuantityFormatter.Builder builder = new QuantityFormatter.Builder();
        Map<MeasureUnit, EnumMap<FormatWidth, QuantityFormatter>> unitToStyleToCountToFormat
        = new HashMap<MeasureUnit, EnumMap<FormatWidth, QuantityFormatter>>();
        Map<MeasureUnit, EnumMap<FormatWidth, SimplePatternFormatter>> unitToStyleToPerUnitPattern
        = new HashMap<MeasureUnit, EnumMap<FormatWidth, SimplePatternFormatter>>();
        ICUResourceBundle resource = (ICUResourceBundle)UResourceBundle.getBundleInstance(ICUData.ICU_UNIT_BASE_NAME, locale);
        EnumMap<FormatWidth, SimplePatternFormatter> styleToPerPattern = new EnumMap<FormatWidth, SimplePatternFormatter>(FormatWidth.class);
        for (FormatWidth styleItem : FormatWidth.values()) {
            try {
                ICUResourceBundle unitTypeRes = resource.getWithFallback(styleItem.resourceKey);
                ICUResourceBundle compoundRes = unitTypeRes.getWithFallback("compound");
                ICUResourceBundle perRes = compoundRes.getWithFallback("per");
                styleToPerPattern.put(styleItem, SimplePatternFormatter.compile(perRes.getString()));
            } catch (MissingResourceException e) {
                // may not have compound/per for every width.
                continue;
            }
        }
        fillInStyleMap(styleToPerPattern);
        for (MeasureUnit unit : MeasureUnit.getAvailable()) {
            // Currency data cannot be found here. Skip.
            if (unit instanceof Currency) {
                continue;
            }
            EnumMap<FormatWidth, QuantityFormatter> styleToCountToFormat = unitToStyleToCountToFormat.get(unit);
            if (styleToCountToFormat == null) {
                unitToStyleToCountToFormat.put(unit, styleToCountToFormat = new EnumMap<FormatWidth, QuantityFormatter>(FormatWidth.class));
            }
            EnumMap<FormatWidth, SimplePatternFormatter> styleToPerUnitPattern = new EnumMap<FormatWidth, SimplePatternFormatter>(FormatWidth.class);
            unitToStyleToPerUnitPattern.put(unit, styleToPerUnitPattern);
            for (FormatWidth styleItem : FormatWidth.values()) {
                try {
                    ICUResourceBundle unitTypeRes = resource.getWithFallback(styleItem.resourceKey);
                    ICUResourceBundle unitsRes = unitTypeRes.getWithFallback(unit.getType());
                    ICUResourceBundle oneUnitRes = unitsRes.getWithFallback(unit.getSubtype());
                    builder.reset();
                    boolean havePluralItem = false;
                    int len = oneUnitRes.getSize();
                    for (int i = 0; i < len; i++) {
                        UResourceBundle countBundle;
                        try {
                            countBundle = oneUnitRes.get(i);
                        } catch (MissingResourceException e) {
                            continue;
                        }
                        String resKey = countBundle.getKey();
                        if (resKey.equals("dnam")) {
                            continue; // skip display name & per pattern (new in CLDR 26 / ICU 54) for now, not part of plurals
                        }
                        if (resKey.equals("per")) {
                            styleToPerUnitPattern.put(
                                    styleItem, SimplePatternFormatter.compile(countBundle.getString()));
                            continue;
                        }
                        havePluralItem = true;
                        builder.add(resKey, countBundle.getString());
                    }
                    if (havePluralItem) {
                        // might not have any plural items if countBundle only has "dnam" display name, for instance,
                        // as with fr unitsNarrow/light/lux in CLDR 26
                        styleToCountToFormat.put(styleItem, builder.build());
                    }
                } catch (MissingResourceException e) {
                    continue;
                }
            }
            // TODO: if no fallback available, get from root.
            fillInStyleMap(styleToCountToFormat);
            fillInStyleMap(styleToPerUnitPattern);
        }
        return new MeasureFormatData(unitToStyleToCountToFormat, unitToStyleToPerUnitPattern, styleToPerPattern);
    }
    
    private static <T> boolean fillInStyleMap(Map<FormatWidth, T> styleMap) {
        if (styleMap.size() == FormatWidth.values().length) {
            return true;
        }
        T fallback = styleMap.get(FormatWidth.SHORT);
        if (fallback == null) {
            return false;
        }
        for (FormatWidth styleItem : FormatWidth.values()) {
            T item = styleMap.get(styleItem);
            if (item == null) {
                styleMap.put(styleItem, fallback);
            }
        }
        return true;
    }
    
    private int withPerUnitAndAppend(
            CharSequence formatted, MeasureUnit perUnit, StringBuilder appendTo) {
        int[] offsets = new int[1];
        Map<FormatWidth, SimplePatternFormatter> styleToPerUnitPattern =
                unitToStyleToPerUnitPattern.get(perUnit);
        SimplePatternFormatter perUnitPattern = styleToPerUnitPattern.get(formatWidth);
        if (perUnitPattern != null) {
            perUnitPattern.formatAndAppend(appendTo, offsets, formatted);
            return offsets[0];
        }
        SimplePatternFormatter perPattern = styleToPerPattern.get(formatWidth);
        Map<FormatWidth, QuantityFormatter> styleToCountToFormat = unitToStyleToCountToFormat.get(perUnit);
        QuantityFormatter countToFormat = styleToCountToFormat.get(formatWidth);
        String perUnitString = countToFormat.getByVariant("one").getPatternWithNoPlaceholders().trim();
        perPattern.formatAndAppend(appendTo, offsets, formatted, perUnitString);
        return offsets[0];
    }

    private String formatMeasure(Measure measure, ImmutableNumberFormat nf) {
        return formatMeasure(
                measure, nf, new StringBuilder(),
                DontCareFieldPosition.INSTANCE).toString();
    }

    private StringBuilder formatMeasure(
            Measure measure,
            ImmutableNumberFormat nf,
            StringBuilder appendTo,
            FieldPosition fieldPosition) {
        if (measure.getUnit() instanceof Currency) {
            return appendTo.append(
                    currencyFormat.format(
                            new CurrencyAmount(measure.getNumber(), (Currency) measure.getUnit()),
                            new StringBuffer(),
                            fieldPosition));

        }
        Number n = measure.getNumber();
        MeasureUnit unit = measure.getUnit(); 
        UFieldPosition fpos = new UFieldPosition(fieldPosition.getFieldAttribute(), fieldPosition.getField());
        StringBuffer formattedNumber = nf.format(n, new StringBuffer(), fpos);
        String keyword = rules.select(new PluralRules.FixedDecimal(n.doubleValue(), fpos.getCountVisibleFractionDigits(), fpos.getFractionDigits()));

        Map<FormatWidth, QuantityFormatter> styleToCountToFormat = unitToStyleToCountToFormat.get(unit);
        QuantityFormatter countToFormat = styleToCountToFormat.get(formatWidth);
        SimplePatternFormatter formatter = countToFormat.getByVariant(keyword);
        int[] offsets = new int[1];
        formatter.formatAndAppend(appendTo, offsets, formattedNumber);
        if (offsets[0] != -1) { // there is a number (may not happen with, say, Arabic dual)
            // Fix field position
            if (fpos.getBeginIndex() != 0 || fpos.getEndIndex() != 0) {
                fieldPosition.setBeginIndex(fpos.getBeginIndex() + offsets[0]);
                fieldPosition.setEndIndex(fpos.getEndIndex() + offsets[0]);
            }
        }
        return appendTo;
    }
    
    private static final class MeasureFormatData {
        MeasureFormatData(
                Map<MeasureUnit, EnumMap<FormatWidth, QuantityFormatter>> unitToStyleToCountToFormat,
                Map<MeasureUnit, EnumMap<FormatWidth, SimplePatternFormatter>> unitToStyleToPerUnitPattern,
                EnumMap<FormatWidth, SimplePatternFormatter> styleToPerPattern) {
            this.unitToStyleToCountToFormat = unitToStyleToCountToFormat;
            this.unitToStyleToPerUnitPattern = unitToStyleToPerUnitPattern;
            this.styleToPerPattern = styleToPerPattern;
        }
        final Map<MeasureUnit, EnumMap<FormatWidth, QuantityFormatter>> unitToStyleToCountToFormat;
        final Map<MeasureUnit, EnumMap<FormatWidth, SimplePatternFormatter>> unitToStyleToPerUnitPattern;
        final EnumMap<FormatWidth, SimplePatternFormatter> styleToPerPattern;
    }

    // Wrapper around NumberFormat that provides immutability and thread-safety.
    private static final class ImmutableNumberFormat {
        private NumberFormat nf;

        public ImmutableNumberFormat(NumberFormat nf) {
            this.nf = (NumberFormat) nf.clone();
        }

        public synchronized NumberFormat get() {
            return (NumberFormat) nf.clone();
        }

        public synchronized StringBuffer format(
                Number n, StringBuffer buffer, FieldPosition pos) {
            return nf.format(n, buffer, pos);
        }

        public synchronized StringBuffer format(
                CurrencyAmount n, StringBuffer buffer, FieldPosition pos) {
            return nf.format(n, buffer, pos);
        }

        @SuppressWarnings("unused")
        public synchronized String format(Number number) {
            return nf.format(number);
        }

        public String getPrefix(boolean positive) {
            return positive ? ((DecimalFormat)nf).getPositivePrefix() : ((DecimalFormat)nf).getNegativePrefix();
        }
        public String getSuffix(boolean positive) {
            return positive ? ((DecimalFormat)nf).getPositiveSuffix() : ((DecimalFormat)nf).getPositiveSuffix();
        }
    }

    static final class PatternData {
        final String prefix;
        final String suffix;
        public PatternData(String pattern) {
            int pos = pattern.indexOf("{0}");
            if (pos < 0) {
                prefix = pattern;
                suffix = null;
            } else {
                prefix = pattern.substring(0,pos);
                suffix = pattern.substring(pos+3);
            }
        }
        public String toString() {
            return prefix + "; " + suffix;
        }

    }

    Object toTimeUnitProxy() {
        return new MeasureProxy(getLocale(), formatWidth, numberFormat.get(), TIME_UNIT_FORMAT);
    }

    Object toCurrencyProxy() {
        return new MeasureProxy(getLocale(), formatWidth, numberFormat.get(), CURRENCY_FORMAT);
    }

    private StringBuilder formatMeasuresSlowTrack(
            ListFormatter listFormatter,
            StringBuilder appendTo,
            FieldPosition fieldPosition,
            Measure... measures) {
        String[] results = new String[measures.length];

        // Zero out our field position so that we can tell when we find our field.
        FieldPosition fpos = new FieldPosition(
                fieldPosition.getFieldAttribute(), fieldPosition.getField());

        int fieldPositionFoundIndex = -1;
        for (int i = 0; i < measures.length; ++i) {
            ImmutableNumberFormat nf = (i == measures.length - 1 ? numberFormat : integerFormat);
            if (fieldPositionFoundIndex == -1) {
                results[i] = formatMeasure(measures[i], nf, new StringBuilder(), fpos).toString();
                if (fpos.getBeginIndex() != 0 || fpos.getEndIndex() != 0) {
                    fieldPositionFoundIndex = i;    
                }
            } else {
                results[i] = formatMeasure(measures[i], nf);
            }
        }
        ListFormatter.FormattedListBuilder builder =
                listFormatter.format(Arrays.asList(results), fieldPositionFoundIndex);

        // Fix up FieldPosition indexes if our field is found.
        if (builder.getOffset() != -1) {
            fieldPosition.setBeginIndex(fpos.getBeginIndex() + builder.getOffset() + appendTo.length());
            fieldPosition.setEndIndex(fpos.getEndIndex() + builder.getOffset() + appendTo.length());
        }
        return appendTo.append(builder.toString());
    }

    // type is one of "hm", "ms" or "hms"
    private static DateFormat loadNumericDurationFormat(
            ICUResourceBundle r, String type) {
        r = r.getWithFallback(String.format("durationUnits/%s", type));
        // We replace 'h' with 'H' because 'h' does not make sense in the context of durations.
        DateFormat result = new SimpleDateFormat(r.getString().replace("h", "H"));
        result.setTimeZone(TimeZone.GMT_ZONE);
        return result;
    }

    // Returns hours in [0]; minutes in [1]; seconds in [2] out of measures array. If
    // unsuccessful, e.g measures has other measurements besides hours, minutes, seconds;
    // hours, minutes, seconds are out of order; or have negative values, returns null.
    // If hours, minutes, or seconds is missing from measures the corresponding element in
    // returned array will be null.
    private static Number[] toHMS(Measure[] measures) {
        Number[] result = new Number[3];
        int lastIdx = -1;
        for (Measure m : measures) {
            if (m.getNumber().doubleValue() < 0.0) {
                return null;
            }
            Integer idxObj = hmsTo012.get(m.getUnit());
            if (idxObj == null) {
                return null;
            }
            int idx = idxObj.intValue();
            if (idx <= lastIdx) {
                // hour before minute before second
                return null;
            }
            lastIdx = idx;
            result[idx] = m.getNumber();
        }
        return result;
    }

    // Formats numeric time duration as 5:00:47 or 3:54. In the process, it replaces any null
    // values in hms with 0.
    private StringBuilder formatNumeric(Number[] hms, StringBuilder appendable) {

        // find the start and end of non-nil values in hms array. We have to know if we
        // have hour-minute; minute-second; or hour-minute-second.
        int startIndex = -1;
        int endIndex = -1;
        for (int i = 0; i < hms.length; i++) {
            if (hms[i] != null) {
                endIndex = i;
                if (startIndex == -1) {
                    startIndex = endIndex;
                }
            } else {
                // Replace nil value with 0.
                hms[i] = Integer.valueOf(0);
            }
        }
        // convert hours, minutes, seconds into milliseconds.
        long millis = (long) (((Math.floor(hms[0].doubleValue()) * 60.0
                + Math.floor(hms[1].doubleValue())) * 60.0
                + Math.floor(hms[2].doubleValue())) * 1000.0);
        Date d = new Date(millis);
        // if hour-minute-second
        if (startIndex == 0 && endIndex == 2) {
            return formatNumeric(
                    d, 
                    numericFormatters.getHourMinuteSecond(),
                    DateFormat.Field.SECOND,
                    hms[endIndex],
                    appendable);
        }
        // if minute-second
        if (startIndex == 1 && endIndex == 2) {
            return formatNumeric(
                    d, 
                    numericFormatters.getMinuteSecond(),
                    DateFormat.Field.SECOND,
                    hms[endIndex],
                    appendable);
        }
        // if hour-minute
        if (startIndex == 0 && endIndex == 1) {
            return formatNumeric(
                    d, 
                    numericFormatters.getHourMinute(),
                    DateFormat.Field.MINUTE,
                    hms[endIndex],
                    appendable);
        }
        throw new IllegalStateException();
    }

    // Formats a duration as 5:00:37 or 23:59.
    // duration is a particular duration after epoch.
    // formatter is a hour-minute-second, hour-minute, or minute-second formatter.
    // smallestField denotes what the smallest field is in duration: either
    // hour, minute, or second.
    // smallestAmount is the value of that smallest field. for 5:00:37.3,
    // smallestAmount is 37.3. This smallest field is formatted with this object's
    // NumberFormat instead of formatter.
    // appendTo is where the formatted string is appended.
    private StringBuilder formatNumeric(
            Date duration,
            DateFormat formatter,
            DateFormat.Field smallestField,
            Number smallestAmount,
            StringBuilder appendTo) {
        // Format the smallest amount ahead of time.
        String smallestAmountFormatted;

        // Format the smallest amount using this object's number format, but keep track
        // of the integer portion of this formatted amount. We have to replace just the
        // integer part with the corresponding value from formatting the date. Otherwise
        // when formatting 0 minutes 9 seconds, we may get "00:9" instead of "00:09"
        FieldPosition intFieldPosition = new FieldPosition(NumberFormat.INTEGER_FIELD);
        smallestAmountFormatted = numberFormat.format(
                smallestAmount, new StringBuffer(), intFieldPosition).toString();
        // Give up if there is no integer field.
        if (intFieldPosition.getBeginIndex() == 0 && intFieldPosition.getEndIndex() == 0) {
            throw new IllegalStateException();
        }
        // Format our duration as a date, but keep track of where the smallest field is
        // so that we can use it to replace the integer portion of the smallest value.
        FieldPosition smallestFieldPosition = new FieldPosition(smallestField);
        String draft = formatter.format(
                duration, new StringBuffer(), smallestFieldPosition).toString();

        // If we find the smallest field
        if (smallestFieldPosition.getBeginIndex() != 0
                || smallestFieldPosition.getEndIndex() != 0) {
            // add everything up to the start of the smallest field in duration.
            appendTo.append(draft, 0, smallestFieldPosition.getBeginIndex());

            // add everything in the smallest field up to the integer portion
            appendTo.append(smallestAmountFormatted, 0, intFieldPosition.getBeginIndex());

            // Add the smallest field in formatted duration in lieu of the integer portion
            // of smallest field
            appendTo.append(
                    draft,
                    smallestFieldPosition.getBeginIndex(),
                    smallestFieldPosition.getEndIndex());

            // Add the rest of the smallest field
            appendTo.append(
                    smallestAmountFormatted,
                    intFieldPosition.getEndIndex(),
                    smallestAmountFormatted.length());
            appendTo.append(draft, smallestFieldPosition.getEndIndex(), draft.length());
        } else {
            // As fallback, just use the formatted duration.
            appendTo.append(draft);
        }
        return appendTo;
    }

    private Object writeReplace() throws ObjectStreamException {
        return new MeasureProxy(
                getLocale(), formatWidth, numberFormat.get(), MEASURE_FORMAT);
    }

    static class MeasureProxy implements Externalizable {
        private static final long serialVersionUID = -6033308329886716770L;

        private ULocale locale;
        private FormatWidth formatWidth;
        private NumberFormat numberFormat;
        private int subClass;
        private HashMap<Object, Object> keyValues;

        public MeasureProxy(
                ULocale locale,
                FormatWidth width,
                NumberFormat numberFormat,
                int subClass) {
            this.locale = locale;
            this.formatWidth = width;
            this.numberFormat = numberFormat;
            this.subClass = subClass;
            this.keyValues = new HashMap<Object, Object>();
        }

        // Must have public constructor, to enable Externalizable
        public MeasureProxy() {
        }

        public void writeExternal(ObjectOutput out) throws IOException {
            out.writeByte(0); // version
            out.writeUTF(locale.toLanguageTag());
            out.writeByte(formatWidth.ordinal());
            out.writeObject(numberFormat);
            out.writeByte(subClass);
            out.writeObject(keyValues);
        }

        @SuppressWarnings("unchecked")
        public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
            in.readByte(); // version.
            locale = ULocale.forLanguageTag(in.readUTF());
            formatWidth = fromFormatWidthOrdinal(in.readByte() & 0xFF);
            numberFormat = (NumberFormat) in.readObject();
            if (numberFormat == null) {
                throw new InvalidObjectException("Missing number format.");
            }
            subClass = in.readByte() & 0xFF;

            // This cast is safe because the serialized form of hashtable can have
            // any object as the key and any object as the value.
            keyValues = (HashMap<Object, Object>) in.readObject();
            if (keyValues == null) {
                throw new InvalidObjectException("Missing optional values map.");
            }
        }

        private TimeUnitFormat createTimeUnitFormat() throws InvalidObjectException {
            int style;
            if (formatWidth == FormatWidth.WIDE) {
                style = TimeUnitFormat.FULL_NAME;
            } else if (formatWidth == FormatWidth.SHORT) {
                style = TimeUnitFormat.ABBREVIATED_NAME;
            } else {
                throw new InvalidObjectException("Bad width: " + formatWidth);
            }
            TimeUnitFormat result = new TimeUnitFormat(locale, style);
            result.setNumberFormat(numberFormat);
            return result;
        }

        private Object readResolve() throws ObjectStreamException {
            switch (subClass) {
            case MEASURE_FORMAT:
                return MeasureFormat.getInstance(locale, formatWidth, numberFormat);
            case TIME_UNIT_FORMAT:
                return createTimeUnitFormat();
            case CURRENCY_FORMAT:
                return new CurrencyFormat(locale);
            default:
                throw new InvalidObjectException("Unknown subclass: " + subClass);
            }
        }
    }

    private static FormatWidth fromFormatWidthOrdinal(int ordinal) {
        FormatWidth[] values = FormatWidth.values();
        if (ordinal < 0 || ordinal >= values.length) {
            return FormatWidth.SHORT;
        }
        return values[ordinal];
    }

    static final Map<ULocale, SimplePatternFormatter> localeIdToRangeFormat 
    = new ConcurrentHashMap<ULocale, SimplePatternFormatter>();

    /**
     * Return a simple pattern formatter for a range, such as "{0}–{1}".
     * @param forLocale locale to get the format for
     * @param width the format width
     * @return range formatter, such as "{0}–{1}"
     * @deprecated This API is ICU internal only.
     * @hide original deprecated method
     * @hide draft / provisional / internal are hidden on Android
     */
    @Deprecated

    public static SimplePatternFormatter getRangeFormat(ULocale forLocale, FormatWidth width) {
        // TODO fix Hack for French
        if (forLocale.getLanguage().equals("fr")) {
            return getRangeFormat(ULocale.ROOT, width);
        }
        SimplePatternFormatter result = localeIdToRangeFormat.get(forLocale);
        if (result == null) {
            ICUResourceBundle rb = (ICUResourceBundle)UResourceBundle.
                    getBundleInstance(ICUData.ICU_BASE_NAME, forLocale);
            ULocale realLocale = rb.getULocale();
            if (!forLocale.equals(realLocale)) { // if the child would inherit, then add a cache entry for it.
                result = localeIdToRangeFormat.get(forLocale);
                if (result != null) {
                    localeIdToRangeFormat.put(forLocale, result);
                    return result;
                }
            }
            // At this point, both the forLocale and the realLocale don't have an item
            // So we have to make one.
            NumberingSystem ns = NumberingSystem.getInstance(forLocale);

            String resultString = null;
            try {
                resultString = rb.getStringWithFallback("NumberElements/" + ns.getName() + "/miscPatterns/range");
            } catch ( MissingResourceException ex ) {
                resultString = rb.getStringWithFallback("NumberElements/latn/patterns/range");
            }
            result = SimplePatternFormatter.compile(resultString);
            localeIdToRangeFormat.put(forLocale, result);
            if (!forLocale.equals(realLocale)) {
                localeIdToRangeFormat.put(realLocale, result);
            }
        }
        return result;
    }
    
    /**
     * Return a simple pattern pattern for a range, such as "{0}–{1}" or "{0}～{1}".
     * @param forLocale locale to get the range pattern for
     * @param width the format width.
     * @return range pattern
     * @deprecated This API is ICU internal only.
     * @hide original deprecated method
     * @hide draft / provisional / internal are hidden on Android
     */
    @Deprecated
    public static String getRangePattern(ULocale forLocale, FormatWidth width) {
        return getRangeFormat(forLocale, width).toString();
    }
}
