// © 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
/*
 ********************************************************************************
 * Copyright (C) 2006-2016, Google, International Business Machines Corporation
 * and others. All Rights Reserved.
 ********************************************************************************
 */
package com.ibm.icu.text;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;

import com.ibm.icu.impl.ICUCache;
import com.ibm.icu.impl.ICUData;
import com.ibm.icu.impl.ICUResourceBundle;
import com.ibm.icu.impl.PatternTokenizer;
import com.ibm.icu.impl.SimpleCache;
import com.ibm.icu.impl.SimpleFormatterImpl;
import com.ibm.icu.impl.UResource;
import com.ibm.icu.util.Calendar;
import com.ibm.icu.util.Freezable;
import com.ibm.icu.util.ICUCloneNotSupportedException;
import com.ibm.icu.util.Region;
import com.ibm.icu.util.ULocale;
import com.ibm.icu.util.ULocale.Category;
import com.ibm.icu.util.UResourceBundle;

/**
 * This class provides flexible generation of date format patterns, like
 * "yy-MM-dd". The user can build up the generator by adding successive
 * patterns. Once that is done, a query can be made using a "skeleton", which is
 * a pattern which just includes the desired fields and lengths. The generator
 * will return the "best fit" pattern corresponding to that skeleton.
 * <p>
 * The main method people will use is getBestPattern(String skeleton), since
 * normally this class is pre-built with data from a particular locale. However,
 * generators can be built directly from other data as well.
 * @stable ICU 3.6
 */
public class DateTimePatternGenerator implements Freezable<DateTimePatternGenerator>, Cloneable {
    private static final boolean DEBUG = false;

    // debugging flags
    //static boolean SHOW_DISTANCE = false;
    // TODO add hack to fix months for CJK, as per bug ticket 1099

    /**
     * Create empty generator, to be constructed with addPattern(...) etc.
     * @stable ICU 3.6
     */
    public static DateTimePatternGenerator getEmptyInstance() {
        DateTimePatternGenerator instance = new DateTimePatternGenerator();
        instance.addCanonicalItems();
        instance.fillInMissing();
        return instance;
    }

    /**
     * Only for use by subclasses
     * @stable ICU 3.6
     */
    protected DateTimePatternGenerator() {
    }

    /**
     * Construct a flexible generator according to data for the default <code>FORMAT</code> locale.
     * @see Category#FORMAT
     * @stable ICU 3.6
     */
    public static DateTimePatternGenerator getInstance() {
        return getInstance(ULocale.getDefault(Category.FORMAT));
    }

    /**
     * Construct a flexible generator according to data for a given locale.
     * @param uLocale The locale to pass.
     * @stable ICU 3.6
     */
    public static DateTimePatternGenerator getInstance(ULocale uLocale) {
        return getFrozenInstance(uLocale).cloneAsThawed();
    }

    /**
     * Construct a flexible generator according to data for a given locale.
     * @param locale The {@link java.util.Locale} to pass.
     * @stable ICU 54
     */
    public static DateTimePatternGenerator getInstance(Locale locale) {
        return getInstance(ULocale.forLocale(locale));
    }

    /**
     * Construct a frozen instance of DateTimePatternGenerator for a
     * given locale.  This method returns a cached frozen instance of
     * DateTimePatternGenerator, so less expensive than the regular
     * factory method.
     * @param uLocale The locale to pass.
     * @return A frozen DateTimePatternGenerator.
     * @internal
     * @deprecated This API is ICU internal only.
     */
    @Deprecated
    public static DateTimePatternGenerator getFrozenInstance(ULocale uLocale) {
        String localeKey = uLocale.toString();
        DateTimePatternGenerator result = DTPNG_CACHE.get(localeKey);
        if (result != null) {
            return result;
        }

        result = new DateTimePatternGenerator();
        result.initData(uLocale, false);

        // freeze and cache
        result.freeze();
        DTPNG_CACHE.put(localeKey, result);
        return result;
    }

    /**
     * Construct a non-frozen instance of DateTimePatternGenerator for a
     * given locale that skips using the standard date and time patterns.
     * Because this is different than the normal instance for the locale,
     * it does not set or use the cache.
     * @param uLocale The locale to pass.
     * @internal
     * @deprecated This API is ICU internal only.
     */
    @Deprecated
    public static DateTimePatternGenerator getInstanceNoStdPat(ULocale uLocale) {
        DateTimePatternGenerator result = new DateTimePatternGenerator();
        result.initData(uLocale, true);
        return result;
    }

    private void initData(ULocale uLocale, boolean skipStdPatterns) {
        // This instance of PatternInfo is required for calling some functions.  It is used for
        // passing additional information to the caller.  We won't use this extra information, but
        // we still need to make a temporary instance.
        PatternInfo returnInfo = new PatternInfo();

        addCanonicalItems();
        if (!skipStdPatterns) { // skip to prevent circular dependency when used by Calendar
            addICUPatterns(returnInfo, uLocale);
        }
        addCLDRData(returnInfo, uLocale);
        if (!skipStdPatterns) { // also skip to prevent circular dependency from Calendar
            setDateTimeFromCalendar(uLocale);
        } else {
            // instead, since from Calendar we do not care about dateTimePattern, use a fallback
            setDateTimeFormat("{1} {0}");
        }
        setDecimalSymbols(uLocale);
        getAllowedHourFormats(uLocale);
        fillInMissing();
    }

    private void addICUPatterns(PatternInfo returnInfo, ULocale uLocale) {
        // first load with the ICU patterns
        for (int i = DateFormat.FULL; i <= DateFormat.SHORT; ++i) {
            SimpleDateFormat df = (SimpleDateFormat) DateFormat.getDateInstance(i, uLocale);
            addPattern(df.toPattern(), false, returnInfo);
            df = (SimpleDateFormat) DateFormat.getTimeInstance(i, uLocale);
            addPattern(df.toPattern(), false, returnInfo);

            if (i == DateFormat.SHORT) {
                consumeShortTimePattern(df.toPattern(), returnInfo);
            }
        }
    }

    private String getCalendarTypeToUse(ULocale uLocale) {
        // Get the correct calendar type
        // TODO: C++ and Java are inconsistent (see #9952).
        String calendarTypeToUse = uLocale.getKeywordValue("calendar");
        if ( calendarTypeToUse == null ) {
            String[] preferredCalendarTypes = Calendar.getKeywordValuesForLocale("calendar", uLocale, true);
            calendarTypeToUse = preferredCalendarTypes[0]; // the most preferred calendar
        }
        if ( calendarTypeToUse == null ) {
            calendarTypeToUse = "gregorian"; // fallback
        }
        return calendarTypeToUse;
    }

    private void consumeShortTimePattern(String shortTimePattern, PatternInfo returnInfo) {
        // keep this pattern to populate other time field
        // combination patterns by hackTimes later in this method.
        // ICU-20383 No longer set defaultHourFormatChar to the hour format character from
        // this pattern; instead it is set from LOCALE_TO_ALLOWED_HOUR which now
        // includes entries for both preferred and allowed formats.

        // some languages didn't add mm:ss or HH:mm, so put in a hack to compute that from the short time.
        hackTimes(returnInfo, shortTimePattern);
    }

    private class AppendItemFormatsSink extends UResource.Sink {
        @Override
        public void put(UResource.Key key, UResource.Value value, boolean noFallback) {
            int field = getAppendFormatNumber(key);
            if (field < 0) { return; }
            if (getAppendItemFormat(field) == null) {
                setAppendItemFormat(field, value.toString());
            }
        }
    }

    private class AppendItemNamesSink extends UResource.Sink {
        @Override
        public void put(UResource.Key key, UResource.Value value, boolean noFallback) {
            int fieldAndWidth = getCLDRFieldAndWidthNumber(key);
            if (fieldAndWidth == -1) { return; }
            int field = fieldAndWidth / DisplayWidth.COUNT;
            DisplayWidth width = CLDR_FIELD_WIDTH[fieldAndWidth % DisplayWidth.COUNT];
            UResource.Table detailsTable = value.getTable();
            if (detailsTable.findValue("dn", value)) {
                if (getFieldDisplayName(field, width) == null) {
                    setFieldDisplayName(field, width, value.toString());
                }
            }
        }
    }

    private void fillInMissing() {
        for (int i = 0; i < TYPE_LIMIT; ++i) {
            if (getAppendItemFormat(i) == null) {
                setAppendItemFormat(i, "{0} \u251C{2}: {1}\u2524");
            }
            if (getFieldDisplayName(i, DisplayWidth.WIDE) == null) {
                setFieldDisplayName(i, DisplayWidth.WIDE, "F" + i);
            }
            if (getFieldDisplayName(i, DisplayWidth.ABBREVIATED) == null) {
                setFieldDisplayName(i, DisplayWidth.ABBREVIATED, getFieldDisplayName(i, DisplayWidth.WIDE));
            }
            if (getFieldDisplayName(i, DisplayWidth.NARROW) == null) {
                setFieldDisplayName(i, DisplayWidth.NARROW, getFieldDisplayName(i, DisplayWidth.ABBREVIATED));
            }
       }
    }

    private class AvailableFormatsSink extends UResource.Sink {
        PatternInfo returnInfo;
        public AvailableFormatsSink(PatternInfo returnInfo) {
            this.returnInfo = returnInfo;
        }

        @Override
        public void put(UResource.Key key, UResource.Value value, boolean isRoot) {
            String formatKey = key.toString();
            if (!isAvailableFormatSet(formatKey)) {
                setAvailableFormat(formatKey);
                // Add pattern with its associated skeleton. Override any duplicate derived from std patterns,
                // but not a previous availableFormats entry:
                String formatValue = value.toString();
                addPatternWithSkeleton(formatValue, formatKey, !isRoot, returnInfo);
            }
        }
    }

    private void addCLDRData(PatternInfo returnInfo, ULocale uLocale) {
        ICUResourceBundle rb = (ICUResourceBundle) UResourceBundle.getBundleInstance(ICUData.ICU_BASE_NAME, uLocale);
        String calendarTypeToUse = getCalendarTypeToUse(uLocale);

        //      ICU4J getWithFallback does not work well when
        //      1) A nested table is an alias to /LOCALE/...
        //      2) getWithFallback is called multiple times for going down hierarchical resource path
        //      #9987 resolved the issue of alias table when full path is specified in getWithFallback,
        //      but there is no easy solution when the equivalent operation is done by multiple operations.
        //      This issue is addressed in #9964.

        // Load append item formats.
        AppendItemFormatsSink appendItemFormatsSink = new AppendItemFormatsSink();
        try {
            rb.getAllChildrenWithFallback(
                    "calendar/" + calendarTypeToUse + "/appendItems",
                    appendItemFormatsSink);
        }catch(MissingResourceException e) {
        }

        // Load CLDR item names.
        AppendItemNamesSink appendItemNamesSink = new AppendItemNamesSink();
        try {
            rb.getAllChildrenWithFallback(
                    "fields",
                    appendItemNamesSink);
        }catch(MissingResourceException e) {
        }

        // Load the available formats from CLDR.
        AvailableFormatsSink availableFormatsSink = new AvailableFormatsSink(returnInfo);
        try {
            rb.getAllChildrenWithFallback(
                    "calendar/" + calendarTypeToUse + "/availableFormats",
                    availableFormatsSink);
        } catch (MissingResourceException e) {
        }
    }

    private void setDateTimeFromCalendar(ULocale uLocale) {
        Calendar cal = Calendar.getInstance(uLocale);
        for (int style = DateFormat.FULL; style <= DateFormat.SHORT; style++) {
            String dateTimeFormat = Calendar.getDateAtTimePattern(cal, uLocale, style);
            setDateTimeFormat(style, dateTimeFormat);
        }
    }

    private void setDecimalSymbols(ULocale uLocale) {
        // decimal point for seconds
        DecimalFormatSymbols dfs = new DecimalFormatSymbols(uLocale);
        setDecimal(String.valueOf(dfs.getDecimalSeparator()));
    }

    private static final String[] LAST_RESORT_ALLOWED_HOUR_FORMAT = {"H"};

    private String[] getAllowedHourFormatsLangCountry(String language, String country) {
        String langCountry = language + "_" + country;
        String[] list = LOCALE_TO_ALLOWED_HOUR.get(langCountry);
        if (list == null) {
            list = LOCALE_TO_ALLOWED_HOUR.get(country);
        }
        return list;
    }

