/*
 **********************************************************************
 * 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 com.ibm.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 com.ibm.icu.impl.DontCareFieldPosition;
import com.ibm.icu.impl.ICUData;
import com.ibm.icu.impl.ICUResourceBundle;
import com.ibm.icu.impl.SimpleCache;
import com.ibm.icu.impl.SimplePatternFormatter;
import com.ibm.icu.math.BigDecimal;
import com.ibm.icu.text.PluralRules.Factory;
import com.ibm.icu.text.PluralRules.StandardPluralCategories;
import com.ibm.icu.util.Currency;
import com.ibm.icu.util.CurrencyAmount;
import com.ibm.icu.util.Measure;
import com.ibm.icu.util.MeasureUnit;
import com.ibm.icu.util.TimeZone;
import com.ibm.icu.util.ULocale;
import com.ibm.icu.util.ULocale.Category;
import com.ibm.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 com.ibm.icu.text.UFormat
 * @author Alan Liu
 * @stable ICU 3.0
 */
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.
     * 
     * @stable ICU 53
     */
    // Be sure to update MeasureUnitTest.TestSerialFormatWidthEnum
    // when adding an enum value.
    public enum FormatWidth {

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

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

        /**
         * Brief. Use only a symbol for the unit when possible.
         * 
         * @stable ICU 53
         */
        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.
         * 
         * @stable ICU 53
         */
        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.
     * @stable ICU 53
     */
    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.
     * @draft ICU 54
     * @provisional This API might change or be removed in a future release.
     */
    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.
     * @stable ICU 53
     */
    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.
     * @draft ICU 54
     * @provisional This API might change or be removed in a future release.
     */
    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)
     * 
     * @stable ICU53
     */
    @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.
     * @draft ICU 53 (Retain)
     * @provisional This API might change or be removed in a future release.
     */
    @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.
     * @stable ICU 53
     */
    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.
     * @internal
     * @deprecated This API is ICU internal only.
     */
    @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.
     * @draft ICU 55
     * @provisional This API might change or be removed in a future release.
     */
    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...)
     * @stable ICU 53
     */
    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.
     * @stable ICU 53
     */
    @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}
     * @stable ICU 53
     */
    @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.
     * @stable ICU 53
     */
    public MeasureFormat.FormatWidth getWidth() {
        return formatWidth;
    }

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

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

    /**
     * Return a formatter for CurrencyAmount objects in the given
     * locale.
     * @param locale desired locale
     * @return a formatter object
     * @stable ICU 3.0
     */
    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
     * @draft ICU 54
     * @provisional This API might change or be removed in a future release.
     */
    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
     * @stable ICU 3.0
     */
    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}"
     * @internal
     * @deprecated This API is ICU internal only.
     */
    @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
     * @internal
     * @deprecated This API is ICU internal only.
     */
    @Deprecated
    public static String getRangePattern(ULocale forLocale, FormatWidth width) {
        return getRangeFormat(forLocale, width).toString();
    }
}
