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
17 public class UnicodeLocaleExtension extends Extension {
\r
18 public static final char SINGLETON = 'u';
\r
20 public static final UnicodeLocaleExtension CA_JAPANESE = new UnicodeLocaleExtension().put("ca", "japanese");
\r
21 public static final UnicodeLocaleExtension NU_THAI = new UnicodeLocaleExtension().put("nu", "thai");
\r
23 private SortedMap<String, String> _keyTypeMap;
\r
25 protected UnicodeLocaleExtension() {
\r
30 * Package local constructor only used by InternalLocaleBuilder
\r
32 UnicodeLocaleExtension(SortedMap<String, String> keyTypeMap) {
\r
34 _keyTypeMap = keyTypeMap;
\r
35 updateStringValue();
\r
38 protected void setExtensionValue(StringTokenIterator itr, ParseStatus sts) {
\r
39 if (sts.isError() || itr.isDone()) {
\r
44 SortedMap<String, String> keyTypeMap = new TreeMap<String, String>();
\r
46 StringBuilder buf = new StringBuilder();
\r
49 while (!itr.isDone()) {
\r
50 String s = itr.current();
\r
52 if (isTypeSubtag(s)) {
\r
55 sts.errorIndex = itr.currentStart();
\r
56 sts.errorMsg = "Invalid Unicode locale extension key: " + s;
\r
59 if (buf.length() > 0) {
\r
60 buf.append(LanguageTag.SEP);
\r
62 buf.append(canonicalizeTypeSubtag(s));
\r
63 typeEnd = itr.currentEnd();
\r
65 if (!itr.hasNext()) {
\r
66 // emit the last key/type
\r
67 keyTypeMap.put(ukey, buf.toString());
\r
68 sts.parseLength = typeEnd;
\r
75 if (buf.length() > 0) {
\r
76 // emit previous key and value
\r
77 keyTypeMap.put(ukey, buf.toString());
\r
78 sts.parseLength = typeEnd;
\r
81 sts.errorIndex = itr.currentStart();
\r
82 sts.errorMsg = "Invalid Unicode locale extension type: " + s;
\r
87 if (itr.hasNext()) {
\r
88 ukey = canonicalizeKey(s);
\r
89 if (keyTypeMap.containsKey(ukey)) {
\r
91 sts.errorIndex = itr.currentStart();
\r
92 sts.errorMsg = "Duplicate Unicode locale extension key: " + s;
\r
99 sts.errorIndex = itr.currentStart();
\r
100 sts.errorMsg = "Missing subtag for Unicode locale extension: " + s;
\r
106 if (keyTypeMap.size() == 0) {
\r
108 sts.errorIndex = itr.currentStart();
\r
109 sts.errorMsg = "Invalid Unicode locale extension key: " + s;
\r
117 if (keyTypeMap.size() == 0) {
\r
122 _keyTypeMap = keyTypeMap;
\r
123 updateStringValue();
\r
126 public Set<String> getKeys() {
\r
127 if (_keyTypeMap == null) {
\r
128 return Collections.emptySet();
\r
130 return Collections.unmodifiableSet(_keyTypeMap.keySet());
\r
133 public String getType(String key) {
\r
134 String type = null;
\r
135 if (_keyTypeMap != null) {
\r
136 type = _keyTypeMap.get(canonicalizeKey(key));
\r
139 return (type == null ? "" : type);
\r
142 public static boolean isKey(String s) {
\r
144 return (s.length() == 2) && AsciiUtil.isAlphaNumericString(s);
\r
147 public static boolean isTypeSubtag(String s) {
\r
149 return (s.length() >= 3) && (s.length() <= 8) && AsciiUtil.isAlphaNumericString(s);
\r
152 public static String canonicalizeKey(String s) {
\r
153 return LanguageTag.canonicalizeExtensionSubtag(s);
\r
156 public static String canonicalizeTypeSubtag(String s) {
\r
157 return LanguageTag.canonicalizeExtensionSubtag(s);
\r
160 // These methods are only used by InterlaLocaleBuilder
\r
161 UnicodeLocaleExtension remove(String key) {
\r
162 if (_keyTypeMap != null) {
\r
163 _keyTypeMap.remove(key);
\r
164 updateStringValue();
\r
169 UnicodeLocaleExtension put(String key, String type) {
\r
170 if (_keyTypeMap == null) {
\r
171 _keyTypeMap = new TreeMap<String, String>();
\r
173 _keyTypeMap.put(key, type);
\r
174 updateStringValue();
\r
178 boolean isEmpty() {
\r
179 return (_keyTypeMap.size() == 0);
\r
182 private void updateStringValue() {
\r
185 if (_keyTypeMap != null) {
\r
186 // re-construct string representation
\r
187 StringBuilder valBuf = new StringBuilder();
\r
188 Set<Entry<String, String>> entries = _keyTypeMap.entrySet();
\r
189 boolean isFirst = true;
\r
190 for (Entry<String, String> e : entries) {
\r
194 valBuf.append(LanguageTag.SEP);
\r
196 valBuf.append(e.getKey());
\r
197 valBuf.append(LanguageTag.SEP);
\r
198 valBuf.append(e.getValue());
\r
201 if (valBuf.length() > 0) {
\r
202 _value = valBuf.toString();
\r