    private void getAllowedHourFormats(ULocale uLocale) {
        // key can be either region or locale (lang_region)
        //        ZW{
        //            allowed{
        //                "h",
        //                "H",
        //            }
        //            preferred{"h"}
        //        }
        //        af_ZA{
        //            allowed{
        //                "h",
        //                "H",
        //                "hB",
        //                "hb",
        //            }
        //            preferred{"h"}
        //        }

        String language = uLocale.getLanguage();
        String country = uLocale.getCountry();
        if (language.isEmpty() || country.isEmpty()) {
            // Note: addLikelySubtags is documented not to throw in Java,
            // unlike in C++.
            ULocale max = ULocale.addLikelySubtags(uLocale);
            language = max.getLanguage();
            country = max.getCountry();
        }

        if (language.isEmpty()) {
            // Unexpected, but fail gracefully
            language = "und";
        }
        if (country.isEmpty()) {
            country = "001";
        }

        String[] list = getAllowedHourFormatsLangCountry(language, country);

        // We need to check if there is an hour cycle on locale
        Character defaultCharFromLocale = null;
        String hourCycle = uLocale.getKeywordValue("hours");
        if (hourCycle != null) {
            switch(hourCycle) {
                case "h24":
                    defaultCharFromLocale = 'k';
                    break;
                case "h23":
                    defaultCharFromLocale = 'H';
                    break;
                case "h12":
                    defaultCharFromLocale = 'h';
                    break;
                case "h11":
                    defaultCharFromLocale = 'K';
                    break;
            }
        }

        // Check if the region has an alias
        if (list == null) {
            try {
                Region region = Region.getInstance(country);
                country = region.toString();
                list = getAllowedHourFormatsLangCountry(language, country);
            } catch (IllegalArgumentException e) {
                // invalid region; fall through
            }
        }

        if (list != null) {
            defaultHourFormatChar = defaultCharFromLocale != null ? defaultCharFromLocale : list[0].charAt(0);
            allowedHourFormats = Arrays.copyOfRange(list, 1, list.length - 1);
        } else {
            allowedHourFormats = LAST_RESORT_ALLOWED_HOUR_FORMAT;
            defaultHourFormatChar = (defaultCharFromLocale != null) ? defaultCharFromLocale : allowedHourFormats[0].charAt(0);
        }
    }

    private static class DayPeriodAllowedHoursSink extends UResource.Sink {
        HashMap<String, String[]> tempMap;

        private DayPeriodAllowedHoursSink(HashMap<String, String[]> tempMap) {
            this.tempMap = tempMap;
        }

        @Override
        public void put(UResource.Key key, UResource.Value value, boolean noFallback) {
            UResource.Table timeData = value.getTable();
            for (int i = 0; timeData.getKeyAndValue(i, key, value); ++i) {
                String regionOrLocale = key.toString();
                UResource.Table formatList = value.getTable();
                String[] allowed = null;
                String preferred = null;
                for (int j = 0; formatList.getKeyAndValue(j, key, value); ++j) {
                    if (key.contentEquals("allowed")) {
                        allowed = value.getStringArrayOrStringAsArray();
                    } else if (key.contentEquals("preferred")) {
                        preferred = value.getString();
                    }
                }
                // below we construct a list[] that has an entry for the "preferred" value at [0],
                 // followed by 1 or more entries for the "allowed" values.
                String[] list = null;
                if (allowed!=null && allowed.length > 0) {
                    list = new String[allowed.length + 1];
                    list[0] = (preferred != null)? preferred:  allowed[0];
                    System.arraycopy(allowed, 0, list, 1, allowed.length);
                } else {
                    // fallback handling for missing data
                    list = new String[2];
                    list[0] = (preferred != null)? preferred: LAST_RESORT_ALLOWED_HOUR_FORMAT[0];
                    list[1] = list[0];
                }
                tempMap.put(regionOrLocale, list);
            }
        }
    }

    // Get the data for dayperiod C.
    static final Map<String, String[]> LOCALE_TO_ALLOWED_HOUR;
    static {
        HashMap<String, String[]> temp = new HashMap<>();
        ICUResourceBundle suppData = (ICUResourceBundle)ICUResourceBundle.getBundleInstance(
                ICUData.ICU_BASE_NAME,
                "supplementalData",
                ICUResourceBundle.ICU_DATA_CLASS_LOADER);

        DayPeriodAllowedHoursSink allowedHoursSink = new DayPeriodAllowedHoursSink(temp);
        suppData.getAllItemsWithFallback("timeData", allowedHoursSink);

        LOCALE_TO_ALLOWED_HOUR = Collections.unmodifiableMap(temp);
    }

    /**
     * @internal
     * @deprecated This API is ICU internal only.
     */
    @Deprecated
    public char getDefaultHourFormatChar() {
        return defaultHourFormatChar;
    }

    /**
     * @internal
     * @deprecated This API is ICU internal only.
     */
    @Deprecated
    public void setDefaultHourFormatChar(char defaultHourFormatChar) {
        this.defaultHourFormatChar = defaultHourFormatChar;
    }

    private void hackTimes(PatternInfo returnInfo, String shortTimePattern) {
        fp.set(shortTimePattern);
        StringBuilder mmss = new StringBuilder();
        // to get mm:ss, we strip all but mm literal ss
        boolean gotMm = false;
        for (int i = 0; i < fp.items.size(); ++i) {
            Object item = fp.items.get(i);
            if (item instanceof String) {
                if (gotMm) {
                    mmss.append(fp.quoteLiteral(item.toString()));
                }
            } else {
                char ch = item.toString().charAt(0);
                if (ch == 'm') {
                    gotMm = true;
                    mmss.append(item);
                } else if (ch == 's') {
                    if (!gotMm) {
                        break; // failed
                    }
                    mmss.append(item);
                    addPattern(mmss.toString(), false, returnInfo);
                    break;
                } else if (gotMm || ch == 'z' || ch == 'Z' || ch == 'v' || ch == 'V') {
                    break; // failed
                }
            }
        }
        // to get hh:mm, we strip (literal ss) and (literal S)
        // the easiest way to do this is to mark the stuff we want to nuke, then remove it in a second pass.
        BitSet variables = new BitSet();
        BitSet nuke = new BitSet();
        for (int i = 0; i < fp.items.size(); ++i) {
            Object item = fp.items.get(i);
            if (item instanceof VariableField) {
                variables.set(i);
                char ch = item.toString().charAt(0);
                if (ch == 's' || ch == 'S') {
                    nuke.set(i);
                    for (int j = i-1; j >= 0; ++j) {
                        if (variables.get(j)) break;
                        nuke.set(i);
                    }
                }
            }
        }
        String hhmm = getFilteredPattern(fp, nuke);
        addPattern(hhmm, false, returnInfo);
    }

    private static String getFilteredPattern(FormatParser fp, BitSet nuke) {
        StringBuilder result = new StringBuilder();
        for (int i = 0; i < fp.items.size(); ++i) {
            if (nuke.get(i)) continue;
            Object item = fp.items.get(i);
            if (item instanceof String) {
                result.append(fp.quoteLiteral(item.toString()));
            } else {
                result.append(item.toString());
            }
        }
        return result.toString();
    }

    /*private static int getAppendNameNumber(String string) {
        for (int i = 0; i < CLDR_FIELD_NAME.length; ++i) {
            if (CLDR_FIELD_NAME[i].equals(string)) return i;
        }
        return -1;
    }*/

    /**
     * @internal
     * @deprecated This API is ICU internal only.
     */
    @Deprecated
    public static int getAppendFormatNumber(UResource.Key key) {
        for (int i = 0; i < CLDR_FIELD_APPEND.length; ++i) {
            if (key.contentEquals(CLDR_FIELD_APPEND[i])) {
                return i;
            }
        }
        return -1;
    }

    /**
     * @internal CLDR
     * @deprecated This API is ICU internal only.
     */
    @Deprecated
    public static int getAppendFormatNumber(String string) {
        for (int i = 0; i < CLDR_FIELD_APPEND.length; ++i) {
            if (CLDR_FIELD_APPEND[i].equals(string)) {
                return i;
            }
        }
        return -1;
    }

    private static int getCLDRFieldAndWidthNumber(UResource.Key key) {
        for (int i = 0; i < CLDR_FIELD_NAME.length; ++i) {
            for (int j = 0; j < DisplayWidth.COUNT; ++j) {
                String fullKey = CLDR_FIELD_NAME[i].concat(CLDR_FIELD_WIDTH[j].cldrKey());
                if (key.contentEquals(fullKey)) {
                    return i * DisplayWidth.COUNT + j;
                }
            }
        }
        return -1;
    }

    /**
     * Return the best pattern matching the input skeleton. It is guaranteed to
     * have all of the fields in the skeleton.
     * <p>Example code:{@.jcite com.ibm.icu.samples.text.datetimepatterngenerator.DateTimePatternGeneratorSample:---getBestPatternExample}
     * @param skeleton The skeleton is a pattern containing only the variable fields.
     *            For example, "MMMdd" and "mmhh" are skeletons.
     * @return Best pattern matching the input skeleton.
     * @stable ICU 3.6
     */
    public String getBestPattern(String skeleton) {
        return getBestPattern(skeleton, null, MATCH_NO_OPTIONS);
    }

    /**
     * Return the best pattern matching the input skeleton. It is guaranteed to
     * have all of the fields in the skeleton.
     *
     * @param skeleton The skeleton is a pattern containing only the variable fields.
     *            For example, "MMMdd" and "mmhh" are skeletons.
     * @param options MATCH_xxx options for forcing the length of specified fields in
     *            the returned pattern to match those in the skeleton (when this would
     *            not happen otherwise). For default behavior, use MATCH_NO_OPTIONS.
     * @return Best pattern matching the input skeleton (and options).
     * @stable ICU 4.4
     */
    public String getBestPattern(String skeleton, int options) {
        return getBestPattern(skeleton, null, options);
    }

    /*
     * getBestPattern which takes optional skip matcher
     */
    private String getBestPattern(String skeleton, DateTimeMatcher skipMatcher, int options) {
        EnumSet<DTPGflags> flags = EnumSet.noneOf(DTPGflags.class);
        // Replace hour metacharacters 'j', 'C', and 'J', set flags as necessary
        String skeletonMapped = mapSkeletonMetacharacters(skeleton, flags);
        String datePattern, timePattern;
        synchronized(this) {
            current.set(skeletonMapped, fp, false);
            PatternWithMatcher bestWithMatcher = getBestRaw(current, -1, _distanceInfo, skipMatcher);
            if (_distanceInfo.missingFieldMask == 0 && _distanceInfo.extraFieldMask == 0) {
                // we have a good item. Adjust the field types
                return adjustFieldTypes(bestWithMatcher, current, flags, options);
            }
            int neededFields = current.getFieldMask();

            // otherwise break up by date and time.
            datePattern = getBestAppending(current, neededFields & DATE_MASK, _distanceInfo, skipMatcher, flags, options);
            timePattern = getBestAppending(current, neededFields & TIME_MASK, _distanceInfo, skipMatcher, flags, options);
        }

        if (datePattern == null) return timePattern == null ? "" : timePattern;
        if (timePattern == null) return datePattern;
        // determine which dateTimeFormat to use
        String canonicalSkeleton = current.toCanonicalString(); // month fields use M, weekday fields use E
        int style = DateFormat.SHORT;
        int monthFieldLen = 0;
        int monthFieldOffset = canonicalSkeleton.indexOf('M');
        if (monthFieldOffset >= 0) {
            monthFieldLen = 1 + canonicalSkeleton.lastIndexOf('M') - monthFieldOffset;
        }
        if (monthFieldLen == 4) {
            if (canonicalSkeleton.indexOf('E') >= 0) {
                style = DateFormat.FULL;
            } else {
                style = DateFormat.LONG;
            }
        } else if (monthFieldLen == 3) {
            style = DateFormat.MEDIUM;
        }
        // and now use it to compose date and time
        return SimpleFormatterImpl.formatRawPattern(
                getDateTimeFormat(style), 2, 2, timePattern, datePattern);
    }

    /*
     * Map a skeleton that may have metacharacters jJC to one without, by replacing
     * the metacharacters with locale-appropriate fields of of h/H/k/K and of a/b/B
     * (depends on defaultHourFormatChar and allowedHourFormats being set, which in
     * turn depends on initData having been run). This method also updates the flags
     * as necessary. Returns the updated skeleton.
     */
    private String mapSkeletonMetacharacters(String skeleton, EnumSet<DTPGflags> flags) {
        StringBuilder skeletonCopy = new StringBuilder();
        boolean inQuoted = false;
        for (int patPos = 0; patPos < skeleton.length(); patPos++) {
            char patChr = skeleton.charAt(patPos);
            if (patChr == '\'') {
                inQuoted = !inQuoted;
            } else if (!inQuoted) {
                // Handle special mappings for 'j' and 'C' in which fields lengths
                // 1,3,5 => hour field length 1
                // 2,4,6 => hour field length 2
                // 1,2 => abbreviated dayPeriod (field length 1..3)
                // 3,4 => long dayPeriod (field length 4)
                // 5,6 => narrow dayPeriod (field length 5)
                if (patChr == 'j' || patChr == 'C') {
                    int extraLen = 0; // 1 less than total field length
                    while (patPos+1 < skeleton.length() && skeleton.charAt(patPos+1) == patChr) {
                        extraLen++;
                        patPos++;
                    }
                    int hourLen = 1 + (extraLen & 1);
                    int dayPeriodLen = (extraLen < 2)? 1: 3 + (extraLen >> 1);
                    char hourChar = 'h';
                    char dayPeriodChar = 'a';
                    if (patChr == 'j') {
                        hourChar = defaultHourFormatChar;
                    } else { // patChr == 'C'
                        String bestAllowed = allowedHourFormats[0];
                        hourChar = bestAllowed.charAt(0);
                        // in #13183 just add b/B to skeleton, no longer need to set special flags
                        char last = bestAllowed.charAt(bestAllowed.length()-1);
                        if (last=='b' || last=='B') {
                            dayPeriodChar = last;
                        }
                    }
                    if (hourChar=='H' || hourChar=='k') {
                        dayPeriodLen = 0;
                    }
                    while (dayPeriodLen-- > 0) {
                        skeletonCopy.append(dayPeriodChar);
                    }
                     while (hourLen-- > 0) {
                        skeletonCopy.append(hourChar);
                    }
                } else if (patChr == 'J') {
                    // Get pattern for skeleton with H, then (in adjustFieldTypes)
                    // replace H or k with defaultHourFormatChar
                    skeletonCopy.append('H');
                    flags.add(DTPGflags.SKELETON_USES_CAP_J);
                } else {
                    skeletonCopy.append(patChr);
                }
            }
        }
        return skeletonCopy.toString();
    }

