2 *******************************************************************************
3 * Copyright (C) 2009-2010, International Business Machines Corporation and *
4 * others. All Rights Reserved. *
5 *******************************************************************************
7 package com.ibm.icu.impl.locale;
9 import java.util.Collections;
11 import java.util.Map.Entry;
13 import java.util.SortedMap;
14 import java.util.TreeMap;
15 import java.util.TreeSet;
17 import com.ibm.icu.impl.locale.InternalLocaleBuilder.CaseInsensitiveChar;
18 import com.ibm.icu.impl.locale.InternalLocaleBuilder.CaseInsensitiveString;
21 public class LocaleExtensions {
23 private SortedMap<Character, Extension> _map;
26 private static final SortedMap<Character, Extension> EMPTY_MAP =
27 Collections.unmodifiableSortedMap(new TreeMap<Character, Extension>());
29 public static final LocaleExtensions EMPTY_EXTENSIONS;
30 public static final LocaleExtensions CALENDAR_JAPANESE;
31 public static final LocaleExtensions NUMBER_THAI;
34 EMPTY_EXTENSIONS = new LocaleExtensions();
35 EMPTY_EXTENSIONS._id = "";
36 EMPTY_EXTENSIONS._map = EMPTY_MAP;
38 CALENDAR_JAPANESE = new LocaleExtensions();
39 CALENDAR_JAPANESE._id = "u-ca-japanese";
40 CALENDAR_JAPANESE._map = new TreeMap<Character, Extension>();
41 CALENDAR_JAPANESE._map.put(Character.valueOf(UnicodeLocaleExtension.SINGLETON), UnicodeLocaleExtension.CA_JAPANESE);
43 NUMBER_THAI = new LocaleExtensions();
44 NUMBER_THAI._id = "u-nu-thai";
45 NUMBER_THAI._map = new TreeMap<Character, Extension>();
46 NUMBER_THAI._map.put(Character.valueOf(UnicodeLocaleExtension.SINGLETON), UnicodeLocaleExtension.NU_THAI);
49 private LocaleExtensions() {
53 * Package local constructor, only used by InternalLocaleBuilder.
55 LocaleExtensions(Map<CaseInsensitiveChar, String> extensions,
56 Set<CaseInsensitiveString> uattributes, Map<CaseInsensitiveString, String> ukeywords) {
57 boolean hasExtension = (extensions != null && extensions.size() > 0);
58 boolean hasUAttributes = (uattributes != null && uattributes.size() > 0);
59 boolean hasUKeywords = (ukeywords != null && ukeywords.size() > 0);
61 if (!hasExtension && !hasUAttributes && !hasUKeywords) {
67 // Build extension map
68 _map = new TreeMap<Character, Extension>();
70 for (Entry<CaseInsensitiveChar, String> ext : extensions.entrySet()) {
71 char key = AsciiUtil.toLower(ext.getKey().value());
72 String value = ext.getValue();
74 if (LanguageTag.isPrivateusePrefixChar(key)) {
75 // we need to exclude special variant in privuateuse, e.g. "x-abc-lvariant-DEF"
76 value = InternalLocaleBuilder.removePrivateuseVariant(value);
82 Extension e = new Extension(key, AsciiUtil.toLowerString(value));
83 _map.put(Character.valueOf(key), e);
87 if (hasUAttributes || hasUKeywords) {
88 TreeSet<String> uaset = null;
89 TreeMap<String, String> ukmap = null;
92 uaset = new TreeSet<String>();
93 for (CaseInsensitiveString cis : uattributes) {
94 uaset.add(AsciiUtil.toLowerString(cis.value()));
99 ukmap = new TreeMap<String, String>();
100 for (Entry<CaseInsensitiveString, String> kwd : ukeywords.entrySet()) {
101 String key = AsciiUtil.toLowerString(kwd.getKey().value());
102 String type = AsciiUtil.toLowerString(kwd.getValue());
103 ukmap.put(key, type);
107 UnicodeLocaleExtension ule = new UnicodeLocaleExtension(uaset, ukmap);
108 _map.put(Character.valueOf(UnicodeLocaleExtension.SINGLETON), ule);
111 if (_map.size() == 0) {
112 // this could happen when only privuateuse with special variant
120 public Set<Character> getKeys() {
121 return Collections.unmodifiableSet(_map.keySet());
124 public Extension getExtension(Character key) {
125 return _map.get(Character.valueOf(AsciiUtil.toLower(key.charValue())));
128 public String getExtensionValue(Character key) {
129 Extension ext = _map.get(Character.valueOf(AsciiUtil.toLower(key.charValue())));
133 return ext.getValue();
136 public Set<String> getUnicodeLocaleAttributes() {
137 Extension ext = _map.get(Character.valueOf(UnicodeLocaleExtension.SINGLETON));
139 return Collections.emptySet();
141 assert (ext instanceof UnicodeLocaleExtension);
142 return ((UnicodeLocaleExtension)ext).getUnicodeLocaleAttributes();
145 public Set<String> getUnicodeLocaleKeys() {
146 Extension ext = _map.get(Character.valueOf(UnicodeLocaleExtension.SINGLETON));
148 return Collections.emptySet();
150 assert (ext instanceof UnicodeLocaleExtension);
151 return ((UnicodeLocaleExtension)ext).getUnicodeLocaleKeys();
154 public String getUnicodeLocaleType(String unicodeLocaleKey) {
155 Extension ext = _map.get(Character.valueOf(UnicodeLocaleExtension.SINGLETON));
159 assert (ext instanceof UnicodeLocaleExtension);
160 return ((UnicodeLocaleExtension)ext).getUnicodeLocaleType(AsciiUtil.toLowerString(unicodeLocaleKey));
163 public boolean isEmpty() {
164 return _map.isEmpty();
167 public static boolean isValidKey(char c) {
168 return LanguageTag.isExtensionSingletonChar(c) || LanguageTag.isPrivateusePrefixChar(c);
171 public static boolean isValidUnicodeLocaleKey(String ukey) {
172 return UnicodeLocaleExtension.isKey(ukey);
175 private static String toID(SortedMap<Character, Extension> map) {
176 StringBuilder buf = new StringBuilder();
177 Extension privuse = null;
178 for (Entry<Character, Extension> entry : map.entrySet()) {
179 char singleton = entry.getKey().charValue();
180 Extension extension = entry.getValue();
181 if (LanguageTag.isPrivateusePrefixChar(singleton)) {
184 if (buf.length() > 0) {
185 buf.append(LanguageTag.SEP);
187 buf.append(extension);
190 if (privuse != null) {
191 if (buf.length() > 0) {
192 buf.append(LanguageTag.SEP);
196 return buf.toString();
200 public String toString() {
204 public String getID() {
208 public int hashCode() {
209 return _id.hashCode();
212 public boolean equals(Object other) {
216 if (!(other instanceof LocaleExtensions)) {
219 return this._id.equals(((LocaleExtensions)other)._id);