/*
 **********************************************************************
 * Copyright (c) 2004-2014, 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.
     * 
     * @draft ICU 53
     * @provisional This API might change or be removed in a future release.
     */
    // Be sure to update MeasureUnitTest.TestSerialFormatWidthEnum
    // when adding an enum value.
    public enum FormatWidth {

        /**
         * Spell out everything.
         * 
         * @draft ICU 53
         * @provisional This API might change or be removed in a future release.
         */
        WIDE("units", ListFormatter.Style.DURATION, NumberFormat.PLURALCURRENCYSTYLE), 

        /**
         * Abbreviate when possible.
         * 
         * @draft ICU 53
         * @provisional This API might change or be removed in a future release.
         */
        SHORT("unitsShort", ListFormatter.Style.DURATION_SHORT, NumberFormat.ISOCURRENCYSTYLE), 

        /**
         * Brief. Use only a symbol for the unit when possible.
         * 
         * @draft ICU 53
         * @provisional This API might change or be removed in a future release.
         */
        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.
         * 
         * @draft ICU 53
         * @provisional This API might change or be removed in a future release.
         */
        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.
     * @draft ICU 53
     * @provisional This API might change or be removed in a future release.
     */
    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.
     * @draft ICU 53
     * @provisional This API might change or be removed in a future release.
     */
    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)
     * 
     * @draft ICU53
     * @provisional This API might change or be removed in a future release.
     */
    @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
     * @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.
     * @draft ICU 53
     * @provisional This API might change or be removed in a future release.
     */
    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()));
        }
    }
    
    /**
     * Like formatMeasures but formats with a per unit.
     * 
     * Will format to a string such as "5 kilometers, 300 meters per hour."
     * 
     * @param appendTo the formatted string appended here.
     * @param fieldPosition Identifies a field in the formatted text.
     * @param perUnit for the example above would be MeasureUnit.HOUR.
     * @param measures the measures to format.
     * @return appendTo.
     * @internal
     * @deprecated This API is ICU internal only.
     */
    @Deprecated
    public StringBuilder formatMeasuresPer(
            StringBuilder appendTo, FieldPosition fieldPosition, MeasureUnit perUnit, Measure... measures) {
        FieldPosition fpos = new FieldPosition(
                fieldPosition.getFieldAttribute(), fieldPosition.getField());
        int offset = withPerUnit(
                formatMeasures(new StringBuilder(), fpos, measures),
                perUnit,
                appendTo);
        if (fpos.getBeginIndex() != 0 || fpos.getEndIndex() != 0) {
            fieldPosition.setBeginIndex(fpos.getBeginIndex() + offset);
            fieldPosition.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...)
     * @draft ICU 53
     * @provisional This API might change or be removed in a future release.
     */
    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.
     * @draft ICU 53
     * @provisional This API might change or be removed in a future release.
     */
    @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}
     * @draft ICU 53
     * @provisional This API might change or be removed in a future release.
     */
    @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.
     * @draft ICU 53
     * @provisional This API might change or be removed in a future release.
     */
    public MeasureFormat.FormatWidth getWidth() {
        return formatWidth;
    }

    /**
     * Get the locale of this instance.
     * @draft ICU 53
     * @provisional This API might change or be removed in a future release.
     */
    public final ULocale getLocale() {
        return getLocale(ULocale.VALID_LOCALE);
    }

    /**
     * Get a copy of the number format.
     * @draft ICU 53
     * @provisional This API might change or be removed in a future release.
     */
    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_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) {
            fallback = styleMap.get(FormatWidth.WIDE);
        }
        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 withPerUnit(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.format(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.format(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.format(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.WIDE;
        }
        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();
    }
}