    /**
     * PatternInfo supplies output parameters for addPattern(...). It is used because
     * Java doesn't have real output parameters. It is treated like a struct (eg
     * Point), so all fields are public.
     *
     * @stable ICU 3.6
     */
    public static final class PatternInfo { // struct for return information
        /**
         * @stable ICU 3.6
         */
        public static final int OK = 0;

        /**
         * @stable ICU 3.6
         */
        public static final int BASE_CONFLICT = 1;

        /**
         * @stable ICU 3.6
         */
        public static final int CONFLICT = 2;

        /**
         * @stable ICU 3.6
         */
        public int status;

        /**
         * @stable ICU 3.6
         */
        public String conflictingPattern;

        /**
         * Simple constructor, since this is treated like a struct.
         * @stable ICU 3.6
         */
        public PatternInfo() {
        }
    }

    /**
     * Adds a pattern to the generator. If the pattern has the same skeleton as
     * an existing pattern, and the override parameter is set, then the previous
     * value is overridden. Otherwise, the previous value is retained. In either
     * case, the conflicting information is returned in PatternInfo.
     * <p>
     * Note that single-field patterns (like "MMM") are automatically added, and
     * don't need to be added explicitly!
     * * <p>Example code:{@.jcite com.ibm.icu.samples.text.datetimepatterngenerator.DateTimePatternGeneratorSample:---addPatternExample}
     * @param pattern Pattern to add.
     * @param override When existing values are to be overridden use true, otherwise
     *            use false.
     * @param returnInfo Returned information.
     * @stable ICU 3.6
     */
    public DateTimePatternGenerator addPattern(String pattern, boolean override, PatternInfo returnInfo) {
        return addPatternWithSkeleton(pattern, null, override, returnInfo);
    }

    /**
     * addPatternWithSkeleton:
     * If skeletonToUse is specified, then an availableFormats entry is being added. In this case:
     * 1. We pass that skeleton to DateTimeMatcher().set instead of having it derive a skeleton from the pattern.
     * 2. If the new entry's skeleton or basePattern does match an existing entry but that entry also had a skeleton specified
     * (i.e. it was also from availableFormats), then the new entry does not override it regardless of the value of the override
     * parameter. This prevents later availableFormats entries from a parent locale overriding earlier ones from the actual
     * specified locale. However, availableFormats entries *should* override entries with matching skeleton whose skeleton was
     * derived (i.e. entries derived from the standard date/time patters for the specified locale).
     * 3. When adding the pattern (skeleton2pattern.put, basePattern_pattern.put), we set a field to indicate that the added
     * entry had a specified skeleton.
     * @internal
     * @deprecated This API is ICU internal only.
     */
    @Deprecated
    public DateTimePatternGenerator addPatternWithSkeleton(String pattern, String skeletonToUse, boolean override, PatternInfo returnInfo) {
        checkFrozen();
        DateTimeMatcher matcher;
        if (skeletonToUse == null) {
            matcher = new DateTimeMatcher().set(pattern, fp, false);
        } else {
            matcher = new DateTimeMatcher().set(skeletonToUse, fp, false);
        }
        String basePattern = matcher.getBasePattern();
        // We only care about base conflicts - and replacing the pattern associated with a base - if:
        // 1. the conflicting previous base pattern did *not* have an explicit skeleton; in that case the previous
        // base + pattern combination was derived from either (a) a canonical item, (b) a standard format, or
        // (c) a pattern specified programmatically with a previous call to addPattern (which would only happen
        // if we are getting here from a subsequent call to addPattern).
        // 2. a skeleton is specified for the current pattern, but override=false; in that case we are checking
        // availableFormats items from root, which should not override any previous entry with the same base.
        PatternWithSkeletonFlag previousPatternWithSameBase = basePattern_pattern.get(basePattern);
        if (previousPatternWithSameBase != null && (!previousPatternWithSameBase.skeletonWasSpecified || (skeletonToUse != null && !override))) {
            returnInfo.status = PatternInfo.BASE_CONFLICT;
            returnInfo.conflictingPattern = previousPatternWithSameBase.pattern;
            if (!override) {
                return this;
            }
        }
        // The only time we get here with override=true and skeletonToUse!=null is when adding availableFormats
        // items from CLDR data. In that case, we don't want an item from a parent locale to replace an item with
        // same skeleton from the specified locale, so skip the current item if skeletonWasSpecified is true for
        // the previously-specified conflicting item.
        PatternWithSkeletonFlag previousValue = skeleton2pattern.get(matcher);
        if (previousValue != null) {
            returnInfo.status = PatternInfo.CONFLICT;
            returnInfo.conflictingPattern = previousValue.pattern;
            if (!override || (skeletonToUse != null && previousValue.skeletonWasSpecified)) return this;
        }
        returnInfo.status = PatternInfo.OK;
        returnInfo.conflictingPattern = "";
        PatternWithSkeletonFlag patWithSkelFlag = new PatternWithSkeletonFlag(pattern,skeletonToUse != null);
        if (DEBUG) {
            System.out.println(matcher + " => " + patWithSkelFlag);
        }
        skeleton2pattern.put(matcher, patWithSkelFlag);
        basePattern_pattern.put(basePattern, patWithSkelFlag);
        return this;
    }

    /**
     * Utility to return a unique skeleton from a given pattern. For example,
     * both "MMM-dd" and "dd/MMM" produce the skeleton "MMMdd".
     *
     * @param pattern Input pattern, such as "dd/MMM"
     * @return skeleton, such as "MMMdd"
     * @stable ICU 3.6
     */
    public String getSkeleton(String pattern) {
        synchronized (this) { // synchronized since a getter must be thread-safe
            current.set(pattern, fp, false);
            return current.toString();
        }
    }

    /**
     * Same as getSkeleton, but allows duplicates
     *
     * @param pattern Input pattern, such as "dd/MMM"
     * @return skeleton, such as "MMMdd"
     * @internal
     * @deprecated This API is ICU internal only.
     */
    @Deprecated
    public String getSkeletonAllowingDuplicates(String pattern) {
        synchronized (this) { // synchronized since a getter must be thread-safe
            current.set(pattern, fp, true);
            return current.toString();
        }
    }

    /**
     * Same as getSkeleton, but allows duplicates
     * and returns a string using canonical pattern chars
     *
     * @param pattern Input pattern, such as "ccc, d LLL"
     * @return skeleton, such as "MMMEd"
     * @internal
     * @deprecated This API is ICU internal only.
     */
    @Deprecated
    public String getCanonicalSkeletonAllowingDuplicates(String pattern) {
        synchronized (this) { // synchronized since a getter must be thread-safe
            current.set(pattern, fp, true);
            return current.toCanonicalString();
        }
    }

    /**
     * Utility to return a unique base skeleton from a given pattern. This is
     * the same as the skeleton, except that differences in length are minimized
     * so as to only preserve the difference between string and numeric form. So
     * for example, both "MMM-dd" and "d/MMM" produce the skeleton "MMMd"
     * (notice the single d).
     *
     * @param pattern Input pattern, such as "dd/MMM"
     * @return skeleton, such as "MMMdd"
     * @stable ICU 3.6
     */
    public String getBaseSkeleton(String pattern) {
        synchronized (this) { // synchronized since a getter must be thread-safe
            current.set(pattern, fp, false);
            return current.getBasePattern();
        }
    }

    /**
     * Return a list of all the skeletons (in canonical form) from this class,
     * and the patterns that they map to.
     *
     * @param result an output Map in which to place the mapping from skeleton to
     *            pattern. If you want to see the internal order being used,
     *            supply a LinkedHashMap. If the input value is null, then a
     *            LinkedHashMap is allocated.
     *            <p>
     *            <i>Issue: an alternate API would be to just return a list of
     *            the skeletons, and then have a separate routine to get from
     *            skeleton to pattern.</i>
     * @return the input Map containing the values.
     * @stable ICU 3.6
     */
    public Map<String, String> getSkeletons(Map<String, String> result) {
        if (result == null) {
            result = new LinkedHashMap<>();
        }
        for (DateTimeMatcher item : skeleton2pattern.keySet()) {
            PatternWithSkeletonFlag patternWithSkelFlag = skeleton2pattern.get(item);
            String pattern = patternWithSkelFlag.pattern;
            if (CANONICAL_SET.contains(pattern)) {
                continue;
            }
            result.put(item.toString(), pattern);
        }
        return result;
    }

    /**
     * Return a list of all the base skeletons (in canonical form) from this class
     * @stable ICU 3.6
     */
    public Set<String> getBaseSkeletons(Set<String> result) {
        if (result == null) {
            result = new HashSet<>();
        }
        result.addAll(basePattern_pattern.keySet());
        return result;
    }

    /**
     * Adjusts the field types (width and subtype) of a pattern to match what is
     * in a skeleton. That is, if you supply a pattern like "d-M H:m", and a
     * skeleton of "MMMMddhhmm", then the input pattern is adjusted to be
     * "dd-MMMM hh:mm". This is used internally to get the best match for the
     * input skeleton, but can also be used externally.
     * <p>Example code:{@.jcite com.ibm.icu.samples.text.datetimepatterngenerator.DateTimePatternGeneratorSample:---replaceFieldTypesExample}
     * @param pattern input pattern
     * @param skeleton For the pattern to match to.
     * @return pattern adjusted to match the skeleton fields widths and subtypes.
     * @stable ICU 3.6
     */
    public String replaceFieldTypes(String pattern, String skeleton) {
        return replaceFieldTypes(pattern, skeleton, MATCH_NO_OPTIONS);
    }

    /**
     * Adjusts the field types (width and subtype) of a pattern to match what is
     * in a skeleton. That is, if you supply a pattern like "d-M H:m", and a
     * skeleton of "MMMMddhhmm", then the input pattern is adjusted to be
     * "dd-MMMM hh:mm". This is used internally to get the best match for the
     * input skeleton, but can also be used externally.
     *
     * @param pattern input pattern
     * @param skeleton For the pattern to match to.
     * @param options MATCH_xxx options for forcing the length of specified fields in
     *            the returned pattern to match those in the skeleton (when this would
     *            not happen otherwise). For default behavior, use MATCH_NO_OPTIONS.
     * @return pattern adjusted to match the skeleton fields widths and subtypes.
     * @stable ICU 4.4
     */
    public String replaceFieldTypes(String pattern, String skeleton, int options) {
        synchronized (this) { // synchronized since a getter must be thread-safe
            PatternWithMatcher patternNoMatcher = new PatternWithMatcher(pattern, null);
            return adjustFieldTypes(patternNoMatcher, current.set(skeleton, fp, false), EnumSet.noneOf(DTPGflags.class), options);
        }
    }

    /**
     * The date time format is a message format pattern used to compose date and
     * time patterns. The default value is "{1} {0}", where {1} will be replaced
     * by the date pattern and {0} will be replaced by the time pattern.
     * <p>
     * This is used when the input skeleton contains both date and time fields,
     * but there is not a close match among the added patterns. For example,
     * suppose that this object was created by adding "dd-MMM" and "hh:mm", and
     * its datetimeFormat is the default "{1} {0}". Then if the input skeleton
     * is "MMMdhmm", there is not an exact match, so the input skeleton is
     * broken up into two components "MMMd" and "hmm". There are close matches
     * for those two skeletons, so the result is put together with this pattern,
     * resulting in "d-MMM h:mm".
     *
     * There are four DateTimeFormats in a DateTimePatternGenerator object,
     * corresponding to date styles DateFormat.FULL..DateFormat.SHORT. This method sets
     * all of them to the specified pattern. To set them individually, see
     * setDateTimeFormat(int style, ...).
     *
     * @param dateTimeFormat message format pattern, where {1} will be replaced by the date
     *            pattern and {0} will be replaced by the time pattern.
     * @stable ICU 3.6
     */
    public void setDateTimeFormat(String dateTimeFormat) {
        checkFrozen();
        for (int style = DateFormat.FULL; style <= DateFormat.SHORT; style++) {
            setDateTimeFormat(style, dateTimeFormat);
        }
    }

    /**
     * Getter corresponding to setDateTimeFormat.
     *
     * There are four DateTimeFormats in a DateTimePatternGenerator object,
     * corresponding to date styles DateFormat.FULL..DateFormat.SHORT. This method gets
     * the style for DateFormat.MEDIUM (the default). To get them individually, see
     * getDateTimeFormat(int style).
     *
     * @return pattern
     * @stable ICU 3.6
     */
    public String getDateTimeFormat() {
        return getDateTimeFormat(DateFormat.MEDIUM);
    }

    /**
     * dateTimeFormats are message patterns used to compose combinations of date
     * and time patterns. There are four length styles, corresponding to the
     * inferred style of the date pattern:
     *  - DateFormat.FULL (for date pattern with weekday and long month), else
     *  - DateFormat.LONG (for a date pattern with long month), else
     *  - DateFormat.MEDIUM (for a date pattern with abbreviated month), else
     *  - DateFormat.SHORT (for any other date pattern).
     * For details on dateTimeFormats, see
     * https://www.unicode.org/reports/tr35/tr35-dates.html#dateTimeFormats.
     * The default pattern in the root locale for all styles is "{1} {0}".
     *
     * @param style
     *              one of DateFormat.FULL..DateFormat.SHORT. An exception will
     *              be thrown if out of range.
     * @param dateTimeFormat
     *              the new dateTimeFormat to set for the specified style
     * @draft ICU 71
     */
    public void setDateTimeFormat(int style, String dateTimeFormat) {
        if (style < DateFormat.FULL || style > DateFormat.SHORT) {
            throw new IllegalArgumentException("Illegal style here: " + style);
        }
        checkFrozen();
        this.dateTimeFormats[style] = dateTimeFormat;
    }

