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