• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /*
4  *******************************************************************************
5  * Copyright (C) 2009-2010, International Business Machines Corporation and    *
6  * others. All Rights Reserved.                                                *
7  *******************************************************************************
8  */
9 package com.ibm.icu.impl.locale;
10 
11 import java.util.Collections;
12 import java.util.Map;
13 import java.util.Map.Entry;
14 import java.util.Set;
15 import java.util.SortedMap;
16 import java.util.TreeMap;
17 import java.util.TreeSet;
18 
19 import com.ibm.icu.impl.locale.InternalLocaleBuilder.CaseInsensitiveChar;
20 import com.ibm.icu.impl.locale.InternalLocaleBuilder.CaseInsensitiveString;
21 
22 
23 public class LocaleExtensions {
24 
25     private SortedMap<Character, Extension> _map;
26     private String _id;
27 
28     private static final SortedMap<Character, Extension> EMPTY_MAP =
29         Collections.unmodifiableSortedMap(new TreeMap<Character, Extension>());
30 
31     public static final LocaleExtensions EMPTY_EXTENSIONS;
32     public static final LocaleExtensions CALENDAR_JAPANESE;
33     public static final LocaleExtensions NUMBER_THAI;
34 
35     static {
36         EMPTY_EXTENSIONS = new LocaleExtensions();
37         EMPTY_EXTENSIONS._id = "";
38         EMPTY_EXTENSIONS._map = EMPTY_MAP;
39 
40         CALENDAR_JAPANESE = new LocaleExtensions();
41         CALENDAR_JAPANESE._id = "u-ca-japanese";
42         CALENDAR_JAPANESE._map = new TreeMap<Character, Extension>();
CALENDAR_JAPANESE._map.put(UnicodeLocaleExtension.SINGLETON, UnicodeLocaleExtension.CA_JAPANESE)43         CALENDAR_JAPANESE._map.put(UnicodeLocaleExtension.SINGLETON, UnicodeLocaleExtension.CA_JAPANESE);
44 
45         NUMBER_THAI = new LocaleExtensions();
46         NUMBER_THAI._id = "u-nu-thai";
47         NUMBER_THAI._map = new TreeMap<Character, Extension>();
NUMBER_THAI._map.put(UnicodeLocaleExtension.SINGLETON, UnicodeLocaleExtension.NU_THAI)48         NUMBER_THAI._map.put(UnicodeLocaleExtension.SINGLETON, UnicodeLocaleExtension.NU_THAI);
49     }
50 
LocaleExtensions()51     private LocaleExtensions() {
52     }
53 
54     /*
55      * Package local constructor, only used by InternalLocaleBuilder.
56      */
LocaleExtensions(Map<CaseInsensitiveChar, String> extensions, Set<CaseInsensitiveString> uattributes, Map<CaseInsensitiveString, String> ukeywords)57     LocaleExtensions(Map<CaseInsensitiveChar, String> extensions,
58             Set<CaseInsensitiveString> uattributes, Map<CaseInsensitiveString, String> ukeywords) {
59         boolean hasExtension = (extensions != null && extensions.size() > 0);
60         boolean hasUAttributes = (uattributes != null && uattributes.size() > 0);
61         boolean hasUKeywords = (ukeywords != null && ukeywords.size() > 0);
62 
63         if (!hasExtension && !hasUAttributes && !hasUKeywords) {
64             _map = EMPTY_MAP;
65             _id = "";
66             return;
67         }
68 
69         // Build extension map
70         _map = new TreeMap<>();
71         if (hasExtension) {
72             for (Entry<CaseInsensitiveChar, String> ext : extensions.entrySet()) {
73                 char key = AsciiUtil.toLower(ext.getKey().value());
74                 String value = ext.getValue();
75 
76                 if (LanguageTag.isPrivateusePrefixChar(key)) {
77                     // we need to exclude special variant in privuateuse, e.g. "x-abc-lvariant-DEF"
78                     value = InternalLocaleBuilder.removePrivateuseVariant(value);
79                     if (value == null) {
80                         continue;
81                     }
82                 }
83 
84                 Extension e = new Extension(key, AsciiUtil.toLowerString(value));
85                 _map.put(key, e);
86             }
87         }
88 
89         if (hasUAttributes || hasUKeywords) {
90             TreeSet<String> uaset = null;
91             TreeMap<String, String> ukmap = null;
92 
93             if (hasUAttributes) {
94                 uaset = new TreeSet<String>();
95                 for (CaseInsensitiveString cis : uattributes) {
96                     uaset.add(AsciiUtil.toLowerString(cis.value()));
97                 }
98             }
99 
100             if (hasUKeywords) {
101                 ukmap = new TreeMap<String, String>();
102                 for (Entry<CaseInsensitiveString, String> kwd : ukeywords.entrySet()) {
103                     String key = AsciiUtil.toLowerString(kwd.getKey().value());
104                     String type = AsciiUtil.toLowerString(kwd.getValue());
105                     ukmap.put(key, type);
106                 }
107             }
108 
109             UnicodeLocaleExtension ule = new UnicodeLocaleExtension(uaset, ukmap);
110             _map.put(UnicodeLocaleExtension.SINGLETON, ule);
111         }
112 
113         if (_map.size() == 0) {
114             // this could happen when only privuateuse with special variant
115             _map = EMPTY_MAP;
116             _id = "";
117         } else {
118             _id = toID(_map);
119         }
120     }
121 
getKeys()122     public Set<Character> getKeys() {
123         return Collections.unmodifiableSet(_map.keySet());
124     }
125 
getExtension(Character key)126     public Extension getExtension(Character key) {
127         return _map.get(AsciiUtil.toLower(key.charValue()));
128     }
129 
getExtensionValue(Character key)130     public String getExtensionValue(Character key) {
131         Extension ext = _map.get(AsciiUtil.toLower(key.charValue()));
132         if (ext == null) {
133             return null;
134         }
135         return ext.getValue();
136     }
137 
getUnicodeLocaleAttributes()138     public Set<String> getUnicodeLocaleAttributes() {
139         Extension ext = _map.get(UnicodeLocaleExtension.SINGLETON);
140         if (ext == null) {
141             return Collections.emptySet();
142         }
143         assert (ext instanceof UnicodeLocaleExtension);
144         return ((UnicodeLocaleExtension)ext).getUnicodeLocaleAttributes();
145     }
146 
getUnicodeLocaleKeys()147     public Set<String> getUnicodeLocaleKeys() {
148         Extension ext = _map.get(UnicodeLocaleExtension.SINGLETON);
149         if (ext == null) {
150             return Collections.emptySet();
151         }
152         assert (ext instanceof UnicodeLocaleExtension);
153         return ((UnicodeLocaleExtension)ext).getUnicodeLocaleKeys();
154     }
155 
getUnicodeLocaleType(String unicodeLocaleKey)156     public String getUnicodeLocaleType(String unicodeLocaleKey) {
157         Extension ext = _map.get(UnicodeLocaleExtension.SINGLETON);
158         if (ext == null) {
159             return null;
160         }
161         assert (ext instanceof UnicodeLocaleExtension);
162         return ((UnicodeLocaleExtension)ext).getUnicodeLocaleType(AsciiUtil.toLowerString(unicodeLocaleKey));
163     }
164 
isEmpty()165     public boolean isEmpty() {
166         return _map.isEmpty();
167     }
168 
isValidKey(char c)169     public static boolean isValidKey(char c) {
170         return LanguageTag.isExtensionSingletonChar(c) || LanguageTag.isPrivateusePrefixChar(c);
171     }
172 
isValidUnicodeLocaleKey(String ukey)173     public static boolean isValidUnicodeLocaleKey(String ukey) {
174         return UnicodeLocaleExtension.isKey(ukey);
175     }
176 
toID(SortedMap<Character, Extension> map)177     private static String toID(SortedMap<Character, Extension> map) {
178         StringBuilder buf = new StringBuilder();
179         Extension privuse = null;
180         for (Entry<Character, Extension> entry : map.entrySet()) {
181             char singleton = entry.getKey().charValue();
182             Extension extension = entry.getValue();
183             if (LanguageTag.isPrivateusePrefixChar(singleton)) {
184                 privuse = extension;
185             } else {
186                 if (buf.length() > 0) {
187                     buf.append(LanguageTag.SEP);
188                 }
189                 buf.append(extension);
190             }
191         }
192         if (privuse != null) {
193             if (buf.length() > 0) {
194                 buf.append(LanguageTag.SEP);
195             }
196             buf.append(privuse);
197         }
198         return buf.toString();
199     }
200 
201 
202     @Override
toString()203     public String toString() {
204         return _id;
205     }
206 
getID()207     public String getID() {
208         return _id;
209     }
210 
211     @Override
hashCode()212     public int hashCode() {
213         return _id.hashCode();
214     }
215 
216     @Override
equals(Object other)217     public boolean equals(Object other) {
218         if (this == other) {
219             return true;
220         }
221         if (!(other instanceof LocaleExtensions)) {
222             return false;
223         }
224         return this._id.equals(((LocaleExtensions)other)._id);
225     }
226 }
227