    /**
     * Getter corresponding to setDateTimeFormat.
     *
     * @param style
     *              one of DateFormat.FULL..DateFormat.SHORT. An exception will
     *              be thrown if out of range.
     * @return
     *              the current dateTimeFormat for the specified style.
     * @draft ICU 71
     */
    public String getDateTimeFormat(int style) {
        if (style < DateFormat.FULL || style > DateFormat.SHORT) {
            throw new IllegalArgumentException("Illegal style here: " + style);
        }
        return dateTimeFormats[style];
    }

    /**
     * The decimal value is used in formatting fractions of seconds. If the
     * skeleton contains fractional seconds, then this is used with the
     * fractional seconds. For example, suppose that the input pattern is
     * "hhmmssSSSS", and the best matching pattern internally is "H:mm:ss", and
     * the decimal string is ",". Then the resulting pattern is modified to be
     * "H:mm:ss,SSSS"
     *
     * @param decimal The decimal to set to.
     * @stable ICU 3.6
     */
    public void setDecimal(String decimal) {
        checkFrozen();
        this.decimal = decimal;
    }

    /**
     * Getter corresponding to setDecimal.
     * @return string corresponding to the decimal point
     * @stable ICU 3.6
     */
    public String getDecimal() {
        return decimal;
    }

    /**
     * Redundant patterns are those which if removed, make no difference in the
     * resulting getBestPattern values. This method returns a list of them, to
     * help check the consistency of the patterns used to build this generator.
     *
     * @param output stores the redundant patterns that are removed. To get these
     *            in internal order, supply a LinkedHashSet. If null, a
     *            collection is allocated.
     * @return the collection with added elements.
     * @internal
     * @deprecated This API is ICU internal only.
     */
    @Deprecated
    public Collection<String> getRedundants(Collection<String> output) {
        synchronized (this) { // synchronized since a getter must be thread-safe
            if (output == null) {
                output = new LinkedHashSet<>();
            }
            for (DateTimeMatcher cur : skeleton2pattern.keySet()) {
                PatternWithSkeletonFlag patternWithSkelFlag = skeleton2pattern.get(cur);
                String pattern = patternWithSkelFlag.pattern;
                if (CANONICAL_SET.contains(pattern)) {
                    continue;
                }
                String trial = getBestPattern(cur.toString(), cur, MATCH_NO_OPTIONS);
                if (trial.equals(pattern)) {
                    output.add(pattern);
                }
            }
            ///CLOVER:OFF
            //The following would never be called since the parameter is false
            //Eclipse stated the following is "dead code"
            /*if (false) { // ordered
                DateTimePatternGenerator results = new DateTimePatternGenerator();
                PatternInfo pinfo = new PatternInfo();
                for (DateTimeMatcher cur : skeleton2pattern.keySet()) {
                    String pattern = skeleton2pattern.get(cur);
                    if (CANONICAL_SET.contains(pattern)) {
                        continue;
                    }
                    //skipMatcher = current;
                    String trial = results.getBestPattern(cur.toString());
                    if (trial.equals(pattern)) {
                        output.add(pattern);
                    } else {
                        results.addPattern(pattern, false, pinfo);
                    }
                }
            }*/
            ///CLOVER:ON
            return output;
        }
    }

    // Field numbers, used for AppendItem functions

    /**
     * @stable ICU 3.6
     */
    public static final int ERA = 0;

    /**
     * @stable ICU 3.6
     */
    public static final int YEAR = 1;

    /**
     * @stable ICU 3.6
     */
    public static final int QUARTER = 2;

    /**
     * @stable ICU 3.6
     */
    public static final int MONTH = 3;

    /**
     * @stable ICU 3.6
     */
    public static final int WEEK_OF_YEAR = 4;

    /**
     * @stable ICU 3.6
     */
    public static final int WEEK_OF_MONTH = 5;

    /**
     * @stable ICU 3.6
     */
    public static final int WEEKDAY = 6;

    /**
     * @stable ICU 3.6
     */
    public static final int DAY = 7;

    /**
     * @stable ICU 3.6
     */
    public static final int DAY_OF_YEAR = 8;

    /**
     * @stable ICU 3.6
     */
    public static final int DAY_OF_WEEK_IN_MONTH = 9;

    /**
     * @stable ICU 3.6
     */
    public static final int DAYPERIOD = 10;

    /**
     * @stable ICU 3.6
     */
    public static final int HOUR = 11;

    /**
     * @stable ICU 3.6
     */
    public static final int MINUTE = 12;

    /**
     * @stable ICU 3.6
     */
    public static final int SECOND = 13;

    /**
     * @stable ICU 3.6
     */
    public static final int FRACTIONAL_SECOND = 14;

    /**
     * @stable ICU 3.6
     */
    public static final int ZONE = 15;

    /**
     * One more than the highest normal field number.
     * @deprecated ICU 58 The numeric value may change over time, see ICU ticket #12420.
     */
    @Deprecated
    public static final int TYPE_LIMIT = 16;

    /**
     * Field display name width constants for getFieldDisplayName
     * @stable ICU 61
     */
    public enum DisplayWidth {
        /**
         * The full field name
         * @stable ICU 61
         */
        WIDE(""),
        /**
         * An abbreviated field name
         * (may be the same as the wide version, if short enough)
         * @stable ICU 61
         */
        ABBREVIATED("-short"),
        /**
         * The shortest possible field name
         * (may be the same as the abbreviated version)
         * @stable ICU 61
         */
        NARROW("-narrow");
        /**
         * The count of available widths
         * @internal
         * @deprecated This API is ICU internal only.
         */
        @Deprecated
        private static int COUNT = DisplayWidth.values().length;
        private final String cldrKey;
        DisplayWidth(String cldrKey) {
            this.cldrKey = cldrKey;
        }
        private String cldrKey() {
            return cldrKey;
        }
    }

    /**
     * The field name width for use in appendItems
     */
    private static final DisplayWidth APPENDITEM_WIDTH = DisplayWidth.WIDE;
    private static final int APPENDITEM_WIDTH_INT = APPENDITEM_WIDTH.ordinal();
    private static final DisplayWidth[] CLDR_FIELD_WIDTH = DisplayWidth.values();

    // Option masks for getBestPattern, replaceFieldTypes (individual masks may be ORed together)

    /**
     * Default option mask used for {@link #getBestPattern(String, int)}
     * and {@link #replaceFieldTypes(String, String, int)}.
     * @stable ICU 4.4
     * @see #getBestPattern(String, int)
     * @see #replaceFieldTypes(String, String, int)
     */
    public static final int MATCH_NO_OPTIONS = 0;

    /**
     * Option mask for forcing the width of hour field.
     * @stable ICU 4.4
     * @see #getBestPattern(String, int)
     * @see #replaceFieldTypes(String, String, int)
     */
    public static final int MATCH_HOUR_FIELD_LENGTH = 1 << HOUR;

    /**
     * Option mask for forcing  the width of minute field.
     * @internal
     * @deprecated This API is ICU internal only.
     */
    @Deprecated
    public static final int MATCH_MINUTE_FIELD_LENGTH = 1 << MINUTE;

    /**
     * Option mask for forcing  the width of second field.
     * @internal
     * @deprecated This API is ICU internal only.
     */
    @Deprecated
    public static final int MATCH_SECOND_FIELD_LENGTH = 1 << SECOND;

    /**
     * Option mask for forcing the width of all date and time fields.
     * @stable ICU 4.4
     * @see #getBestPattern(String, int)
     * @see #replaceFieldTypes(String, String, int)
     */
    public static final int MATCH_ALL_FIELDS_LENGTH = (1 << TYPE_LIMIT) - 1;

    /**
     * An AppendItem format is a pattern used to append a field if there is no
     * good match. For example, suppose that the input skeleton is "GyyyyMMMd",
     * and there is no matching pattern internally, but there is a pattern
     * matching "yyyyMMMd", say "d-MM-yyyy". Then that pattern is used, plus the
     * G. The way these two are conjoined is by using the AppendItemFormat for G
     * (era). So if that value is, say "{0}, {1}" then the final resulting
     * pattern is "d-MM-yyyy, G".
     * <p>
     * There are actually three available variables: {0} is the pattern so far,
     * {1} is the element we are adding, and {2} is the name of the element.
     * <p>
     * This reflects the way that the CLDR data is organized.
     *
     * @param field such as ERA
     * @param value pattern, such as "{0}, {1}"
     * @stable ICU 3.6
     */
    public void setAppendItemFormat(int field, String value) {
        checkFrozen();
        appendItemFormats[field] = value;
    }

    /**
     * Getter corresponding to setAppendItemFormats. Values below 0 or at or
     * above TYPE_LIMIT are illegal arguments.
     *
     * @param field The index to retrieve the append item formats.
     * @return append pattern for field
     * @stable ICU 3.6
     */
    public String getAppendItemFormat(int field) {
        return appendItemFormats[field];
    }

    /**
     * Sets the names of fields, eg "era" in English for ERA. These are only
     * used if the corresponding AppendItemFormat is used, and if it contains a
     * {2} variable.
     * <p>
     * This reflects the way that the CLDR data is organized.
     *
     * @param field Index of the append item names.
     * @param value The value to set the item to.
     * @stable ICU 3.6
     */
    public void setAppendItemName(int field, String value) {
        setFieldDisplayName(field, APPENDITEM_WIDTH, value);
    }

    /**
     * Getter corresponding to setAppendItemName. Values below 0 or at or above
     * TYPE_LIMIT are illegal arguments. Note: The more general method
     * for getting date/time field display names is getFieldDisplayName.
     *
     * @param field The index to get the append item name.
     * @return name for field
     * @see #getFieldDisplayName(int, DisplayWidth)
     * @stable ICU 3.6
     */
    public String getAppendItemName(int field) {
        return getFieldDisplayName(field, APPENDITEM_WIDTH);
    }

    /**
     * Return the default hour cycle.
     * @stable ICU 67
     */
    public DateFormat.HourCycle getDefaultHourCycle() {
      switch(getDefaultHourFormatChar()) {
        case 'h': return DateFormat.HourCycle.HOUR_CYCLE_12;
        case 'H': return DateFormat.HourCycle.HOUR_CYCLE_23;
        case 'k': return DateFormat.HourCycle.HOUR_CYCLE_24;
        case 'K': return DateFormat.HourCycle.HOUR_CYCLE_11;
        default: throw new AssertionError("should be unreachable");
      }
    }

    /**
     * The private interface to set a display name for a particular date/time field,
     * in one of several possible display widths.
     *
     * @param field The field type, such as ERA.
     * @param width The desired DisplayWidth, such as DisplayWidth.ABBREVIATED.
     * @param value The display name to set
     * @internal
     * @deprecated This API is ICU internal only.
     */
    @Deprecated
    private void setFieldDisplayName(int field, DisplayWidth width, String value) {
        checkFrozen();
        if (field < TYPE_LIMIT && field >= 0) {
            fieldDisplayNames[field][width.ordinal()] = value;
        }
    }

    /**
     * The general interface to get a display name for a particular date/time field,
     * in one of several possible display widths.
     *
     * @param field The field type, such as ERA.
     * @param width The desired DisplayWidth, such as DisplayWidth.ABBREVIATED.
     * @return      The display name for the field
     * @stable ICU 61
     */
    public String getFieldDisplayName(int field, DisplayWidth width) {
        if (field >= TYPE_LIMIT || field < 0) {
            return "";
        }
        return fieldDisplayNames[field][width.ordinal()];
    }

    /**
     * Determines whether a skeleton contains a single field
     *
     * @param skeleton The skeleton to determine if it contains a single field.
     * @return true or not
     * @internal
     * @deprecated This API is ICU internal only.
     */
    @Deprecated
    public static boolean isSingleField(String skeleton) {
        char first = skeleton.charAt(0);
        for (int i = 1; i < skeleton.length(); ++i) {
            if (skeleton.charAt(i) != first) return false;
        }
        return true;
    }

    /**
     * Add key to HashSet cldrAvailableFormatKeys.
     *
     * @param key of the availableFormats in CLDR
     * @stable ICU 3.6
     */
    private void setAvailableFormat(String key) {
        checkFrozen();
        cldrAvailableFormatKeys.add(key);
    }

    /**
     * This function checks the corresponding slot of CLDR_AVAIL_FORMAT_KEY[]
     * has been added to DateTimePatternGenerator.
     * The function is to avoid the duplicate availableFomats added to
     * the pattern map from parent locales.
     *
     * @param key of the availableFormatMask in CLDR
     * @return TRUE if the corresponding slot of CLDR_AVAIL_FORMAT_KEY[]
     * has been added to DateTimePatternGenerator.
     * @stable ICU 3.6
     */
    private boolean isAvailableFormatSet(String key) {
        return cldrAvailableFormatKeys.contains(key);
    }

    /**
     * {@inheritDoc}
     * @stable ICU 3.6
     */
    @Override
    public boolean isFrozen() {
        return frozen;
    }

