2 *******************************************************************************
\r
3 * Copyright (C) 2009, International Business Machines Corporation and *
\r
4 * others. All Rights Reserved. *
\r
5 *******************************************************************************
\r
7 package com.ibm.icu.impl.locale;
\r
9 import java.util.Collections;
\r
10 import java.util.Set;
\r
11 import java.util.SortedMap;
\r
12 import java.util.TreeMap;
\r
13 import java.util.Map.Entry;
\r
15 import com.ibm.icu.impl.locale.LanguageTag.ParseStatus;
\r
18 public class LocaleExtensions {
\r
20 private SortedMap<Character, Extension> _map = EMPTY_MAP;
\r
21 private String _id = "";
\r
23 private static final SortedMap<Character, Extension> EMPTY_MAP =
\r
24 Collections.unmodifiableSortedMap(new TreeMap<Character, Extension>());
\r
26 private static final LocaleObjectCache<String, LocaleExtensions> LOCALEEXTENSIONS_CACHE =
\r
27 new LocaleObjectCache<String, LocaleExtensions>();
\r
30 public static LocaleExtensions EMPTY_EXTENSIONS = new LocaleExtensions();
\r
32 public static final LocaleExtensions CALENDAR_JAPANESE;
\r
33 public static final LocaleExtensions NUMBER_THAI;
\r
36 CALENDAR_JAPANESE = new LocaleExtensions();
\r
37 CALENDAR_JAPANESE._id = UnicodeLocaleExtension.CA_JAPANESE.getID();
\r
38 CALENDAR_JAPANESE._map = new TreeMap<Character, Extension>();
\r
39 CALENDAR_JAPANESE._map.put(Character.valueOf(UnicodeLocaleExtension.CA_JAPANESE.getKey()), UnicodeLocaleExtension.CA_JAPANESE);
\r
40 LOCALEEXTENSIONS_CACHE.put(CALENDAR_JAPANESE._id, CALENDAR_JAPANESE);
\r
42 NUMBER_THAI = new LocaleExtensions();
\r
43 NUMBER_THAI._id = UnicodeLocaleExtension.NU_THAI.getID();
\r
44 NUMBER_THAI._map = new TreeMap<Character, Extension>();
\r
45 NUMBER_THAI._map.put(Character.valueOf(UnicodeLocaleExtension.NU_THAI.getKey()), UnicodeLocaleExtension.NU_THAI);
\r
46 LOCALEEXTENSIONS_CACHE.put(NUMBER_THAI._id, NUMBER_THAI);
\r
50 private LocaleExtensions() {
\r
53 public static LocaleExtensions getInstance(String str) throws LocaleSyntaxException {
\r
54 if (str == null || str.length() == 0) {
\r
55 return EMPTY_EXTENSIONS;
\r
57 LocaleExtensions exts = LOCALEEXTENSIONS_CACHE.get(str);
\r
59 StringTokenIterator itr = new StringTokenIterator(str, LanguageTag.SEP);
\r
60 ParseStatus sts = new ParseStatus();
\r
61 TreeMap<Character, Extension> map = new TreeMap<Character, Extension>();
\r
63 while (!itr.isDone()) {
\r
64 int startOffset = itr.currentEnd();
\r
65 Extension ext = Extension.create(itr, sts);
\r
66 if (sts.isError()) {
\r
67 throw new LocaleSyntaxException(sts.errorMsg, sts.errorIndex);
\r
70 throw new LocaleSyntaxException("Invalid extension subtag: " + itr.current(), startOffset);
\r
73 Character keyChar = Character.valueOf(ext.getKey());
\r
74 if (map.containsKey(keyChar)) {
\r
75 throw new LocaleSyntaxException("Duplicated extension: " + keyChar, startOffset);
\r
78 map.put(keyChar, ext);
\r
81 String id = toID(map);
\r
82 // check the cache with canonicalized ID
\r
83 exts = LOCALEEXTENSIONS_CACHE.get(id);
\r
85 exts = new LocaleExtensions();
\r
89 exts = LOCALEEXTENSIONS_CACHE.put(id, exts);
\r
95 static LocaleExtensions getInstance(SortedMap<Character, Extension> map) {
\r
96 if (map == null || map.isEmpty()) {
\r
97 return EMPTY_EXTENSIONS;
\r
99 String id = toID(map);
\r
100 LocaleExtensions exts = LOCALEEXTENSIONS_CACHE.get(id);
\r
101 if (exts == null) {
\r
102 exts = new LocaleExtensions();
\r
103 exts._map = new TreeMap<Character, Extension>(map);
\r
106 exts = LOCALEEXTENSIONS_CACHE.put(id, exts);
\r
111 private static String toID(SortedMap<Character, Extension> map) {
\r
112 StringBuilder buf = new StringBuilder();
\r
113 Extension privuse = null;
\r
114 if (map != null && !map.isEmpty()) {
\r
115 Set<Entry<Character, Extension>> entries = map.entrySet();
\r
116 for (Entry<Character, Extension> entry : entries) {
\r
117 Character key = entry.getKey();
\r
118 if (key.charValue() == LanguageTag.PRIVATEUSE.charAt(0)) {
\r
119 privuse = entry.getValue();
\r
122 if (buf.length() > 0) {
\r
123 buf.append(LanguageTag.SEP);
\r
125 buf.append(entry.getKey());
\r
126 buf.append(LanguageTag.SEP);
\r
127 buf.append(entry.getValue().getValue());
\r
130 if (privuse != null) {
\r
131 if (buf.length() > 0) {
\r
132 buf.append(LanguageTag.SEP);
\r
134 buf.append(LanguageTag.PRIVATEUSE);
\r
135 buf.append(LanguageTag.SEP);
\r
136 buf.append(privuse.getValue());
\r
138 return buf.toString();
\r
141 public Set<Character> getKeys() {
\r
142 return Collections.unmodifiableSet(_map.keySet());
\r
145 public Extension getExtension(Character key) {
\r
146 return _map.get(key);
\r
149 public String getExtensionValue(Character key) {
\r
150 Extension ext = _map.get(key);
\r
154 return ext.getValue();
\r
157 public Set<String> getUnicodeLocaleKeys() {
\r
158 Extension ext = _map.get(Character.valueOf(UnicodeLocaleExtension.SINGLETON));
\r
160 return Collections.emptySet();
\r
162 assert (ext instanceof UnicodeLocaleExtension);
\r
163 return ((UnicodeLocaleExtension)ext).getKeys();
\r
166 public String getUnicodeLocaleType(String unicodeLocaleKey) {
\r
167 Extension ext = _map.get(Character.valueOf(UnicodeLocaleExtension.SINGLETON));
\r
171 assert (ext instanceof UnicodeLocaleExtension);
\r
172 return ((UnicodeLocaleExtension)ext).getType(unicodeLocaleKey);
\r
175 public String toString() {
\r
179 public String getID() {
\r
183 public int hashCode() {
\r
184 return _id.hashCode();
\r
187 public static boolean isValidKey(String key) {
\r
188 return LanguageTag.isExtensionSingleton(key) || LanguageTag.isPrivateuseSingleton(key);
\r