LocalePriorityList.java revision 836e6b40a94ec3fb7545a76cb072960442b7eee9
12ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller/* GENERATED SOURCE. DO NOT MODIFY. */
22ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller/*
32ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller *******************************************************************************
42ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Copyright (C) 2010-2014, Google, Inc.; International Business Machines      *
52ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Corporation and others. All Rights Reserved.                                *
62ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller *******************************************************************************
72ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */
82ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
92ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerpackage android.icu.util;
102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.util.Collections;
122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.util.Comparator;
132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.util.Iterator;
142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.util.LinkedHashMap;
152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.util.LinkedHashSet;
162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.util.Map;
172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.util.Map.Entry;
182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.util.Set;
192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.util.TreeMap;
202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.util.regex.Matcher;
212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.util.regex.Pattern;
222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller/**
242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Provides an immutable list of languages (locales) in priority order.
252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * The string format is based on the Accept-Language format
262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * {@link "http://www.ietf.org/rfc/rfc2616.txt"}, such as
272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * "af, en, fr;q=0.9". Syntactically it is slightly
282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * more lenient, in allowing extra whitespace between elements, extra commas,
292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * and more than 3 decimals (on input), and pins between 0 and 1.
302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <p>In theory, Accept-Language indicates the relative 'quality' of each item,
312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * but in practice, all of the browsers just take an ordered list, like
322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * "en, fr, de", and synthesize arbitrary quality values that put these in the
332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * right order, like: "en, fr;q=0.7, de;q=0.3". The quality values in these de facto
342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * semantics thus have <b>nothing</b> to do with the relative qualities of the
352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * original. Accept-Language also doesn't
362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * specify the interpretation of multiple instances, eg what "en, fr, en;q=.5"
372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * means.
382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <p>There are various ways to build a LanguagePriorityList, such
392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * as using the following equivalent patterns:
402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller *
412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <pre>
422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * list = LanguagePriorityList.add(&quot;af, en, fr;q=0.9&quot;).build();
432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller *
442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * list2 = LanguagePriorityList
452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller *  .add(ULocale.forString(&quot;af&quot;))
462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller *  .add(ULocale.ENGLISH)
472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller *  .add(ULocale.FRENCH, 0.9d)
482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller *  .build();
492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * </pre>
502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * When the list is built, the internal values are sorted in descending order by
512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * weight, and then by input order. That is, if two languages have the same weight, the first one in the original order
522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * comes first. If exactly the same language tag appears multiple times,
532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * the last one wins.
542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller *
552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * There are two options when building. If preserveWeights are on, then "de;q=0.3, ja;q=0.3, en, fr;q=0.7, de " would result in the following:
562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * <pre> en;q=1.0
572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * de;q=1.0
582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * fr;q=0.7
592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * ja;q=0.3</pre>
602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * If it is off (the default), then all weights are reset to 1.0 after reordering.
612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * This is to match the effect of the Accept-Language semantics as used in browsers, and results in the following:
622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller *  * <pre> en;q=1.0
632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * de;q=1.0
642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * fr;q=1.0
652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * ja;q=1.0</pre>
662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @author markdavis@google.com
672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * @stable ICU 4.4
68836e6b40a94ec3fb7545a76cb072960442b7eee9Neil Fuller * @hide Only a subset of ICU is exposed in Android
69704056c96cc5de08c2425fa1679a5c0a92c5a88eNeil Fuller * @hide All android.icu classes are currently hidden
702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */
712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerpublic class LocalePriorityList implements Iterable<ULocale> {
722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static final double D0 = 0.0d;
732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static final Double D1 = 1.0d;
742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static final Pattern languageSplitter = Pattern.compile("\\s*,\\s*");
762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static final Pattern weightSplitter = Pattern
772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    .compile("\\s*(\\S*)\\s*;\\s*q\\s*=\\s*(\\S*)");
782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private final Map<ULocale, Double> languagesAndWeights;
792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Add a language code to the list being built, with weight 1.0.
822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *
832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @param languageCode locale/language to be added
842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @return internal builder, for chaining
852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 4.4
862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static Builder add(ULocale... languageCode) {
882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return new Builder().add(languageCode);
892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Add a language code to the list being built, with specified weight.
932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *
942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @param languageCode locale/language to be added
952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @param weight value from 0.0 to 1.0
962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @return internal builder, for chaining
972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 4.4
982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static Builder add(ULocale languageCode, final double weight) {
1002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return new Builder().add(languageCode, weight);
1012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
1042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Add a language priority list.
1052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *
1062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @param languagePriorityList list to add all the members of
1072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @return internal builder, for chaining
1082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 4.4
1092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
1102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static Builder add(LocalePriorityList languagePriorityList) {
1112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return new Builder().add(languagePriorityList);
1122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
1152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Add language codes to the list being built, using a string in rfc2616
1162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * (lenient) format, where each language is a valid {@link ULocale}.
1172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *
1182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @param acceptLanguageString String in rfc2616 format (but leniently parsed)
1192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @return internal builder, for chaining
1202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 4.4
1212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
1222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static Builder add(String acceptLanguageString) {
1232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return new Builder().add(acceptLanguageString);
1242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
1272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Return the weight for a given language, or null if there is none. Note that
1282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * the weights may be adjusted from those used to build the list.
1292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     *
1302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @param language to get weight of
1312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @return weight
1322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 4.4
1332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
1342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public Double getWeight(ULocale language) {
1352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return languagesAndWeights.get(language);
1362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
1392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * {@inheritDoc}
1402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 4.4
1412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
1422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    @Override
1432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public String toString() {
1442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        final StringBuilder result = new StringBuilder();
1452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        for (final ULocale language : languagesAndWeights.keySet()) {
1462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if (result.length() != 0) {
1472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                result.append(", ");
1482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
1492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            result.append(language);
1502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            double weight = languagesAndWeights.get(language);
1512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if (weight != D1) {
1522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                result.append(";q=").append(weight);
1532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
1542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
1552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return result.toString();
1562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
1592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * {@inheritDoc}
1602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 4.4
1612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
1622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public Iterator<ULocale> iterator() {
1632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return languagesAndWeights.keySet().iterator();
1642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
1672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * {@inheritDoc}
1682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 4.4
1692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
1702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    @Override
1712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public boolean equals(final Object o) {
1722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if (o == null) {
1732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return false;
1742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
1752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        if (this == o) {
1762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return true;
1772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
1782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        try {
1792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            final LocalePriorityList that = (LocalePriorityList) o;
1802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return languagesAndWeights.equals(that.languagesAndWeights);
1812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        } catch (final RuntimeException e) {
1822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return false;
1832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
1842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
1872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * {@inheritDoc}
1882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 4.4
1892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
1902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    @Override
1912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public int hashCode() {
1922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        return languagesAndWeights.hashCode();
1932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
1942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    // ==================== Privates ====================
1962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
1982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private LocalePriorityList(final Map<ULocale, Double> languageToWeight) {
1992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        this.languagesAndWeights = languageToWeight;
2002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
2012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    /**
2032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * Class used for building LanguagePriorityLists
2042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     * @stable ICU 4.4
2052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller     */
2062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    public static class Builder {
2072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /**
2082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * These store the input languages and weights, in chronological order,
2092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * where later additions override previous ones.
2102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         */
2112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        private final Map<ULocale, Double> languageToWeight
2122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        = new LinkedHashMap<ULocale, Double>();
2132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /*
2152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * Private constructor, only used by LocalePriorityList
2162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         */
2172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        private Builder() {
2182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
2192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /**
2212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * Creates a LocalePriorityList.  This is equivalent to
2222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * {@link Builder#build(boolean) Builder.build(false)}.
2232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         *
2242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * @return A LocalePriorityList
2252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * @stable ICU 4.4
2262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         */
2272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        public LocalePriorityList build() {
2282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return build(false);
2292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
2302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /**
2322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * Creates a LocalePriorityList.
2332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         *
2342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * @param preserveWeights when true, the weights originally came
2352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * from a language priority list specified by add() are preserved.
2362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * @return A LocalePriorityList
2372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * @stable ICU 4.4
2382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         */
2392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        public LocalePriorityList build(boolean preserveWeights) {
2402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            // Walk through the input list, collecting the items with the same weights.
2412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            final Map<Double, Set<ULocale>> doubleCheck = new TreeMap<Double, Set<ULocale>>(
2422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    myDescendingDouble);
2432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            for (final ULocale lang : languageToWeight.keySet()) {
2442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                Double weight = languageToWeight.get(lang);
2452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                Set<ULocale> s = doubleCheck.get(weight);
2462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                if (s == null) {
2472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    doubleCheck.put(weight, s = new LinkedHashSet<ULocale>());
2482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
2492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                s.add(lang);
2502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
2512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            // We now have a bunch of items sorted by weight, then chronologically.
2522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            // We can now create a list in the right order
2532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            final Map<ULocale, Double> temp = new LinkedHashMap<ULocale, Double>();
2542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            for (Entry<Double, Set<ULocale>> langEntry : doubleCheck.entrySet()) {
2552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                final Double weight = langEntry.getKey();
2562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                for (final ULocale lang : langEntry.getValue()) {
2572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    temp.put(lang, preserveWeights ? weight : D1);
2582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
2592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
2602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return new LocalePriorityList(Collections.unmodifiableMap(temp));
2612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
2622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /**
2642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * Adds a LocalePriorityList
2652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         *
2662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * @param languagePriorityList a LocalePriorityList
2672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * @return this, for chaining
2682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * @stable ICU 4.4
2692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         */
2702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        public Builder add(
2712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                final LocalePriorityList languagePriorityList) {
2722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            for (final ULocale language : languagePriorityList.languagesAndWeights
2732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    .keySet()) {
2742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                add(language, languagePriorityList.languagesAndWeights.get(language));
2752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
2762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return this;
2772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
2782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /**
2802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * Adds a new language code, with weight = 1.0.
2812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         *
2822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * @param languageCode to add with weight 1.0
2832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * @return this, for chaining
2842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * @stable ICU 4.4
2852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         */
2862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        public Builder add(final ULocale languageCode) {
2872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return add(languageCode, D1);
2882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
2892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
2902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /**
2912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * Adds language codes, with each having weight = 1.0.
2922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         *
2932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * @param languageCodes List of language codes.
2942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * @return this, for chaining.
2952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * @stable ICU 4.4
2962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         */
2972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        public Builder add(ULocale... languageCodes) {
2982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            for (final ULocale languageCode : languageCodes) {
2992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                add(languageCode, D1);
3002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
3012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return this;
3022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
3032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
3042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /**
3052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * Adds a new supported languageCode, with specified weight. Overrides any
3062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * previous weight for the language.
3072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         *
3082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * @param languageCode language/locale to add
3092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * @param weight value between 0.0 and 1.1
3102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * @return this, for chaining.
3112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * @stable ICU 4.4
3122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         */
3132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        public Builder add(final ULocale languageCode,
3142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                double weight) {
3152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if (languageToWeight.containsKey(languageCode)) {
3162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                languageToWeight.remove(languageCode);
3172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
3182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            if (weight <= D0) {
3192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                return this; // skip zeros
3202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            } else if (weight > D1) {
3212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                weight = D1;
3222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
3232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            languageToWeight.put(languageCode, weight);
3242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return this;
3252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
3262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
3272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        /**
3282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * Adds rfc2616 list.
3292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         *
3302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * @param acceptLanguageList in rfc2616 format
3312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * @return this, for chaining.
3322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         * @stable ICU 4.4
3332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller         */
3342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        public Builder add(final String acceptLanguageList) {
3352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            final String[] items = languageSplitter.split(acceptLanguageList.trim());
3362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            final Matcher itemMatcher = weightSplitter.matcher("");
3372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            for (final String item : items) {
3382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                if (itemMatcher.reset(item).matches()) {
3392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    final ULocale language = new ULocale(itemMatcher.group(1));
3402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    final double weight = Double.parseDouble(itemMatcher.group(2));
3412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    if (!(weight >= D0 && weight <= D1)) { // do ! for NaN
3422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                        throw new IllegalArgumentException("Illegal weight, must be 0..1: "
3432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                                + weight);
3442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    }
3452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    add(language, weight);
3462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                } else if (item.length() != 0) {
3472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                    add(new ULocale(item));
3482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller                }
3492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            }
3502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return this;
3512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
3522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    }
3532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller
3542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    private static Comparator<Double> myDescendingDouble = new Comparator<Double>() {
3552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        public int compare(Double o1, Double o2) {
3562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller            return -o1.compareTo(o2);
3572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller        }
3582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller    };
3592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller}
360