    /**
     * {@inheritDoc}
     * @stable ICU 4.4
     */
    @Override
    public DateTimePatternGenerator freeze() {
        frozen = true;
        return this;
    }

    /**
     * {@inheritDoc}
     * @stable ICU 4.4
     */
    @Override
    public DateTimePatternGenerator cloneAsThawed() {
        DateTimePatternGenerator result = (DateTimePatternGenerator) (this.clone());
        frozen = false;
        return result;
    }

    /**
     * Returns a copy of this <code>DateTimePatternGenerator</code> object.
     * @return A copy of this <code>DateTimePatternGenerator</code> object.
     * @stable ICU 3.6
     */
    @Override
    @SuppressWarnings("unchecked")
    public Object clone() {
        try {
            DateTimePatternGenerator result = (DateTimePatternGenerator) (super.clone());
            result.skeleton2pattern = (TreeMap<DateTimeMatcher, PatternWithSkeletonFlag>) skeleton2pattern.clone();
            result.basePattern_pattern = (TreeMap<String, PatternWithSkeletonFlag>) basePattern_pattern.clone();
            result.dateTimeFormats = dateTimeFormats.clone();
            result.appendItemFormats = appendItemFormats.clone();
            result.fieldDisplayNames = fieldDisplayNames.clone();
            result.current = new DateTimeMatcher();
            result.fp = new FormatParser();
            result._distanceInfo = new DistanceInfo();

            result.frozen = false;
            return result;
        } catch (CloneNotSupportedException e) {
            ///CLOVER:OFF
            throw new ICUCloneNotSupportedException("Internal Error", e);
            ///CLOVER:ON
        }
    }

    /**
     * Utility class for FormatParser. Immutable class that is only used to mark
     * the difference between a variable field and a literal string. Each
     * variable field must consist of 1 to n variable characters, representing
     * date format fields. For example, "VVVV" is valid while "V4" is not, nor
     * is "44".
     *
     * @internal
     * @deprecated This API is ICU internal only.
     */
    @Deprecated
    public static class VariableField {
        private final String string;
        private final int canonicalIndex;

        /**
         * Create a variable field: equivalent to VariableField(string,false);
         * @param string The string for the variable field.
         * @internal
         * @deprecated This API is ICU internal only.
         */
        @Deprecated
        public VariableField(String string) {
            this(string, false);
        }
        /**
         * Create a variable field
         * @param string The string for the variable field
         * @param strict If true, then only allows exactly those lengths specified by CLDR for variables. For example, "hh:mm aa" would throw an exception.
         * @throws IllegalArgumentException if the variable field is not valid.
         * @internal
         * @deprecated This API is ICU internal only.
         */
        @Deprecated
        public VariableField(String string, boolean strict) {
            canonicalIndex = DateTimePatternGenerator.getCanonicalIndex(string, strict);
            if (canonicalIndex < 0) {
                throw new IllegalArgumentException("Illegal datetime field:\t"
                        + string);
            }
            this.string = string;
        }

        /**
         * Get the main type of this variable. These types are ERA, QUARTER,
         * MONTH, DAY, WEEK_OF_YEAR, WEEK_OF_MONTH, WEEKDAY, DAY, DAYPERIOD
         * (am/pm), HOUR, MINUTE, SECOND,FRACTIONAL_SECOND, ZONE.
         * @return main type.
         * @internal
         * @deprecated This API is ICU internal only.
         */
        @Deprecated
        public int getType() {
            return types[canonicalIndex][1];
        }

        /**
         * @internal
         * @deprecated This API is ICU internal only.
         */
        @Deprecated
        public static String getCanonicalCode(int type) {
            try {
                return CANONICAL_ITEMS[type];
            } catch (Exception e) {
                return String.valueOf(type);
            }
        }
        /**
         * Check if the type of this variable field is numeric.
         * @return true if the type of this variable field is numeric.
         * @internal
         * @deprecated This API is ICU internal only.
         */
        @Deprecated
        public boolean isNumeric() {
            return types[canonicalIndex][2] > 0;
        }

        /**
         * Private method.
         */
        private int getCanonicalIndex() {
            return canonicalIndex;
        }

        /**
         * Get the string represented by this variable.
         * @internal
         * @deprecated This API is ICU internal only.
         */
        @Override
        @Deprecated
        public String toString() {
            return string;
        }
    }

    /**
     * This class provides mechanisms for parsing a SimpleDateFormat pattern
     * or generating a new pattern, while handling the quoting. It represents
     * the result of the parse as a list of items, where each item is either a
     * literal string or a variable field. When parsing It can be used to find
     * out which variable fields are in a date format, and in what order, such
     * as for presentation in a UI as separate text entry fields. It can also be
     * used to construct new SimpleDateFormats.
     * <p>Example:
     * <pre>
    public boolean containsZone(String pattern) {
        for (Iterator it = formatParser.set(pattern).getItems().iterator(); it.hasNext();) {
            Object item = it.next();
            if (item instanceof VariableField) {
                VariableField variableField = (VariableField) item;
                if (variableField.getType() == DateTimePatternGenerator.ZONE) {
                    return true;
                }
            }
        }
        return false;
    }
     *  </pre>
     * @internal
     * @deprecated This API is ICU internal only.
     */
    @Deprecated
    static public class FormatParser {
        private static final UnicodeSet SYNTAX_CHARS = new UnicodeSet("[a-zA-Z]").freeze();
        private static final UnicodeSet QUOTING_CHARS = new UnicodeSet("[[[:script=Latn:][:script=Cyrl:]]&[[:L:][:M:]]]").freeze();
        private transient PatternTokenizer tokenizer = new PatternTokenizer()
        .setSyntaxCharacters(SYNTAX_CHARS)
        .setExtraQuotingCharacters(QUOTING_CHARS)
        .setUsingQuote(true);
        private List<Object> items = new ArrayList<>();

        /**
         * Construct an empty date format parser, to which strings and variables can be added with set(...).
         * @internal
         * @deprecated This API is ICU internal only.
         */
        @Deprecated
        public FormatParser() {
        }

        /**
         * Parses the string into a list of items.
         * @param string The string to parse.
         * @return this, for chaining
         * @internal
         * @deprecated This API is ICU internal only.
         */
        @Deprecated
        final public FormatParser set(String string) {
            return set(string, false);
        }

        /**
         * Parses the string into a list of items, taking into account all of the quoting that may be going on.
         * @param string  The string to parse.
         * @param strict If true, then only allows exactly those lengths specified by CLDR for variables. For example, "hh:mm aa" would throw an exception.
         * @return this, for chaining
         * @internal
         * @deprecated This API is ICU internal only.
         */
        @Deprecated
        public FormatParser set(String string, boolean strict) {
            items.clear();
            if (string.length() == 0) return this;
            tokenizer.setPattern(string);
            StringBuffer buffer = new StringBuffer();
            StringBuffer variable = new StringBuffer();
            while (true) {
                buffer.setLength(0);
                int status = tokenizer.next(buffer);
                if (status == PatternTokenizer.DONE) break;
                if (status == PatternTokenizer.SYNTAX) {
                    if (variable.length() != 0 && buffer.charAt(0) != variable.charAt(0)) {
                        addVariable(variable, false);
                    }
                    variable.append(buffer);
                } else {
                    addVariable(variable, false);
                    items.add(buffer.toString());
                }
            }
            addVariable(variable, false);
            return this;
        }

        private void addVariable(StringBuffer variable, boolean strict) {
            if (variable.length() != 0) {
                items.add(new VariableField(variable.toString(), strict));
                variable.setLength(0);
            }
        }

        //        /** Private method. Return a collection of fields. These will be a mixture of literal Strings and VariableFields. Any "a" variable field is removed.
        //         * @param output List to append the items to. If null, is allocated as an ArrayList.
        //         * @return list
        //         */
        //        private List getVariableFields(List output) {
        //            if (output == null) output = new ArrayList();
        //            main:
        //                for (Iterator it = items.iterator(); it.hasNext();) {
        //                    Object item = it.next();
        //                    if (item instanceof VariableField) {
        //                        String s = item.toString();
        //                        switch(s.charAt(0)) {
        //                        //case 'Q': continue main; // HACK
        //                        case 'a': continue main; // remove
        //                        }
        //                        output.add(item);
        //                    }
        //                }
        //            //System.out.println(output);
        //            return output;
        //        }

        //        /**
        //         * Produce a string which concatenates all the variables. That is, it is the logically the same as the input with all literals removed.
        //         * @return a string which is a concatenation of all the variable fields
        //         */
        //        public String getVariableFieldString() {
        //            List list = getVariableFields(null);
        //            StringBuffer result = new StringBuffer();
        //            for (Iterator it = list.iterator(); it.hasNext();) {
        //                String item = it.next().toString();
        //                result.append(item);
        //            }
        //            return result.toString();
        //        }

        /**
         * Returns modifiable list which is a mixture of Strings and VariableFields, in the order found during parsing. The strings represent literals, and have all quoting removed. Thus the string "dd 'de' MM" will parse into three items:
         * <pre>
         * VariableField: dd
         * String: " de "
         * VariableField: MM
         * </pre>
         * The list is modifiable, so you can add any strings or variables to it, or remove any items.
         * @return modifiable list of items.
         * @internal
         * @deprecated This API is ICU internal only.
         */
        @Deprecated
        public List<Object> getItems() {
            return items;
        }

        /** Provide display form of formatted input. Each literal string is quoted if necessary.. That is, if the input was "hh':'mm", the result would be "hh:mm", since the ":" doesn't need quoting. See quoteLiteral().
         * @return printable output string
         * @internal
         * @deprecated This API is ICU internal only.
         */
        @Override
        @Deprecated
        public String toString() {
            return toString(0, items.size());
        }

        /**
         * Provide display form of a segment of the parsed input. Each literal string is minimally quoted. That is, if the input was "hh':'mm", the result would be "hh:mm", since the ":" doesn't need quoting. See quoteLiteral().
         * @param start item to start from
         * @param limit last item +1
         * @return printable output string
         * @internal
         * @deprecated This API is ICU internal only.
         */
        @Deprecated
        public String toString(int start, int limit) {
            StringBuilder result = new StringBuilder();
            for (int i = start; i < limit; ++i) {
                Object item = items.get(i);
                if (item instanceof String) {
                    String itemString = (String) item;
                    result.append(tokenizer.quoteLiteral(itemString));
                } else {
                    result.append(items.get(i).toString());
                }
            }
            return result.toString();
        }

        /**
         * Returns true if it has a mixture of date and time variable fields: that is, at least one date variable and at least one time variable.
         * @return true or false
         * @internal
         * @deprecated This API is ICU internal only.
         */
        @Deprecated
        public boolean hasDateAndTimeFields() {
            int foundMask = 0;
            for (Object item : items) {
                if (item instanceof VariableField) {
                    int type = ((VariableField)item).getType();
                    foundMask |= 1 << type;
                }
            }
            boolean isDate = (foundMask & DATE_MASK) != 0;
            boolean isTime = (foundMask & TIME_MASK) != 0;
            return isDate && isTime;
        }

        //        /**
        //         * Internal routine
        //         * @param value
        //         * @param result
        //         * @return list
        //         */
        //        public List getAutoPatterns(String value, List result) {
        //            if (result == null) result = new ArrayList();
        //            int fieldCount = 0;
        //            int minField = Integer.MAX_VALUE;
        //            int maxField = Integer.MIN_VALUE;
        //            for (Iterator it = items.iterator(); it.hasNext();) {
        //                Object item = it.next();
        //                if (item instanceof VariableField) {
        //                    try {
        //                        int type = ((VariableField)item).getType();
        //                        if (minField > type) minField = type;
        //                        if (maxField < type) maxField = type;
        //                        if (type == ZONE || type == DAYPERIOD || type == WEEKDAY) return result; // skip anything with zones
        //                        fieldCount++;
        //                    } catch (Exception e) {
        //                        return result; // if there are any funny fields, return
        //                    }
        //                }
        //            }
        //            if (fieldCount < 3) return result; // skip
        //            // trim from start
        //            // trim first field IF there are no letters around it
        //            // and it is either the min or the max field
        //            // first field is either 0 or 1
        //            for (int i = 0; i < items.size(); ++i) {
        //                Object item = items.get(i);
        //                if (item instanceof VariableField) {
        //                    int type = ((VariableField)item).getType();
        //                    if (type != minField && type != maxField) break;
        //
        //                    if (i > 0) {
        //                        Object previousItem = items.get(0);
        //                        if (alpha.containsSome(previousItem.toString())) break;
        //                    }
        //                    int start = i+1;
        //                    if (start < items.size()) {
        //                        Object nextItem = items.get(start);
        //                        if (nextItem instanceof String) {
        //                            if (alpha.containsSome(nextItem.toString())) break;
        //                            start++; // otherwise skip over string
        //                        }
        //                    }
        //                    result.add(toString(start, items.size()));
        //                    break;
        //                }
        //            }
        //            // now trim from end
        //            for (int i = items.size()-1; i >= 0; --i) {
        //                Object item = items.get(i);
        //                if (item instanceof VariableField) {
        //                    int type = ((VariableField)item).getType();
        //                    if (type != minField && type != maxField) break;
        //                    if (i < items.size() - 1) {
        //                        Object previousItem = items.get(items.size() - 1);
        //                        if (alpha.containsSome(previousItem.toString())) break;
        //                    }
        //                    int end = i-1;
        //                    if (end > 0) {
        //                        Object nextItem = items.get(end);
        //                        if (nextItem instanceof String) {
        //                            if (alpha.containsSome(nextItem.toString())) break;
        //                            end--; // otherwise skip over string
        //                        }
        //                    }
        //                    result.add(toString(0, end+1));
        //                    break;
        //                }
        //            }
        //
        //            return result;
        //        }

