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

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

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

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


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

    private final transient MeasureFormatData cache;

    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;

    private final transient NumericFormatters numericFormatters;

    private final transient ImmutableNumberFormat currencyFormat;

    private final transient ImmutableNumberFormat integerFormat;

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

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

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

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

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

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

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

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

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

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

        // Be sure to update the toFormatWidth and fromFormatWidth() functions
        // when adding an enum value.
        private static final int INDEX_COUNT = 3;  // NARROW.ordinal() + 1

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

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

        ListFormatter.Style getListFormatterStyle() {
            return listFormatterStyle;
        }

        int getCurrencyStyle() {
            return currencyStyle;
        }
    }

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

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

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

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

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

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

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

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

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

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

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

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

        final PluralRanges pluralRanges = Factory.getDefaultFactory().getPluralRanges(getLocale());
        StandardPlural resolvedPlural = pluralRanges.get(
                StandardPlural.fromString(keywordLow),
                StandardPlural.fromString(keywordHigh));

        String rangeFormatter = getRangeFormat(getLocale(), formatWidth);
        String formattedNumber = SimplePatternFormatter.formatCompiledPattern(rangeFormatter, 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, resolvedPlural, result);
            result.append(formattedNumber);
            appendReplacingCurrency(currencyFormat.getSuffix(highDouble >= 0), currencyUnit, resolvedPlural, 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 {
            String formatter =
                    getPluralFormatter(lowValue.getUnit(), formatWidth, resolvedPlural.ordinal());
            return SimplePatternFormatter.formatCompiledPattern(formatter, formattedNumber);
        }
    }

    private void appendReplacingCurrency(String affix, Currency unit, StandardPlural resolvedPlural, 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,
                                resolvedPlural.getKeyword(), null));
            }
            result.append(affix.substring(pos+replacement.length()));
        }
    }
    
    /**
     * Formats a single measure per unit. 
     * 
     * An example of such a formatted string is "3.5 meters per second."
     *
     * @param measure  the measure object. In above example, 3.5 meters.
     * @param perUnit  the per unit. In above example, it is MeasureUnit.SECOND
     * @param appendTo formatted string appended here.
     * @param pos      The field position.
     * @return appendTo.
     * @hide draft / provisional / internal are hidden on Android
     */
    public StringBuilder formatMeasurePerUnit(
            Measure measure,
            MeasureUnit perUnit,
            StringBuilder appendTo,
            FieldPosition pos) {
        MeasureUnit resolvedUnit = MeasureUnit.resolveUnitPerUnit(
                measure.getUnit(), perUnit);
        if (resolvedUnit != null) {
            Measure newMeasure = new Measure(measure.getNumber(), resolvedUnit);
            return formatMeasure(newMeasure, numberFormat, appendTo, pos);
        }
        FieldPosition fpos = new FieldPosition(
                pos.getFieldAttribute(), pos.getField());
        int offset = withPerUnitAndAppend(
                formatMeasure(measure, numberFormat, new StringBuilder(), fpos),
                perUnit,
                appendTo);
        if (fpos.getBeginIndex() != 0 || fpos.getEndIndex() != 0) {
            pos.setBeginIndex(fpos.getBeginIndex() + offset);
            pos.setEndIndex(fpos.getEndIndex() + offset);
        }
        return appendTo;
    }

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

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

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

    }   

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

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

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

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

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

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

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

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

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

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

    private MeasureFormat(
            ULocale locale,
            MeasureFormatData data,
            FormatWidth formatWidth,
            ImmutableNumberFormat format,
            PluralRules rules,
            NumericFormatters formatters,
            ImmutableNumberFormat currencyFormat,
            ImmutableNumberFormat integerFormat) {
        setLocale(locale, locale);
        this.cache = data;
        this.formatWidth = formatWidth;
        this.numberFormat = format;
        this.rules = rules;
        this.numericFormatters = formatters;
        this.currencyFormat = currencyFormat;
        this.integerFormat = integerFormat;
    }

    MeasureFormat() {
        // Make compiler happy by setting final fields to null.
        this.cache = null;
        this.formatWidth = null;
        this.numberFormat = null;
        this.rules = null;
        this.numericFormatters = null;
        this.currencyFormat = null;
        this.integerFormat = 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"));
    }

    /**
     * Sink for enumerating all of the measurement unit display names.
     * Contains inner sink classes, each one corresponding to a type of resource table.
     * The outer sink handles the top-level units, unitsNarrow, and unitsShort tables.
     *
     * More specific bundles (en_GB) are enumerated before their parents (en_001, en, root):
     * Only store a value if it is still missing, that is, it has not been overridden.
     *
     * C++: Each inner sink class has a reference to the main outer sink.
     * Java: Use non-static inner classes instead.
     */
    private static final class UnitDataSink extends UResource.TableSink {
        /**
         * Sink for a table of display patterns. For example,
         * unitsShort/duration/hour contains other{"{0} hrs"}.
         */
        class UnitPatternSink extends UResource.TableSink {
            String[] patterns;

            void setFormatterIfAbsent(int index, UResource.Value value, int minPlaceholders) {
                if (patterns == null) {
                    EnumMap<FormatWidth, String[]> styleToPatterns =
                            cacheData.unitToStyleToPatterns.get(unit);
                    if (styleToPatterns == null) {
                        styleToPatterns =
                                new EnumMap<FormatWidth, String[]>(FormatWidth.class);
                        cacheData.unitToStyleToPatterns.put(unit, styleToPatterns);
                    } else {
                        patterns = styleToPatterns.get(width);
                    }
                    if (patterns == null) {
                        patterns = new String[MeasureFormatData.PATTERN_COUNT];
                        styleToPatterns.put(width, patterns);
                    }
                }
                if (patterns[index] == null) {
                    patterns[index] = SimplePatternFormatter.compileToStringMinMaxPlaceholders(
                            value.getString(), sb, minPlaceholders, 1);
                }
            }

            @Override
            public void put(UResource.Key key, UResource.Value value) {
                if (key.contentEquals("dnam")) {
                    // Skip the unit display name for now.
                } else if (key.contentEquals("per")) {
                    // For example, "{0}/h".
                    // TODO: Set minPlaceholders=1
                    // after http://unicode.org/cldr/trac/ticket/9129 is fixed.
                    setFormatterIfAbsent(MeasureFormatData.PER_UNIT_INDEX, value, 0);
                } else {
                    // The key must be one of the plural form strings. For example:
                    // one{"{0} hr"}
                    // other{"{0} hrs"}
                    setFormatterIfAbsent(StandardPlural.indexFromString(key), value, 0);
                }
            }
        }
        UnitPatternSink patternSink = new UnitPatternSink();

        /**
         * Sink for a table of per-unit tables. For example,
         * unitsShort/duration contains tables for duration-unit subtypes day & hour.
         */
        class UnitSubtypeSink extends UResource.TableSink {
            @Override
            public UResource.TableSink getOrCreateTableSink(UResource.Key key, int initialSize) {
                // Should we ignore or reject unknown units?
                unit = MeasureUnit.internalGetInstance(type, key.toString());  // never null
                // Trigger a fresh lookup of the patterns for this unit+width.
                patternSink.patterns = null;
                return patternSink;
            }
        }
        UnitSubtypeSink subtypeSink = new UnitSubtypeSink();

        /**
         * Sink for compound x-per-y display pattern. For example,
         * unitsShort/compound/per may be "{0}/{1}".
         */
        class UnitCompoundSink extends UResource.TableSink {
            @Override
            public void put(UResource.Key key, UResource.Value value) {
                if (key.contentEquals("per")) {
                    cacheData.styleToPerPattern.put(width,
                            SimplePatternFormatter.compileToStringMinMaxPlaceholders(
                                    value.getString(), sb, 2, 2));
                }
            }
        }
        UnitCompoundSink compoundSink = new UnitCompoundSink();

        /**
         * Sink for a table of unit type tables. For example,
         * unitsShort contains tables for area & duration.
         * It also contains a table for the compound/per pattern.
         */
        class UnitTypeSink extends UResource.TableSink {
            @Override
            public UResource.TableSink getOrCreateTableSink(UResource.Key key, int initialSize) {
                if (key.contentEquals("currency")) {
                    // Skip.
                } else if (key.contentEquals("compound")) {
                    if (!cacheData.hasPerFormatter(width)) {
                        return compoundSink;
                    }
                } else {
                    type = key.toString();
                    return subtypeSink;
                }
                return null;
            }
        }
        UnitTypeSink typeSink = new UnitTypeSink();

        UnitDataSink(MeasureFormatData outputData) {
            cacheData = outputData;
        }
        @Override
        public void put(UResource.Key key, UResource.Value value) {
            // Handle aliases like
            // units:alias{"/LOCALE/unitsShort"}
            // which should only occur in the root bundle.
            if (value.getType() != ICUResourceBundle.ALIAS) { return; }
            FormatWidth sourceWidth = widthFromKey(key);
            if (sourceWidth == null) {
                // Alias from something we don't care about.
                return;
            }
            FormatWidth targetWidth = widthFromAlias(value);
            if (targetWidth == null) {
                // We do not recognize what to fall back to.
                throw new ICUException("Units data fallback from " + key +
                        " to unknown " + value.getAliasString());
            }
            // Check that we do not fall back to another fallback.
            if (cacheData.widthFallback[targetWidth.ordinal()] != null) {
                throw new ICUException("Units data fallback from " + key +
                        " to " + value.getAliasString() + " which falls back to something else");
            }
            cacheData.widthFallback[sourceWidth.ordinal()] = targetWidth;
        }
        @Override
        public UResource.TableSink getOrCreateTableSink(UResource.Key key, int initialSize) {
            if ((width = widthFromKey(key)) != null) {
                return typeSink;
            }
            return null;
        }

        static FormatWidth widthFromKey(UResource.Key key) {
            if (key.startsWith("units")) {
                if (key.length() == 5) {
                    return FormatWidth.WIDE;
                } else if (key.regionMatches(5, "Short")) {
                    return FormatWidth.SHORT;
                } else if (key.regionMatches(5, "Narrow")) {
                    return FormatWidth.NARROW;
                }
            }
            return null;
        }

        static FormatWidth widthFromAlias(UResource.Value value) {
            String s = value.getAliasString();
            // For example: "/LOCALE/unitsShort"
            if (s.startsWith("/LOCALE/units")) {
                if (s.length() == 13) {
                    return FormatWidth.WIDE;
                } else if (s.length() == 18 && s.endsWith("Short")) {
                    return FormatWidth.SHORT;
                } else if (s.length() == 19 && s.endsWith("Narrow")) {
                    return FormatWidth.NARROW;
                }
            }
            return null;
        }

        // Output data.
        MeasureFormatData cacheData;

        // Path to current data.
        FormatWidth width;
        String type;
        MeasureUnit unit;

        // Temporary
        StringBuilder sb = new StringBuilder();
    }

    /**
     * Returns formatting data for all MeasureUnits except for currency ones.
     */
    private static MeasureFormatData loadLocaleData(ULocale locale) {
        ICUResourceBundle resource =
                (ICUResourceBundle)UResourceBundle.getBundleInstance(ICUData.ICU_UNIT_BASE_NAME, locale);
        MeasureFormatData cacheData = new MeasureFormatData();
        UnitDataSink sink = new UnitDataSink(cacheData);
        resource.getAllTableItemsWithFallback("", sink);
        return cacheData;
    }

    private static final FormatWidth getRegularWidth(FormatWidth width) {
        if (width == FormatWidth.NUMERIC) {
            return FormatWidth.NARROW;
        }
        return width;
    }

    private String getFormatterOrNull(MeasureUnit unit, FormatWidth width, int index) {
        width = getRegularWidth(width);
        Map<FormatWidth, String[]> styleToPatterns = cache.unitToStyleToPatterns.get(unit);
        String[] patterns = styleToPatterns.get(width);
        if (patterns != null && patterns[index] != null) {
            return patterns[index];
        }
        FormatWidth fallbackWidth = cache.widthFallback[width.ordinal()];
        if (fallbackWidth != null) {
            patterns = styleToPatterns.get(fallbackWidth);
            if (patterns != null && patterns[index] != null) {
                return patterns[index];
            }
        }
        return null;
    }

    private String getFormatter(MeasureUnit unit, FormatWidth width, int index) {
        String pattern = getFormatterOrNull(unit, width, index);
        if (pattern == null) {
            throw new MissingResourceException(
                    "no formatting pattern for " + unit + ", width " + width + ", index " + index,
                    null, null);
        }
        return pattern;
    }

    private String getPluralFormatter(MeasureUnit unit, FormatWidth width, int index) {
        if (index != StandardPlural.OTHER_INDEX) {
            String pattern = getFormatterOrNull(unit, width, index);
            if (pattern != null) {
                return pattern;
            }
        }
        return getFormatter(unit, width, StandardPlural.OTHER_INDEX);
    }

    private String getPerFormatter(FormatWidth width) {
        width = getRegularWidth(width);
        String perPattern = cache.styleToPerPattern.get(width);
        if (perPattern != null) {
            return perPattern;
        }
        FormatWidth fallbackWidth = cache.widthFallback[width.ordinal()];
        if (fallbackWidth != null) {
            perPattern = cache.styleToPerPattern.get(fallbackWidth);
            if (perPattern != null) {
                return perPattern;
            }
        }
        throw new MissingResourceException("no x-per-y pattern for width " + width, null, null);
    }

    private int withPerUnitAndAppend(
            CharSequence formatted, MeasureUnit perUnit, StringBuilder appendTo) {
        int[] offsets = new int[1];
        String perUnitPattern =
                getFormatterOrNull(perUnit, formatWidth, MeasureFormatData.PER_UNIT_INDEX);
        if (perUnitPattern != null) {
            SimplePatternFormatter.formatAndAppend(perUnitPattern, appendTo, offsets, formatted);
            return offsets[0];
        }
        String perPattern = getPerFormatter(formatWidth);
        String pattern = getPluralFormatter(perUnit, formatWidth, StandardPlural.ONE.ordinal());
        String perUnitString = SimplePatternFormatter.getTextWithNoPlaceholders(pattern).trim();
        SimplePatternFormatter.formatAndAppend(
                perPattern, 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) {
        Number n = measure.getNumber();
        MeasureUnit unit = measure.getUnit();
        if (unit instanceof Currency) {
            return appendTo.append(
                    currencyFormat.format(
                            new CurrencyAmount(n, (Currency) unit),
                            new StringBuffer(),
                            fieldPosition));

        }
        StringBuffer formattedNumber = new StringBuffer();
        StandardPlural pluralForm = QuantityFormatter.selectPlural(
                n, nf.nf, rules, formattedNumber, fieldPosition);
        String formatter = getPluralFormatter(unit, formatWidth, pluralForm.ordinal());
        return QuantityFormatter.format(formatter, formattedNumber, appendTo, fieldPosition);
    }

    /**
     * Instances contain all MeasureFormat specific data for a particular locale.
     * This data is cached. It is never copied, but is shared via shared pointers.
     *
     * Note: We might change the cache data to have
     * an array[WIDTH_INDEX_COUNT] or EnumMap<FormatWidth, ...> of
     * complete sets of unit & per patterns,
     * to correspond to the resource data and its aliases.
     */
    private static final class MeasureFormatData {
        static final int PER_UNIT_INDEX = StandardPlural.COUNT;
        static final int PATTERN_COUNT = PER_UNIT_INDEX + 1;

        boolean hasPerFormatter(FormatWidth width) {
            return styleToPerPattern.containsKey(width);
        }

        /**
         * Redirection data from root-bundle, top-level sideways aliases.
         * - null: initial value, just fall back to root
         * - FormatWidth.WIDE/SHORT/NARROW: sideways alias for missing data
         */
        final FormatWidth widthFallback[] = new FormatWidth[FormatWidth.INDEX_COUNT];
        /** Measure unit -> format width -> array of patterns ("{0} meters") (plurals + PER_UNIT_INDEX) */
        final Map<MeasureUnit, EnumMap<FormatWidth, String[]>> unitToStyleToPatterns =
                new HashMap<MeasureUnit, EnumMap<FormatWidth, String[]>>();
        final EnumMap<FormatWidth, String> styleToPerPattern =
                new EnumMap<FormatWidth, String>(FormatWidth.class);;
    }

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

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

    /**
     * Return a formatter (compiled SimplePatternFormatter pattern) for a range, such as "{0}–{1}".
     * @param forLocale locale to get the format for
     * @param width the format width
     * @return range formatter, such as "{0}–{1}"
     * @deprecated This API is ICU internal only.
     * @hide original deprecated declaration
     * @hide draft / provisional / internal are hidden on Android
     */
    @Deprecated
    public static String getRangeFormat(ULocale forLocale, FormatWidth width) {
        // TODO fix Hack for French
        if (forLocale.getLanguage().equals("fr")) {
            return getRangeFormat(ULocale.ROOT, width);
        }
        String 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.compileToStringMinMaxPlaceholders(resultString, new StringBuilder(), 2, 2);
            localeIdToRangeFormat.put(forLocale, result);
            if (!forLocale.equals(realLocale)) {
                localeIdToRangeFormat.put(realLocale, result);
            }
        }
        return result;
    }
}
