12ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller/* GENERATED SOURCE. DO NOT MODIFY. */ 2f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert// © 2016 and later: Unicode, Inc. and others. 3f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert// License & terms of use: http://www.unicode.org/copyright.html#License 42ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller/* 52ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller ******************************************************************************* 62ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Copyright (C) 2009-2010, International Business Machines Corporation and * 72ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * others. All Rights Reserved. * 82ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller ******************************************************************************* 92ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerpackage android.icu.impl.locale; 112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.util.ArrayList; 132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.util.HashMap; 142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.util.HashSet; 152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.util.List; 162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerimport java.util.Set; 172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 181537b2f39245c07b00aa78c3600f7aebcb172490Neil Fuller/** 191537b2f39245c07b00aa78c3600f7aebcb172490Neil Fuller * @hide Only a subset of ICU is exposed in Android 20836e6b40a94ec3fb7545a76cb072960442b7eee9Neil Fuller */ 212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fullerpublic final class InternalLocaleBuilder { 222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller private static final boolean JDKIMPL = false; 242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller private String _language = ""; 262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller private String _script = ""; 272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller private String _region = ""; 282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller private String _variant = ""; 292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller private static final CaseInsensitiveChar PRIVUSE_KEY = new CaseInsensitiveChar(LanguageTag.PRIVATEUSE.charAt(0)); 312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller private HashMap<CaseInsensitiveChar, String> _extensions; 332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller private HashSet<CaseInsensitiveString> _uattributes; 342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller private HashMap<CaseInsensitiveString, String> _ukeywords; 352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public InternalLocaleBuilder() { 382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public InternalLocaleBuilder setLanguage(String language) throws LocaleSyntaxException { 412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (language == null || language.length() == 0) { 422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _language = ""; 432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } else { 442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (!LanguageTag.isLanguage(language)) { 452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller throw new LocaleSyntaxException("Ill-formed language: " + language, 0); 462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _language = language; 482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return this; 502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public InternalLocaleBuilder setScript(String script) throws LocaleSyntaxException { 532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (script == null || script.length() == 0) { 542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _script = ""; 552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } else { 562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (!LanguageTag.isScript(script)) { 572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller throw new LocaleSyntaxException("Ill-formed script: " + script, 0); 582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _script = script; 602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return this; 622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public InternalLocaleBuilder setRegion(String region) throws LocaleSyntaxException { 652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (region == null || region.length() == 0) { 662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _region = ""; 672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } else { 682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (!LanguageTag.isRegion(region)) { 692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller throw new LocaleSyntaxException("Ill-formed region: " + region, 0); 702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _region = region; 722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return this; 742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public InternalLocaleBuilder setVariant(String variant) throws LocaleSyntaxException { 772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (variant == null || variant.length() == 0) { 782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _variant = ""; 792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } else { 802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // normalize separators to "_" 812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller String var = variant.replaceAll(LanguageTag.SEP, BaseLocale.SEP); 822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller int errIdx = checkVariants(var, BaseLocale.SEP); 832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (errIdx != -1) { 842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller throw new LocaleSyntaxException("Ill-formed variant: " + variant, errIdx); 852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _variant = var; 872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return this; 892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public InternalLocaleBuilder addUnicodeLocaleAttribute(String attribute) throws LocaleSyntaxException { 922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (attribute == null || !UnicodeLocaleExtension.isAttribute(attribute)) { 932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller throw new LocaleSyntaxException("Ill-formed Unicode locale attribute: " + attribute); 942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // Use case insensitive string to prevent duplication 962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (_uattributes == null) { 972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _uattributes = new HashSet<CaseInsensitiveString>(4); 982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _uattributes.add(new CaseInsensitiveString(attribute)); 1002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return this; 1012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 1022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 1032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public InternalLocaleBuilder removeUnicodeLocaleAttribute(String attribute) throws LocaleSyntaxException { 1042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (attribute == null || !UnicodeLocaleExtension.isAttribute(attribute)) { 1052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller throw new LocaleSyntaxException("Ill-formed Unicode locale attribute: " + attribute); 1062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 1072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (_uattributes != null) { 1082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _uattributes.remove(new CaseInsensitiveString(attribute)); 1092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 1102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return this; 1112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 1122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 1132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public InternalLocaleBuilder setUnicodeLocaleKeyword(String key, String type) throws LocaleSyntaxException { 1142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (!UnicodeLocaleExtension.isKey(key)) { 1152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller throw new LocaleSyntaxException("Ill-formed Unicode locale keyword key: " + key); 1162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 1172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 1182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller CaseInsensitiveString cikey = new CaseInsensitiveString(key); 1192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (type == null) { 1202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (_ukeywords != null) { 1212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // null type is used for remove the key 1222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _ukeywords.remove(cikey); 1232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 1242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } else { 1252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (type.length() != 0) { 1262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // normalize separator to "-" 1272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller String tp = type.replaceAll(BaseLocale.SEP, LanguageTag.SEP); 1282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // validate 1292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller StringTokenIterator itr = new StringTokenIterator(tp, LanguageTag.SEP); 1302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller while (!itr.isDone()) { 1312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller String s = itr.current(); 1322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (!UnicodeLocaleExtension.isTypeSubtag(s)) { 1332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller throw new LocaleSyntaxException("Ill-formed Unicode locale keyword type: " + type, itr.currentStart()); 1342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 1352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller itr.next(); 1362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 1372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 1382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (_ukeywords == null) { 1392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _ukeywords = new HashMap<CaseInsensitiveString, String>(4); 1402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 1412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _ukeywords.put(cikey, type); 1422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 1432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return this; 1442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 1452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 1462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public InternalLocaleBuilder setExtension(char singleton, String value) throws LocaleSyntaxException { 1472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // validate key 1482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller boolean isBcpPrivateuse = LanguageTag.isPrivateusePrefixChar(singleton); 1492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (!isBcpPrivateuse && !LanguageTag.isExtensionSingletonChar(singleton)) { 1502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller throw new LocaleSyntaxException("Ill-formed extension key: " + singleton); 1512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 1522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 1532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller boolean remove = (value == null || value.length() == 0); 1542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller CaseInsensitiveChar key = new CaseInsensitiveChar(singleton); 1552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 1562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (remove) { 1572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (UnicodeLocaleExtension.isSingletonChar(key.value())) { 1582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // clear entire Unicode locale extension 1592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (_uattributes != null) { 1602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _uattributes.clear(); 1612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 1622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (_ukeywords != null) { 1632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _ukeywords.clear(); 1642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 1652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } else { 1662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (_extensions != null && _extensions.containsKey(key)) { 1672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _extensions.remove(key); 1682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 1692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 1702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } else { 1712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // validate value 1722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller String val = value.replaceAll(BaseLocale.SEP, LanguageTag.SEP); 1732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller StringTokenIterator itr = new StringTokenIterator(val, LanguageTag.SEP); 1742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller while (!itr.isDone()) { 1752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller String s = itr.current(); 1762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller boolean validSubtag; 1772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (isBcpPrivateuse) { 1782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller validSubtag = LanguageTag.isPrivateuseSubtag(s); 1792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } else { 1802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller validSubtag = LanguageTag.isExtensionSubtag(s); 1812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 1822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (!validSubtag) { 1832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller throw new LocaleSyntaxException("Ill-formed extension value: " + s, itr.currentStart()); 1842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 1852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller itr.next(); 1862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 1872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 1882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (UnicodeLocaleExtension.isSingletonChar(key.value())) { 1892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller setUnicodeLocaleExtension(val); 1902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } else { 1912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (_extensions == null) { 1922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _extensions = new HashMap<CaseInsensitiveChar, String>(4); 1932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 1942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _extensions.put(key, val); 1952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 1962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 1972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return this; 1982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 1992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 2002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /* 2012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Set extension/private subtags in a single string representation 2022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 2032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public InternalLocaleBuilder setExtensions(String subtags) throws LocaleSyntaxException { 2042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (subtags == null || subtags.length() == 0) { 2052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller clearExtensions(); 2062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return this; 2072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 2082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller subtags = subtags.replaceAll(BaseLocale.SEP, LanguageTag.SEP); 2092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller StringTokenIterator itr = new StringTokenIterator(subtags, LanguageTag.SEP); 2102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 2112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller List<String> extensions = null; 2122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller String privateuse = null; 2132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 2142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller int parsed = 0; 2152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller int start; 2162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 2172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // Make a list of extension subtags 2182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller while (!itr.isDone()) { 2192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller String s = itr.current(); 2202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (LanguageTag.isExtensionSingleton(s)) { 2212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller start = itr.currentStart(); 2222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller String singleton = s; 2232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller StringBuilder sb = new StringBuilder(singleton); 2242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 2252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller itr.next(); 2262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller while (!itr.isDone()) { 2272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller s = itr.current(); 2282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (LanguageTag.isExtensionSubtag(s)) { 2292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller sb.append(LanguageTag.SEP).append(s); 2302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller parsed = itr.currentEnd(); 2312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } else { 2322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller break; 2332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 2342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller itr.next(); 2352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 2362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 2372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (parsed < start) { 2382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller throw new LocaleSyntaxException("Incomplete extension '" + singleton + "'", start); 2392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 2402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 2412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (extensions == null) { 2422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller extensions = new ArrayList<String>(4); 2432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 2442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller extensions.add(sb.toString()); 2452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } else { 2462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller break; 2472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 2482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 2492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (!itr.isDone()) { 2502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller String s = itr.current(); 2512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (LanguageTag.isPrivateusePrefix(s)) { 2522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller start = itr.currentStart(); 2532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller StringBuilder sb = new StringBuilder(s); 2542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 2552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller itr.next(); 2562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller while (!itr.isDone()) { 2572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller s = itr.current(); 2582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (!LanguageTag.isPrivateuseSubtag(s)) { 2592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller break; 2602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 2612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller sb.append(LanguageTag.SEP).append(s); 2622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller parsed = itr.currentEnd(); 2632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 2642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller itr.next(); 2652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 2662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (parsed <= start) { 2672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller throw new LocaleSyntaxException("Incomplete privateuse:" + subtags.substring(start), start); 2682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } else { 2692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller privateuse = sb.toString(); 2702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 2712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 2722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 2732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 2742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (!itr.isDone()) { 2752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller throw new LocaleSyntaxException("Ill-formed extension subtags:" + subtags.substring(itr.currentStart()), itr.currentStart()); 2762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 2772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 2782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return setExtensions(extensions, privateuse); 2792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 2802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 2812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /* 2822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Set a list of BCP47 extensions and private use subtags 2832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * BCP47 extensions are already validated and well-formed, but may contain duplicates 2842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 2852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller private InternalLocaleBuilder setExtensions(List<String> bcpExtensions, String privateuse) { 2862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller clearExtensions(); 2872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 2882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (bcpExtensions != null && bcpExtensions.size() > 0) { 2892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller HashSet<CaseInsensitiveChar> processedExtensions = new HashSet<CaseInsensitiveChar>(bcpExtensions.size()); 2902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller for (String bcpExt : bcpExtensions) { 2912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller CaseInsensitiveChar key = new CaseInsensitiveChar(bcpExt.charAt(0)); 2922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // ignore duplicates 2932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (!processedExtensions.contains(key)) { 2942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // each extension string contains singleton, e.g. "a-abc-def" 2952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (UnicodeLocaleExtension.isSingletonChar(key.value())) { 2962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller setUnicodeLocaleExtension(bcpExt.substring(2)); 2972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } else { 2982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (_extensions == null) { 2992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _extensions = new HashMap<CaseInsensitiveChar, String>(4); 3002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 3012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _extensions.put(key, bcpExt.substring(2)); 3022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 3032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 3042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 3052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 3062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (privateuse != null && privateuse.length() > 0) { 3072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // privateuse string contains prefix, e.g. "x-abc-def" 3082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (_extensions == null) { 3092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _extensions = new HashMap<CaseInsensitiveChar, String>(1); 3102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 3112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _extensions.put(new CaseInsensitiveChar(privateuse.charAt(0)), privateuse.substring(2)); 3122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 3132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 3142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return this; 3152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 3162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 3172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /* 3182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Reset Builder's internal state with the given language tag 3192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 3202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public InternalLocaleBuilder setLanguageTag(LanguageTag langtag) { 3212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller clear(); 3222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (langtag.getExtlangs().size() > 0) { 3232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _language = langtag.getExtlangs().get(0); 3242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } else { 3252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller String language = langtag.getLanguage(); 3262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (!language.equals(LanguageTag.UNDETERMINED)) { 3272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _language = language; 3282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 3292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 3302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _script = langtag.getScript(); 3312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _region = langtag.getRegion(); 3322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 3332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller List<String> bcpVariants = langtag.getVariants(); 3342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (bcpVariants.size() > 0) { 3352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller StringBuilder var = new StringBuilder(bcpVariants.get(0)); 3362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller for (int i = 1; i < bcpVariants.size(); i++) { 3372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller var.append(BaseLocale.SEP).append(bcpVariants.get(i)); 3382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 3392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _variant = var.toString(); 3402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 3412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 3422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller setExtensions(langtag.getExtensions(), langtag.getPrivateuse()); 3432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 3442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return this; 3452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 3462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 3472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public InternalLocaleBuilder setLocale(BaseLocale base, LocaleExtensions extensions) throws LocaleSyntaxException { 3482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller String language = base.getLanguage(); 3492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller String script = base.getScript(); 3502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller String region = base.getRegion(); 3512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller String variant = base.getVariant(); 3522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 3532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (JDKIMPL) { 3542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // Special backward compatibility support 3552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 3562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // Exception 1 - ja_JP_JP 3572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (language.equals("ja") && region.equals("JP") && variant.equals("JP")) { 3582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // When locale ja_JP_JP is created, ca-japanese is always there. 3592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // The builder ignores the variant "JP" 3602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller assert("japanese".equals(extensions.getUnicodeLocaleType("ca"))); 3612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller variant = ""; 3622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 3632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // Exception 2 - th_TH_TH 3642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller else if (language.equals("th") && region.equals("TH") && variant.equals("TH")) { 3652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // When locale th_TH_TH is created, nu-thai is always there. 3662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // The builder ignores the variant "TH" 3672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller assert("thai".equals(extensions.getUnicodeLocaleType("nu"))); 3682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller variant = ""; 3692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 3702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // Exception 3 - no_NO_NY 3712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller else if (language.equals("no") && region.equals("NO") && variant.equals("NY")) { 3722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // no_NO_NY is a valid locale and used by Java 6 or older versions. 3732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // The build ignores the variant "NY" and change the language to "nn". 3742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller language = "nn"; 3752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller variant = ""; 3762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 3772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 3782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 3792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // Validate base locale fields before updating internal state. 3802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // LocaleExtensions always store validated/canonicalized values, 3812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // so no checks are necessary. 3822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (language.length() > 0 && !LanguageTag.isLanguage(language)) { 3832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller throw new LocaleSyntaxException("Ill-formed language: " + language); 3842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 3852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 3862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (script.length() > 0 && !LanguageTag.isScript(script)) { 3872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller throw new LocaleSyntaxException("Ill-formed script: " + script); 3882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 3892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 3902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (region.length() > 0 && !LanguageTag.isRegion(region)) { 3912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller throw new LocaleSyntaxException("Ill-formed region: " + region); 3922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 3932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 3942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (variant.length() > 0) { 3952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller int errIdx = checkVariants(variant, BaseLocale.SEP); 3962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (errIdx != -1) { 3972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller throw new LocaleSyntaxException("Ill-formed variant: " + variant, errIdx); 3982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 3992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 4002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 4012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // The input locale is validated at this point. 4022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // Now, updating builder's internal fields. 4032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _language = language; 4042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _script = script; 4052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _region = region; 4062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _variant = variant; 4072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller clearExtensions(); 4082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 4092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller Set<Character> extKeys = (extensions == null) ? null : extensions.getKeys(); 4102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (extKeys != null) { 4112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // map extensions back to builder's internal format 4122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller for (Character key : extKeys) { 4132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller Extension e = extensions.getExtension(key); 4142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (e instanceof UnicodeLocaleExtension) { 4152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller UnicodeLocaleExtension ue = (UnicodeLocaleExtension)e; 4162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller for (String uatr : ue.getUnicodeLocaleAttributes()) { 4172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (_uattributes == null) { 4182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _uattributes = new HashSet<CaseInsensitiveString>(4); 4192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 4202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _uattributes.add(new CaseInsensitiveString(uatr)); 4212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 4222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller for (String ukey : ue.getUnicodeLocaleKeys()) { 4232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (_ukeywords == null) { 4242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _ukeywords = new HashMap<CaseInsensitiveString, String>(4); 4252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 4262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _ukeywords.put(new CaseInsensitiveString(ukey), ue.getUnicodeLocaleType(ukey)); 4272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 4282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } else { 4292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (_extensions == null) { 4302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _extensions = new HashMap<CaseInsensitiveChar, String>(4); 4312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 4322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _extensions.put(new CaseInsensitiveChar(key.charValue()), e.getValue()); 4332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 4342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 4352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 4362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return this; 4372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 4382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 4392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public InternalLocaleBuilder clear() { 4402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _language = ""; 4412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _script = ""; 4422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _region = ""; 4432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _variant = ""; 4442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller clearExtensions(); 4452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return this; 4462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 4472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 4482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public InternalLocaleBuilder clearExtensions() { 4492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (_extensions != null) { 4502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _extensions.clear(); 4512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 4522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (_uattributes != null) { 4532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _uattributes.clear(); 4542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 4552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (_ukeywords != null) { 4562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _ukeywords.clear(); 4572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 4582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return this; 4592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 4602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 4612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public BaseLocale getBaseLocale() { 4622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller String language = _language; 4632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller String script = _script; 4642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller String region = _region; 4652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller String variant = _variant; 4662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 4672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // Special private use subtag sequence identified by "lvariant" will be 4682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // interpreted as Java variant. 4692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (_extensions != null) { 4702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller String privuse = _extensions.get(PRIVUSE_KEY); 4712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (privuse != null) { 4722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller StringTokenIterator itr = new StringTokenIterator(privuse, LanguageTag.SEP); 4732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller boolean sawPrefix = false; 4742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller int privVarStart = -1; 4752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller while (!itr.isDone()) { 4762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (sawPrefix) { 4772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller privVarStart = itr.currentStart(); 4782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller break; 4792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 4802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (AsciiUtil.caseIgnoreMatch(itr.current(), LanguageTag.PRIVUSE_VARIANT_PREFIX)) { 4812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller sawPrefix = true; 4822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 4832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller itr.next(); 4842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 4852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (privVarStart != -1) { 4862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller StringBuilder sb = new StringBuilder(variant); 4872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (sb.length() != 0) { 4882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller sb.append(BaseLocale.SEP); 4892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 4902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller sb.append(privuse.substring(privVarStart).replaceAll(LanguageTag.SEP, BaseLocale.SEP)); 4912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller variant = sb.toString(); 4922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 4932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 4942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 4952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 4962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return BaseLocale.getInstance(language, script, region, variant); 4972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 4982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 4992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public LocaleExtensions getLocaleExtensions() { 5002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if ((_extensions == null || _extensions.size() == 0) 5012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller && (_uattributes == null || _uattributes.size() == 0) 5022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller && (_ukeywords == null || _ukeywords.size() == 0)) { 5032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return LocaleExtensions.EMPTY_EXTENSIONS; 5042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 5052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 5062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return new LocaleExtensions(_extensions, _uattributes, _ukeywords); 5072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 5082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 5092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /* 5102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Remove special private use subtag sequence identified by "lvariant" 5112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * and return the rest. Only used by LocaleExtensions 5122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 5132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller static String removePrivateuseVariant(String privuseVal) { 5142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller StringTokenIterator itr = new StringTokenIterator(privuseVal, LanguageTag.SEP); 5152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 5162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // Note: privateuse value "abc-lvariant" is unchanged 5172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // because no subtags after "lvariant". 5182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 5192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller int prefixStart = -1; 5202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller boolean sawPrivuseVar = false; 5212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller while (!itr.isDone()) { 5222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (prefixStart != -1) { 5232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // Note: privateuse value "abc-lvariant" is unchanged 5242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // because no subtags after "lvariant". 5252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller sawPrivuseVar = true; 5262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller break; 5272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 5282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (AsciiUtil.caseIgnoreMatch(itr.current(), LanguageTag.PRIVUSE_VARIANT_PREFIX)) { 5292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller prefixStart = itr.currentStart(); 5302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 5312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller itr.next(); 5322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 5332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (!sawPrivuseVar) { 5342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return privuseVal; 5352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 5362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 5372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller assert(prefixStart == 0 || prefixStart > 1); 5382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return (prefixStart == 0) ? null : privuseVal.substring(0, prefixStart -1); 5392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 5402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 5412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /* 5422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Check if the given variant subtags separated by the given 5432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * separator(s) are valid 5442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 5452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller private int checkVariants(String variants, String sep) { 5462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller StringTokenIterator itr = new StringTokenIterator(variants, sep); 5472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller while (!itr.isDone()) { 5482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller String s = itr.current(); 5492ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (!LanguageTag.isVariant(s)) { 5502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return itr.currentStart(); 5512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 5522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller itr.next(); 5532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 5542ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return -1; 5552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 5562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 5572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller /* 5582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Private methods parsing Unicode Locale Extension subtags. 5592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * Duplicated attributes/keywords will be ignored. 5602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller * The input must be a valid extension subtags (excluding singleton). 5612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller */ 5622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller private void setUnicodeLocaleExtension(String subtags) { 5632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // wipe out existing attributes/keywords 5642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (_uattributes != null) { 5652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _uattributes.clear(); 5662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 5672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (_ukeywords != null) { 5682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _ukeywords.clear(); 5692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 5702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 5712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller StringTokenIterator itr = new StringTokenIterator(subtags, LanguageTag.SEP); 5722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 5732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // parse attributes 5742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller while (!itr.isDone()) { 5752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (!UnicodeLocaleExtension.isAttribute(itr.current())) { 5762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller break; 5772ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 5782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (_uattributes == null) { 5792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _uattributes = new HashSet<CaseInsensitiveString>(4); 5802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 5812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _uattributes.add(new CaseInsensitiveString(itr.current())); 5822ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller itr.next(); 5832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 5842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 5852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // parse keywords 5862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller CaseInsensitiveString key = null; 5872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller String type; 5882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller int typeStart = -1; 5892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller int typeEnd = -1; 5902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller while (!itr.isDone()) { 5912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (key != null) { 5922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (UnicodeLocaleExtension.isKey(itr.current())) { 5932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // next keyword - emit previous one 5942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller assert(typeStart == -1 || typeEnd != -1); 5952ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller type = (typeStart == -1) ? "" : subtags.substring(typeStart, typeEnd); 5962ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (_ukeywords == null) { 5972ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _ukeywords = new HashMap<CaseInsensitiveString, String>(4); 5982ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 5992ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _ukeywords.put(key, type); 6002ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 6012ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // reset keyword info 6022ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller CaseInsensitiveString tmpKey = new CaseInsensitiveString(itr.current()); 6032ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller key = _ukeywords.containsKey(tmpKey) ? null : tmpKey; 6042ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller typeStart = typeEnd = -1; 6052ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } else { 6062ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (typeStart == -1) { 6072ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller typeStart = itr.currentStart(); 6082ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 6092ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller typeEnd = itr.currentEnd(); 6102ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 6112ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } else if (UnicodeLocaleExtension.isKey(itr.current())) { 6122ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // 1. first keyword or 6132ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // 2. next keyword, but previous one was duplicate 6142ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller key = new CaseInsensitiveString(itr.current()); 6152ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (_ukeywords != null && _ukeywords.containsKey(key)) { 6162ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // duplicate 6172ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller key = null; 6182ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 6192ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 6202ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 6212ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (!itr.hasNext()) { 6222ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (key != null) { 6232ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller // last keyword 6242ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller assert(typeStart == -1 || typeEnd != -1); 6252ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller type = (typeStart == -1) ? "" : subtags.substring(typeStart, typeEnd); 6262ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (_ukeywords == null) { 6272ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _ukeywords = new HashMap<CaseInsensitiveString, String>(4); 6282ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 6292ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _ukeywords.put(key, type); 6302ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 6312ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller break; 6322ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 6332ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 6342ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller itr.next(); 6352ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 6362ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 6372ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 6382ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller static class CaseInsensitiveString { 6392ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller private String _s; 6402ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 6412ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller CaseInsensitiveString(String s) { 6422ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _s = s; 6432ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 6442ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 6452ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public String value() { 6462ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return _s; 6472ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 6482ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 649f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert @Override 6502ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public int hashCode() { 6512ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return AsciiUtil.toLowerString(_s).hashCode(); 6522ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 6532ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 654f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert @Override 6552ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public boolean equals(Object obj) { 6562ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (this == obj) { 6572ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return true; 6582ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 6592ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (!(obj instanceof CaseInsensitiveString)) { 6602ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return false; 6612ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 6622ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return AsciiUtil.caseIgnoreMatch(_s, ((CaseInsensitiveString)obj).value()); 6632ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 6642ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 6652ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 6662ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller static class CaseInsensitiveChar { 6672ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller private char _c; 6682ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 6692ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller CaseInsensitiveChar(char c) { 6702ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller _c = c; 6712ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 6722ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 6732ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public char value() { 6742ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return _c; 6752ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 6762ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 677f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert @Override 6782ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public int hashCode() { 6792ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return AsciiUtil.toLower(_c); 6802ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 6812ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 682f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert @Override 6832ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller public boolean equals(Object obj) { 6842ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (this == obj) { 6852ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return true; 6862ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 6872ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller if (!(obj instanceof CaseInsensitiveChar)) { 6882ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return false; 6892ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 6902ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller return _c == AsciiUtil.toLower(((CaseInsensitiveChar)obj).value()); 6912ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 6922ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller 6932ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller } 6942ae130017183d2f66d55bf0ca51f8da3294644fdNeil Fuller} 695