        //        private static UnicodeSet alpha = new UnicodeSet("[:alphabetic:]");

        //        private int getType(Object item) {
        //            String s = item.toString();
        //            int canonicalIndex = getCanonicalIndex(s);
        //            if (canonicalIndex < 0) {
        //                throw new IllegalArgumentException("Illegal field:\t"
        //                        + s);
        //            }
        //            int type = types[canonicalIndex][1];
        //            return type;
        //        }

        /**
         *  Each literal string is quoted as needed. That is, the ' quote marks will only be added if needed. The exact pattern of quoting is not guaranteed, thus " de la " could be quoted as " 'de la' " or as " 'de' 'la' ".
         * @param string The string to check.
         * @return string with quoted literals
         * @internal
         * @deprecated This API is ICU internal only.
         */
        @Deprecated
        public Object quoteLiteral(String string) {
            return tokenizer.quoteLiteral(string);
        }

    }

    /**
     * Used by CLDR tooling; not in ICU4C.
     * Note, this will not work correctly with normal skeletons, since fields
     * that should be related in the two skeletons being compared - like EEE and
     * ccc, or y and U - will not be sorted in the same relative place as each
     * other when iterating over both TreeSets being compare, using TreeSet's
     * "natural" code point ordering (this could be addressed by initializing
     * the TreeSet with a comparator that compares fields first by their index
     * from getCanonicalIndex()). However if comparing canonical skeletons from
     * getCanonicalSkeletonAllowingDuplicates it will be OK regardless, since
     * in these skeletons all fields are normalized to the canonical pattern
     * char for those fields - M or L to M, E or c to E, y or U to y, etc. -
     * so corresponding fields will sort in the same way for both TreeMaps.
     * @internal
     * @deprecated This API is ICU internal only.
     */
    @Deprecated
    public boolean skeletonsAreSimilar(String id, String skeleton) {
        if (id.equals(skeleton)) {
            return true; // fast path
        }
        // must clone array, make sure items are in same order.
        TreeSet<String> parser1 = getSet(id);
        TreeSet<String> parser2 = getSet(skeleton);
        if (parser1.size() != parser2.size()) {
            return false;
        }
        Iterator<String> it2 = parser2.iterator();
        for (String item : parser1) {
            int index1 = getCanonicalIndex(item, false);
            String item2 = it2.next(); // same length so safe
            int index2 = getCanonicalIndex(item2, false);
            if (types[index1][1] != types[index2][1]) {
                return false;
            }
        }
        return true;
    }

    private TreeSet<String> getSet(String id) {
        final List<Object> items = fp.set(id).getItems();
        TreeSet<String> result = new TreeSet<>();
        for (Object obj : items) {
            final String item = obj.toString();
            if (item.startsWith("G") || item.startsWith("a")) {
                continue;
            }
            result.add(item);
        }
        return result;
    }

    // ========= PRIVATES ============

    private static class PatternWithMatcher {
        public String pattern;
        public DateTimeMatcher matcherWithSkeleton;
        // Simple constructor
        public PatternWithMatcher(String pat, DateTimeMatcher matcher) {
            pattern = pat;
            matcherWithSkeleton = matcher;
        }
    }
    private static class PatternWithSkeletonFlag {
        public String pattern;
        public boolean skeletonWasSpecified;
        // Simple constructor
        public PatternWithSkeletonFlag(String pat, boolean skelSpecified) {
            pattern = pat;
            skeletonWasSpecified = skelSpecified;
        }
        @Override
        public String toString() {
            return pattern + "," + skeletonWasSpecified;
        }
    }
    private TreeMap<DateTimeMatcher, PatternWithSkeletonFlag> skeleton2pattern = new TreeMap<>(); // items are in priority order
    private TreeMap<String, PatternWithSkeletonFlag> basePattern_pattern = new TreeMap<>(); // items are in priority order
    private String decimal = "?";
    // For the following, need fallback patterns in case an empty instance 
    // of DateTimePatterngenerator is used for formatting.
    private String[] dateTimeFormats = {
        "{1} {0}",
        "{1} {0}",
        "{1} {0}",
        "{1} {0}"
    };
    private String[] appendItemFormats = new String[TYPE_LIMIT];
    private String[][] fieldDisplayNames = new String[TYPE_LIMIT][DisplayWidth.COUNT];
    private char defaultHourFormatChar = 'H';
    //private boolean chineseMonthHack = false;
    //private boolean isComplete = false;
    private volatile boolean frozen = false;

    private transient DateTimeMatcher current = new DateTimeMatcher();
    private transient FormatParser fp = new FormatParser();
    private transient DistanceInfo _distanceInfo = new DistanceInfo();

    private String[] allowedHourFormats;

    private static final int FRACTIONAL_MASK = 1<<FRACTIONAL_SECOND;
    private static final int SECOND_AND_FRACTIONAL_MASK = (1<<SECOND) | (1<<FRACTIONAL_SECOND);

    // Cache for DateTimePatternGenerator
    private static ICUCache<String, DateTimePatternGenerator> DTPNG_CACHE = new SimpleCache<>();

    private void checkFrozen() {
        if (isFrozen()) {
            throw new UnsupportedOperationException("Attempt to modify frozen object");
        }
    }

    /**
     * We only get called here if we failed to find an exact skeleton. We have broken it into date + time, and look for the pieces.
     * If we fail to find a complete skeleton, we compose in a loop until we have all the fields.
     */
    private String getBestAppending(DateTimeMatcher source, int missingFields, DistanceInfo distInfo, DateTimeMatcher skipMatcher, EnumSet<DTPGflags> flags, int options) {
        String resultPattern = null;
        if (missingFields != 0) {
            PatternWithMatcher resultPatternWithMatcher = getBestRaw(source, missingFields, distInfo, skipMatcher);
            resultPattern = adjustFieldTypes(resultPatternWithMatcher, source, flags, options);

            while (distInfo.missingFieldMask != 0) { // precondition: EVERY single field must work!

                // special hack for SSS. If we are missing SSS, and we had ss but found it, replace the s field according to the
                // number separator
                if ((distInfo.missingFieldMask & SECOND_AND_FRACTIONAL_MASK) == FRACTIONAL_MASK
                        && (missingFields & SECOND_AND_FRACTIONAL_MASK) == SECOND_AND_FRACTIONAL_MASK) {
                    resultPatternWithMatcher.pattern = resultPattern;
                    flags = EnumSet.copyOf(flags);
                    flags.add(DTPGflags.FIX_FRACTIONAL_SECONDS);
                    resultPattern = adjustFieldTypes(resultPatternWithMatcher, source, flags, options);
                    distInfo.missingFieldMask &= ~FRACTIONAL_MASK; // remove bit
                    continue;
                }

                int startingMask = distInfo.missingFieldMask;
                PatternWithMatcher tempWithMatcher = getBestRaw(source, distInfo.missingFieldMask, distInfo, skipMatcher);
                String temp = adjustFieldTypes(tempWithMatcher, source, flags, options);
                int foundMask = startingMask & ~distInfo.missingFieldMask;
                int topField = getTopBitNumber(foundMask);
                resultPattern = SimpleFormatterImpl.formatRawPattern(
                        getAppendFormat(topField), 2, 3, resultPattern, temp, getAppendName(topField));
            }
        }
        return resultPattern;
    }

    private String getAppendName(int foundMask) {
        return "'" + fieldDisplayNames[foundMask][APPENDITEM_WIDTH_INT] + "'";
    }
    private String getAppendFormat(int foundMask) {
        return appendItemFormats[foundMask];
    }

    //    /**
    //     * @param current2
    //     * @return
    //     */
    //    private String adjustSeconds(DateTimeMatcher current2) {
    //        // TODO Auto-generated method stub
    //        return null;
    //    }

    /**
     * @param foundMask
     */
    private int getTopBitNumber(int foundMask) {
        int i = 0;
        while (foundMask != 0) {
            foundMask >>>= 1;
    ++i;
        }
        return i-1;
    }

    private void addCanonicalItems() {
        PatternInfo patternInfo = new PatternInfo();
        // make sure that every valid field occurs once, with a "default" length
        for (int i = 0; i < CANONICAL_ITEMS.length; ++i) {
            addPattern(String.valueOf(CANONICAL_ITEMS[i]), false, patternInfo);
        }
    }

    private PatternWithMatcher getBestRaw(DateTimeMatcher source, int includeMask, DistanceInfo missingFields, DateTimeMatcher skipMatcher) {
        //      if (SHOW_DISTANCE) System.out.println("Searching for: " + source.pattern
        //      + ", mask: " + showMask(includeMask));
        int bestDistance = Integer.MAX_VALUE;
        int bestMissingFieldMask = Integer.MIN_VALUE;
        PatternWithMatcher bestPatternWithMatcher = new PatternWithMatcher("", null);
        DistanceInfo tempInfo = new DistanceInfo();
        for (DateTimeMatcher trial : skeleton2pattern.keySet()) {
            if (trial.equals(skipMatcher)) {
                continue;
            }
            int distance = source.getDistance(trial, includeMask, tempInfo);
            //          if (SHOW_DISTANCE) System.out.println("\tDistance: " + trial.pattern + ":\t"
            //          + distance + ",\tmissing fields: " + tempInfo);

            // Because we iterate over a map the order is undefined. Can change between implementations,
            // versions, and will very likely be different between Java and C/C++.
            // So if we have patterns with the same distance we also look at the missingFieldMask,
            // and we favour the smallest one. Because the field is a bitmask this technically means we
            // favour differences in the "least significant fields". For example we prefer the one with differences
            // in seconds field vs one with difference in the hours field.
            if (distance < bestDistance || (distance == bestDistance && bestMissingFieldMask < tempInfo.missingFieldMask)) {
                bestDistance = distance;
                bestMissingFieldMask = tempInfo.missingFieldMask;
                PatternWithSkeletonFlag patternWithSkelFlag = skeleton2pattern.get(trial);
                bestPatternWithMatcher.pattern = patternWithSkelFlag.pattern;
                // If the best raw match had a specified skeleton then return it too.
                // This can be passed through to adjustFieldTypes to help it do a better job.
                if (patternWithSkelFlag.skeletonWasSpecified) {
                    bestPatternWithMatcher.matcherWithSkeleton = trial;
                } else {
                    bestPatternWithMatcher.matcherWithSkeleton = null;
                }
                missingFields.setTo(tempInfo);
                if (distance == 0) {
                    break;
                }
            }
        }
        return bestPatternWithMatcher;
    }

    /*
     * @param fixFractionalSeconds TODO
     */
    // flags values
    private enum DTPGflags {
        FIX_FRACTIONAL_SECONDS,
        SKELETON_USES_CAP_J,
        // with #13183, no longer need flags for b, B
        ;
    };

    private String adjustFieldTypes(PatternWithMatcher patternWithMatcher, DateTimeMatcher inputRequest, EnumSet<DTPGflags> flags, int options) {
        fp.set(patternWithMatcher.pattern);
        StringBuilder newPattern = new StringBuilder();
        for (Object item : fp.getItems()) {
            if (item instanceof String) {
                newPattern.append(fp.quoteLiteral((String)item));
            } else {
                final VariableField variableField = (VariableField) item;

                StringBuilder fieldBuilder = new StringBuilder(variableField.toString());
                //                int canonicalIndex = getCanonicalIndex(field, true);
                //                if (canonicalIndex < 0) {
                //                    continue; // don't adjust
                //                }
                //                int type = types[canonicalIndex][1];
                int type = variableField.getType();

                // handle day periods - with #13183, no longer need special handling here, integrated with normal types

                if (flags.contains(DTPGflags.FIX_FRACTIONAL_SECONDS) && type == SECOND) {
                    fieldBuilder.append(decimal);
                    inputRequest.original.appendFieldTo(FRACTIONAL_SECOND, fieldBuilder);
                } else if (inputRequest.type[type] != 0) {
                    // Here:
                    // - "reqField" is the field from the originally requested skeleton, with length
                    // "reqFieldLen".
                    // - "field" is the field from the found pattern.
                    //
                    // The adjusted field should consist of characters from the originally requested
                    // skeleton, except in the case of MONTH or WEEKDAY or YEAR, in which case it
                    // should consist of characters from the found pattern. There is some adjustment
                    // in some cases of HOUR to "defaultHourFormatChar". There is explanation
                    // how it is done below.
                    //
                    // The length of the adjusted field (adjFieldLen) should match that in the originally
                    // requested skeleton, except that in the following cases the length of the adjusted field
                    // should match that in the found pattern (i.e. the length of this pattern field should
                    // not be adjusted):
                    // 1. type is HOUR and the corresponding bit in options is not set (ticket #7180).
                    //    Note, we may want to implement a similar change for other numeric fields (MM, dd,
                    //    etc.) so the default behavior is to get locale preference for field length, but
                    //    options bits can be used to override this.
                    // 2. There is a specified skeleton for the found pattern and one of the following is true:
                    //    a) The length of the field in the skeleton (skelFieldLen) is equal to reqFieldLen.
                    //    b) The pattern field is numeric and the skeleton field is not, or vice versa.
                    //
                    // Old behavior was:
                    // normally we just replace the field. However HOUR is special; we only change the length

                    char reqFieldChar = inputRequest.original.getFieldChar(type);
                    int reqFieldLen = inputRequest.original.getFieldLength(type);
                    if ( reqFieldChar == 'E' && reqFieldLen < 3 ) {
                        reqFieldLen = 3; // 1-3 for E are equivalent to 3 for c,e
                    }
                    int adjFieldLen = reqFieldLen;
                    DateTimeMatcher matcherWithSkeleton = patternWithMatcher.matcherWithSkeleton;
                    if ( (type == HOUR && (options & MATCH_HOUR_FIELD_LENGTH)==0) ||
                            (type == MINUTE && (options & MATCH_MINUTE_FIELD_LENGTH)==0) ||
                            (type == SECOND && (options & MATCH_SECOND_FIELD_LENGTH)==0) ) {
                        adjFieldLen = fieldBuilder.length();
                    } else if (matcherWithSkeleton != null && reqFieldChar != 'c' && reqFieldChar != 'e') {
                        // (we skip this section for 'c' and 'e' because unlike the other characters considered in this function,
                        // they have no minimum field length-- 'E' and 'EE' are equivalent to 'EEE', but 'e' and 'ee' are not
                        // equivalent to 'eee' -- see the entries for "week day" in
                        // https://www.unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table for more info)
                        int skelFieldLen = matcherWithSkeleton.original.getFieldLength(type);
                        boolean patFieldIsNumeric = variableField.isNumeric();
                        boolean skelFieldIsNumeric = matcherWithSkeleton.fieldIsNumeric(type);
                        if (skelFieldLen == reqFieldLen
                                || (patFieldIsNumeric && !skelFieldIsNumeric)
                                || (skelFieldIsNumeric && !patFieldIsNumeric)) {
                            // don't adjust the field length in the found pattern
                            adjFieldLen = fieldBuilder.length();
                        }
                    }
                    char c = (type != HOUR
                            && type != MONTH
                            && type != WEEKDAY
                            && (type != YEAR || reqFieldChar=='Y'))
                            ? reqFieldChar
                            : fieldBuilder.charAt(0);
                    if (c == 'E' && adjFieldLen < 3) {
                        // see https://www.unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table:
                        // If we want a numeric day-of-week field, we have to use 'e'-- 'E' doesn't support
                        // numeric day-of-week abbreivations
                        c = 'e';
                    }
                    if (type == HOUR) {
                        // The adjustment here is required to match spec (https://www.unicode.org/reports/tr35/tr35-dates.html#dfst-hour).
                        // It is necessary to match the hour-cycle preferred by the Locale.
                        // Given that, we need to do the following adjustments:
                        // 1. When hour-cycle is h11 it should replace 'h' by 'K'.
                        // 2. When hour-cycle is h23 it should replace 'H' by 'k'.
                        // 3. When hour-cycle is h24 it should replace 'k' by 'H'.
                        // 4. When hour-cycle is h12 it should replace 'K' by 'h'.
                        if (flags.contains(DTPGflags.SKELETON_USES_CAP_J) || reqFieldChar == defaultHourFormatChar) {
                            c = defaultHourFormatChar;
                        } else if (reqFieldChar == 'h' && defaultHourFormatChar == 'K') {
                            c = 'K';
                        } else if (reqFieldChar == 'H' && defaultHourFormatChar == 'k') {
                            c = 'k';
                        } else if (reqFieldChar == 'k' && defaultHourFormatChar == 'H') {
                            c = 'H';
                        } else if (reqFieldChar == 'K' && defaultHourFormatChar == 'h') {
                            c = 'h';
                        }
                    }
                    fieldBuilder = new StringBuilder();
                    for (int i = adjFieldLen; i > 0; --i) fieldBuilder.append(c);
                }
                newPattern.append(fieldBuilder);
            }
        }
        //if (SHOW_DISTANCE) System.out.println("\tRaw: " + pattern);
        return newPattern.toString();
    }

    //  public static String repeat(String s, int count) {
    //  StringBuffer result = new StringBuffer();
    //  for (int i = 0; i < count; ++i) {
    //  result.append(s);
    //  }
    //  return result.toString();
    //  }

    /**
     * internal routine
     * @param pattern The pattern that is passed.
     * @return field value
     * @internal
     * @deprecated This API is ICU internal only.
     */
    @Deprecated
    public String getFields(String pattern) {
        fp.set(pattern);
        StringBuilder newPattern = new StringBuilder();
        for (Object item : fp.getItems()) {
            if (item instanceof String) {
                newPattern.append(fp.quoteLiteral((String)item));
            } else {
                newPattern.append("{" + getName(item.toString()) + "}");
            }
        }
        return newPattern.toString();
    }

    private static String showMask(int mask) {
        StringBuilder result = new StringBuilder();
        for (int i = 0; i < TYPE_LIMIT; ++i) {
            if ((mask & (1<<i)) == 0)
                continue;
            if (result.length() != 0)
                result.append(" | ");
            result.append(FIELD_NAME[i]);
            result.append(" ");
        }
        return result.toString();
    }

    private static final String[] CLDR_FIELD_APPEND = {
        "Era", "Year", "Quarter", "Month", "Week", "*", "Day-Of-Week",
        "Day", "*", "*", "*",
        "Hour", "Minute", "Second", "*", "Timezone"
    };

    private static final String[] CLDR_FIELD_NAME = {
        "era", "year", "quarter", "month", "week", "weekOfMonth", "weekday",
        "day", "dayOfYear", "weekdayOfMonth", "dayperiod",
        "hour", "minute", "second", "*", "zone"
    };

    private static final String[] FIELD_NAME = {
        "Era", "Year", "Quarter", "Month", "Week_in_Year", "Week_in_Month", "Weekday",
        "Day", "Day_Of_Year", "Day_of_Week_in_Month", "Dayperiod",
        "Hour", "Minute", "Second", "Fractional_Second", "Zone"
    };


    private static final String[] CANONICAL_ITEMS = {
        "G", "y", "Q", "M", "w", "W", "E",
        "d", "D", "F", "a",
        "H", "m", "s", "S", "v"
    };

    // canon    DateTimePatternGen      CLDR fields
    // char     field                   bundle key
    // ----     --------------------    ----------------
    // 'G', //  0 ERA                   "era"
    // 'y', //  1 YEAR                  "year"
    // 'Q', //  2 QUARTER               "quarter"
    // 'M', //  3 MONTH                 "month"
    // 'w', //  4 WEEK_OF_YEAR,         "week"
    // 'W', //  5 WEEK_OF_MONTH         "weekOfMonth"
    // 'E', //  6 WEEKDAY               "weekday"
    // 'd', //  7 DAY                   "day"
    // 'D', //  8 DAY_OF_YEAR           "dayOfYear"
    // 'F', //  9 DAY_OF_WEEK_IN_MONTH  "weekdayOfMonth"
    // 'a', // 10 DAYPERIOD             "dayperiod"
    // 'H', // 11 HOUR                  "hour"
    // 'm', // 12 MINUTE                "minute"
    // 's', // 13 SECOND                "second"
    // 'S', // 14 FRACTIONAL_SECOND
    // 'v', // 15 ZONE                  "zone"

    private static final Set<String> CANONICAL_SET = new HashSet<>(Arrays.asList(CANONICAL_ITEMS));
    private Set<String> cldrAvailableFormatKeys = new HashSet<>(20);

    private static final int
    DATE_MASK = (1<<DAYPERIOD) - 1,
    TIME_MASK = (1<<TYPE_LIMIT) - 1 - DATE_MASK;

    private static final int // numbers are chosen to express 'distance'
    DELTA = 0x10,
    NUMERIC = 0x100,
    NONE = 0,
    NARROW = -0x101,
    SHORTER = -0x102,
    SHORT = -0x103,
    LONG = -0x104,
    EXTRA_FIELD =   0x10000,
    MISSING_FIELD = 0x1000;


    private static String getName(String s) {
        int i = getCanonicalIndex(s, true);
        String name = FIELD_NAME[types[i][1]];
        if (types[i][2] < 0) {
            name += ":S"; // string
        }
        else {
            name += ":N";
        }
        return name;
    }

    /**
     * Get the canonical index, or return -1 if illegal.
     * @param s
     * @param strict TODO
     */
    private static int getCanonicalIndex(String s, boolean strict) {
        int len = s.length();
        if (len == 0) {
            return -1;
        }
        int ch = s.charAt(0);
        //      verify that all are the same character
        for (int i = 1; i < len; ++i) {
            if (s.charAt(i) != ch) {
                return -1;
            }
        }
        int bestRow = -1;
        for (int i = 0; i < types.length; ++i) {
            int[] row = types[i];
            if (row[0] != ch) continue;
            bestRow = i;
            if (row[3] > len) continue;
            if (row[row.length-1] < len) continue;
            return i;
        }
        return strict ? -1 : bestRow;
    }

    /**
     * Gets the canonical character associated with the specified field (ERA, YEAR, etc).
     */
    private static char getCanonicalChar(int field, char reference) {
        // Special case: distinguish between 12-hour and 24-hour
        if (reference == 'h' || reference == 'K') {
            return 'h';
        }

        // Linear search over types (return the top entry for each field)
        for (int i = 0; i < types.length; ++i) {
            int[] row = types[i];
            if (row[1] == field) {
                return (char) row[0];
            }
        }
        throw new IllegalArgumentException("Could not find field " + field);
    }

    private static final int[][] types = {
        // the order here makes a difference only when searching for single field.
        // format is:
        // pattern character, main type, weight, min length, weight
        {'G', ERA, SHORT, 1, 3},
        {'G', ERA, LONG, 4},
        {'G', ERA, NARROW, 5},

        {'y', YEAR, NUMERIC, 1, 20},
        {'Y', YEAR, NUMERIC + DELTA, 1, 20},
        {'u', YEAR, NUMERIC + 2*DELTA, 1, 20},
        {'r', YEAR, NUMERIC + 3*DELTA, 1, 20},
        {'U', YEAR, SHORT, 1, 3},
        {'U', YEAR, LONG, 4},
        {'U', YEAR, NARROW, 5},

        {'Q', QUARTER, NUMERIC, 1, 2},
        {'Q', QUARTER, SHORT, 3},
        {'Q', QUARTER, LONG, 4},
        {'Q', QUARTER, NARROW, 5},
        {'q', QUARTER, NUMERIC + DELTA, 1, 2},
        {'q', QUARTER, SHORT - DELTA, 3},
        {'q', QUARTER, LONG - DELTA, 4},
        {'q', QUARTER, NARROW - DELTA, 5},

        {'M', MONTH, NUMERIC, 1, 2},
        {'M', MONTH, SHORT, 3},
        {'M', MONTH, LONG, 4},
        {'M', MONTH, NARROW, 5},
        {'L', MONTH, NUMERIC + DELTA, 1, 2},
        {'L', MONTH, SHORT - DELTA, 3},
        {'L', MONTH, LONG - DELTA, 4},
        {'L', MONTH, NARROW - DELTA, 5},
        {'l', MONTH, NUMERIC + DELTA, 1, 1},

        {'w', WEEK_OF_YEAR, NUMERIC, 1, 2},

        {'W', WEEK_OF_MONTH, NUMERIC, 1},

        {'E', WEEKDAY, SHORT, 1, 3},
        {'E', WEEKDAY, LONG, 4},
        {'E', WEEKDAY, NARROW, 5},
        {'E', WEEKDAY, SHORTER, 6},
        {'c', WEEKDAY, NUMERIC + 2*DELTA, 1, 2},
        {'c', WEEKDAY, SHORT - 2*DELTA, 3},
        {'c', WEEKDAY, LONG - 2*DELTA, 4},
        {'c', WEEKDAY, NARROW - 2*DELTA, 5},
        {'c', WEEKDAY, SHORTER - 2*DELTA, 6},
        {'e', WEEKDAY, NUMERIC + DELTA, 1, 2}, // 'e' is currently not used in CLDR data, should not be canonical
        {'e', WEEKDAY, SHORT - DELTA, 3},
        {'e', WEEKDAY, LONG - DELTA, 4},
        {'e', WEEKDAY, NARROW - DELTA, 5},
        {'e', WEEKDAY, SHORTER - DELTA, 6},

        {'d', DAY, NUMERIC, 1, 2},
        {'g', DAY, NUMERIC + DELTA, 1, 20}, // really internal use, so we don't care

        {'D', DAY_OF_YEAR, NUMERIC, 1, 3},

        {'F', DAY_OF_WEEK_IN_MONTH, NUMERIC, 1},

        {'a', DAYPERIOD, SHORT, 1, 3},
        {'a', DAYPERIOD, LONG, 4},
        {'a', DAYPERIOD, NARROW, 5},
        {'b', DAYPERIOD, SHORT - DELTA, 1, 3},
        {'b', DAYPERIOD, LONG - DELTA, 4},
        {'b', DAYPERIOD, NARROW - DELTA, 5},
        // b needs to be closer to a than to B, so we make this 3*DELTA
        {'B', DAYPERIOD, SHORT - 3*DELTA, 1, 3},
        {'B', DAYPERIOD, LONG - 3*DELTA, 4},
        {'B', DAYPERIOD, NARROW - 3*DELTA, 5},

        {'H', HOUR, NUMERIC + 10*DELTA, 1, 2}, // 24 hour
        {'k', HOUR, NUMERIC + 11*DELTA, 1, 2},
        {'h', HOUR, NUMERIC, 1, 2}, // 12 hour
        {'K', HOUR, NUMERIC + DELTA, 1, 2},

        {'m', MINUTE, NUMERIC, 1, 2},

        {'s', SECOND, NUMERIC, 1, 2},
        {'A', SECOND, NUMERIC + DELTA, 1, 1000},

        {'S', FRACTIONAL_SECOND, NUMERIC, 1, 1000},

        {'v', ZONE, SHORT - 2*DELTA, 1},
        {'v', ZONE, LONG - 2*DELTA, 4},
        {'z', ZONE, SHORT, 1, 3},
        {'z', ZONE, LONG, 4},
        {'Z', ZONE, NARROW - DELTA, 1, 3},
        {'Z', ZONE, LONG - DELTA, 4},
        {'Z', ZONE, SHORT - DELTA, 5},
        {'O', ZONE, SHORT - DELTA, 1},
        {'O', ZONE, LONG - DELTA, 4},
        {'V', ZONE, SHORT - DELTA, 1},
        {'V', ZONE, LONG - DELTA, 2},
        {'V', ZONE, LONG-1 - DELTA, 3},
        {'V', ZONE, LONG-2 - DELTA, 4},
        {'X', ZONE, NARROW - DELTA, 1},
        {'X', ZONE, SHORT - DELTA, 2},
        {'X', ZONE, LONG - DELTA, 4},
        {'x', ZONE, NARROW - DELTA, 1},
        {'x', ZONE, SHORT - DELTA, 2},
        {'x', ZONE, LONG - DELTA, 4},
    };


    /**
     * A compact storage mechanism for skeleton field strings.  Several dozen of these will be created
     * for a typical DateTimePatternGenerator instance.
     * @author sffc
     */
    private static class SkeletonFields {
        private byte[] chars = new byte[TYPE_LIMIT];
        private byte[] lengths = new byte[TYPE_LIMIT];
        private static final byte DEFAULT_CHAR = '\0';
        private static final byte DEFAULT_LENGTH = 0;

        public void clear() {
            Arrays.fill(chars, DEFAULT_CHAR);
            Arrays.fill(lengths, DEFAULT_LENGTH);
        }

        void copyFieldFrom(SkeletonFields other, int field) {
            chars[field] = other.chars[field];
            lengths[field] = other.lengths[field];
        }

        void clearField(int field) {
            chars[field] = DEFAULT_CHAR;
            lengths[field] = DEFAULT_LENGTH;
        }

        char getFieldChar(int field) {
            return (char) chars[field];
        }

        int getFieldLength(int field) {
            return lengths[field];
        }

        void populate(int field, String value) {
            // Ensure no loss in character data
            for (char ch : value.toCharArray()) {
                assert ch == value.charAt(0);
            }

            populate(field, value.charAt(0), value.length());
        }

        void populate(int field, char ch, int length) {
            assert ch <= Byte.MAX_VALUE;
            assert length <= Byte.MAX_VALUE;

            chars[field] = (byte) ch;
            lengths[field] = (byte) length;
        }

        public boolean isFieldEmpty(int field) {
            return lengths[field] == DEFAULT_LENGTH;
        }

        @Override
        public String toString() {
            return appendTo(new StringBuilder(), false, false).toString();
        }

        public String toString(boolean skipDayPeriod) {
            return appendTo(new StringBuilder(), false, skipDayPeriod).toString();
        }

        @SuppressWarnings("unused")
        public String toCanonicalString() {
            return appendTo(new StringBuilder(), true, false).toString();
        }

        public String toCanonicalString(boolean skipDayPeriod) {
            return appendTo(new StringBuilder(), true, skipDayPeriod).toString();
        }

        @SuppressWarnings("unused")
        public StringBuilder appendTo(StringBuilder sb) {
            return appendTo(sb, false, false);
        }

        private StringBuilder appendTo(StringBuilder sb, boolean canonical, boolean skipDayPeriod) {
            for (int i=0; i<TYPE_LIMIT; ++i) {
                if (skipDayPeriod && i == DAYPERIOD) {
                    continue;
                }
                appendFieldTo(i, sb, canonical);
            }
            return sb;
        }

        public StringBuilder appendFieldTo(int field, StringBuilder sb) {
            return appendFieldTo(field, sb, false);
        }

        private StringBuilder appendFieldTo(int field, StringBuilder sb, boolean canonical) {
            char ch = (char) chars[field];
            int length = lengths[field];

            if (canonical) {
                ch = getCanonicalChar(field, ch);
            }

            for (int i=0; i<length; i++) {
                sb.append(ch);
            }
            return sb;
        }

        public int compareTo(SkeletonFields other) {
            for (int i = 0; i < TYPE_LIMIT; ++i) {
                int charDiff = chars[i] - other.chars[i];
                if (charDiff != 0) {
                    return charDiff;
                }
                int lengthDiff = lengths[i] - other.lengths[i];
                if (lengthDiff != 0) {
                    return lengthDiff;
                }
            }
            return 0;
        }

        @Override
        public boolean equals(Object other) {
            return this == other || (other != null && other instanceof SkeletonFields
                && compareTo((SkeletonFields) other) == 0);
        }

        @Override
        public int hashCode() {
            return Arrays.hashCode(chars) ^ Arrays.hashCode(lengths);
        }
    }


    private static class DateTimeMatcher implements Comparable<DateTimeMatcher> {
        //private String pattern = null;
        private int[] type = new int[TYPE_LIMIT];
        private SkeletonFields original = new SkeletonFields();
        private SkeletonFields baseOriginal = new SkeletonFields();
        private boolean addedDefaultDayPeriod = false;

        // just for testing; fix to make multi-threaded later
        // private static FormatParser fp = new FormatParser();

        public boolean fieldIsNumeric(int field) {
            return type[field] > 0;
        }

        @Override
        public String toString() {
            // for backward compatibility: addedDefaultDayPeriod true => DateTimeMatcher.set
            // added a single 'a' that was not in the provided skeleton, and it will be
            // removed when generating the skeleton to return.
            return original.toString(addedDefaultDayPeriod);
        }

        // returns a string like toString but using the canonical character for most types,
        // e.g. M for M or L, E for E or c, y for y or U, etc. The hour field is canonicalized
        // to 'H' (for 24-hour types) or 'h' (for 12-hour types)
        public String toCanonicalString() {
            // for backward compatibility: addedDefaultDayPeriod true => DateTimeMatcher.set
            // added a single 'a' that was not in the provided skeleton, and it will be
            // removed when generating the skeleton to return.
            return original.toCanonicalString(addedDefaultDayPeriod);
        }

        String getBasePattern() {
            // for backward compatibility: addedDefaultDayPeriod true => DateTimeMatcher.set
            // added a single 'a' that was not in the provided skeleton, and it will be
            // removed when generating the skeleton to return.
            return baseOriginal.toString(addedDefaultDayPeriod);
        }

        DateTimeMatcher set(String pattern, FormatParser fp, boolean allowDuplicateFields) {
            // Reset any data stored in this instance
            Arrays.fill(type, NONE);
            original.clear();
            baseOriginal.clear();
            addedDefaultDayPeriod = false;

            fp.set(pattern);
            for (Object obj : fp.getItems()) {
                if (!(obj instanceof VariableField)) {
                    continue;
                }
                VariableField item = (VariableField)obj;
                String value = item.toString();
                // don't skip 'a' anymore, dayPeriod handled specially below
                int canonicalIndex = item.getCanonicalIndex();
                //                if (canonicalIndex < 0) {
                //                    throw new IllegalArgumentException("Illegal field:\t"
                //                            + field + "\t in " + pattern);
                //                }
                int[] row = types[canonicalIndex];
                int field = row[1];
                if (!original.isFieldEmpty(field)) {
                    char ch1 = original.getFieldChar(field);
                    char ch2 = value.charAt(0);
                    if ( allowDuplicateFields ||
                            (ch1 == 'r' && ch2 == 'U') ||
                            (ch1 == 'U' && ch2 == 'r') ) {
                        continue;
                    }
                    throw new IllegalArgumentException("Conflicting fields:\t"
                            + ch1 + ", " + value + "\t in " + pattern);
                }
                original.populate(field, value);
                char repeatChar = (char)row[0];
                int repeatCount = row[3];
                if ("GEzvQ".indexOf(repeatChar) >= 0) repeatCount = 1;
                baseOriginal.populate(field, repeatChar, repeatCount);
                int subField = row[2];
                if (subField > 0) subField += value.length();
                type[field] = subField;
            }

            // #20739, we have a skeleton with minutes and milliseconds, but no seconds
            //
            // Theoretically we would need to check and fix all fields with "gaps":
            // for example year-day (no month), month-hour (no day), and so on, All the possible field combinations.
            // Plus some smartness: year + hour => should we add month, or add day-of-year?
            // What about month + day-of-week, or month + am/pm indicator.
            // I think beyond a certain point we should not try to fix bad developer input and try guessing what they mean.
            // Garbage in, garbage out.
            if (!original.isFieldEmpty(MINUTE) && !original.isFieldEmpty(FRACTIONAL_SECOND) && original.isFieldEmpty(SECOND)) {
                // Force the use of seconds
                for (int i = 0; i < types.length; ++i) {
                    int[] row = types[i];
                    if (row[1] == SECOND) {
                        // first entry for SECOND
                        original.populate(SECOND, (char)row[0], row[3]);
                        baseOriginal.populate(SECOND, (char)row[0], row[3]);
                        // We add value.length, same as above, when type is first initialized.
                        // The value we want to "fake" here is "s", and 1 means "s".length()
                        int subField = row[2];
                        type[SECOND] = (subField > 0) ? subField + 1 : subField;
                        break;
                    }
                }
            }

            // #13183, handle special behavior for day period characters (a, b, B)
            if (!original.isFieldEmpty(HOUR)) {
                if (original.getFieldChar(HOUR)=='h' || original.getFieldChar(HOUR)=='K') {
                    // We have a skeleton with 12-hour-cycle format
                    if (original.isFieldEmpty(DAYPERIOD)) {
                        // But we do not have a day period in the skeleton; add the default DAYPERIOD (currently "a")
                        for (int i = 0; i < types.length; ++i) {
                            int[] row = types[i];
                            if (row[1] == DAYPERIOD) {
                                // first entry for DAYPERIOD
                                original.populate(DAYPERIOD, (char)row[0], row[3]);
                                baseOriginal.populate(DAYPERIOD, (char)row[0], row[3]);
                                type[DAYPERIOD] = row[2];
                                addedDefaultDayPeriod = true;
                                break;
                            }
                        }
                    }
                } else if (!original.isFieldEmpty(DAYPERIOD)) {
                    // Skeleton has 24-hour-cycle hour format and has dayPeriod, delete dayPeriod (i.e. ignore it)
                    original.clearField(DAYPERIOD);
                    baseOriginal.clearField(DAYPERIOD);
                    type[DAYPERIOD] = NONE;
                }
            }
            return this;
        }

        int getFieldMask() {
            int result = 0;
            for (int i = 0; i < type.length; ++i) {
                if (type[i] != 0) result |= (1<<i);
            }
            return result;
        }

        @SuppressWarnings("unused")
        void extractFrom(DateTimeMatcher source, int fieldMask) {
            for (int i = 0; i < type.length; ++i) {
                if ((fieldMask & (1<<i)) != 0) {
                    type[i] = source.type[i];
                    original.copyFieldFrom(source.original, i);
                } else {
                    type[i] = NONE;
                    original.clearField(i);
                }
            }
        }

        int getDistance(DateTimeMatcher other, int includeMask, DistanceInfo distanceInfo) {
            int result = 0;
            distanceInfo.clear();
            for (int i = 0; i < TYPE_LIMIT; ++i) {
                int myType = (includeMask & (1<<i)) == 0 ? 0 : type[i];
                int otherType = other.type[i];
                if (myType == otherType) continue; // identical (maybe both zero) add 0
                if (myType == 0) { // and other is not
                    result += EXTRA_FIELD;
                    distanceInfo.addExtra(i);
                } else if (otherType == 0) { // and mine is not
                    result += MISSING_FIELD;
                    distanceInfo.addMissing(i);
                } else {
                    result += Math.abs(myType - otherType); // square of mismatch
                }
            }
            return result;
        }

        @Override
        public int compareTo(DateTimeMatcher that) {
            int result = original.compareTo(that.original);
            return result > 0 ? -1 : result < 0 ? 1 : 0; // Reverse the order.
        }

        @Override
        public boolean equals(Object other) {
            return this == other || (other != null && other instanceof DateTimeMatcher
                && original.equals(((DateTimeMatcher) other).original));
        }

        @Override
        public int hashCode() {
            return original.hashCode();
        }
    }

    private static class DistanceInfo {
        int missingFieldMask;
        int extraFieldMask;
        void clear() {
            missingFieldMask = extraFieldMask = 0;
        }
        void setTo(DistanceInfo other) {
            missingFieldMask = other.missingFieldMask;
            extraFieldMask = other.extraFieldMask;
        }
        void addMissing(int field) {
            missingFieldMask |= (1<<field);
        }
        void addExtra(int field) {
            extraFieldMask |= (1<<field);
        }
        @Override
        public String toString() {
            return "missingFieldMask: " + DateTimePatternGenerator.showMask(missingFieldMask)
                    + ", extraFieldMask: " + DateTimePatternGenerator.showMask(extraFieldMask);
        }
    }
}
//eof
