2
*******************************************************************************
3
* Copyright (C) 2009, International Business Machines Corporation and *
4
* others. All Rights Reserved. *
5
*******************************************************************************
7
package com.ibm.icu.impl.locale;
11
import java.util.SortedMap;
12
import java.util.TreeMap;
14
import com.ibm.icu.impl.locale.LanguageTag.ParseStatus;
16
public final class InternalLocaleBuilder {
18
private String _language = "";
19
private String _script = "";
20
private String _region = "";
21
private String _variant = "";
22
private SortedMap<Character, Extension> _extMap;
24
private final boolean _lenientVariant;
26
private static final String LOCALESEP = "_";
28
public InternalLocaleBuilder() {
32
public InternalLocaleBuilder(boolean lenientVariant) {
33
_lenientVariant = lenientVariant;
36
public boolean isLenientVariant() {
37
return _lenientVariant;
40
public InternalLocaleBuilder setLanguage(String language) throws LocaleSyntaxException {
42
if (language.length() > 0) {
43
if (!LanguageTag.isLanguage(language)) {
44
throw new LocaleSyntaxException("Ill-formed language: " + language, 0);
46
newval = LanguageTag.canonicalizeLanguage(language);
52
public InternalLocaleBuilder setScript(String script) throws LocaleSyntaxException {
54
if (script.length() > 0) {
55
if (!LanguageTag.isScript(script)) {
56
throw new LocaleSyntaxException("Ill-formed script: " + script, 0);
58
newval = LanguageTag.canonicalizeScript(script);
64
public InternalLocaleBuilder setRegion(String region) throws LocaleSyntaxException {
66
if (region.length() > 0) {
67
if (!LanguageTag.isRegion(region)) {
68
throw new LocaleSyntaxException("Ill-formed region: " + region);
70
newval = LanguageTag.canonicalizeRegion(region);
76
public InternalLocaleBuilder setVariant(String variant) throws LocaleSyntaxException {
78
if (variant.length() > 0) {
79
if (_lenientVariant) {
82
newval = processVariant(variant);
89
public InternalLocaleBuilder setUnicodeLocaleExtension(String key, String type) throws LocaleSyntaxException {
90
if (key.length() == 0) {
91
throw new LocaleSyntaxException("Empty Unicode locale extension key");
93
if (!UnicodeLocaleExtension.isKey(key)) {
94
throw new LocaleSyntaxException("Ill-formed Unicode locale extension key: " + key, 0);
97
key = UnicodeLocaleExtension.canonicalizeKey(key);
99
UnicodeLocaleExtension ulext = null;
100
if (_extMap != null) {
101
ulext = (UnicodeLocaleExtension)_extMap.get(Character.valueOf(UnicodeLocaleExtension.SINGLETON));
104
if (type.length() == 0) {
107
if (ulext.isEmpty()) {
108
_extMap.remove(Character.valueOf(UnicodeLocaleExtension.SINGLETON));
112
StringBuilder buf = new StringBuilder();
113
StringTokenIterator sti = new StringTokenIterator(type, LanguageTag.SEP);
114
for (String subtag = sti.first(); !sti.isDone(); subtag = sti.next()) {
115
if (!UnicodeLocaleExtension.isTypeSubtag(subtag)) {
116
throw new LocaleSyntaxException("Ill-formed Unicode locale extension type: " + type, sti.currentStart());
118
if (buf.length() > 0) {
119
buf.append(LanguageTag.SEP);
121
buf.append(UnicodeLocaleExtension.canonicalizeTypeSubtag(subtag));
124
SortedMap<String, String> ktmap = new TreeMap<String, String>();
125
ktmap.put(key, buf.toString());
126
ulext = new UnicodeLocaleExtension(ktmap);
127
if (_extMap == null) {
128
_extMap = new TreeMap<Character, Extension>();
130
_extMap.put(Character.valueOf(UnicodeLocaleExtension.SINGLETON), ulext);
132
ulext.put(key, buf.toString());
139
public InternalLocaleBuilder setExtension(char singleton, String value) throws LocaleSyntaxException {
140
String strSingleton = String.valueOf(singleton);
141
if (!LanguageTag.isExtensionSingleton(strSingleton) && !LanguageTag.isPrivateuseSingleton(strSingleton)) {
142
throw new LocaleSyntaxException("Ill-formed extension key: " + singleton);
145
strSingleton = LanguageTag.canonicalizeExtensionSingleton(strSingleton);
146
Character key = Character.valueOf(strSingleton.charAt(0));
148
if (value.length() == 0) {
149
if (_extMap != null) {
153
StringTokenIterator sti = new StringTokenIterator(value, LanguageTag.SEP);
154
ParseStatus sts = new ParseStatus();
156
Extension ext = Extension.create(key.charValue(), sti, sts);
158
throw new LocaleSyntaxException(sts.errorMsg, sts.errorIndex);
160
if (sts.parseLength != value.length() || ext == null) {
161
throw new LocaleSyntaxException("Ill-formed extension value: " + value, sti.currentStart());
163
if (_extMap == null) {
164
_extMap = new TreeMap<Character, Extension>();
166
_extMap.put(key, ext);
171
public InternalLocaleBuilder setLocale(BaseLocale base, LocaleExtensions extensions) throws LocaleSyntaxException {
172
String language = base.getLanguage();
173
String script = base.getScript();
174
String region = base.getRegion();
175
String variant = base.getVariant();
177
// Validate base locale fields before updating internal state.
178
// LocaleExtensions always store validated/canonicalized values,
179
// so no checks are necessary.
180
if (language.length() > 0) {
181
if (!LanguageTag.isLanguage(language)) {
182
throw new LocaleSyntaxException("Ill-formed language: " + language);
184
language = LanguageTag.canonicalizeLanguage(language);
186
if (script.length() > 0) {
187
if (!LanguageTag.isScript(script)) {
188
throw new LocaleSyntaxException("Ill-formed script: " + script);
190
script = LanguageTag.canonicalizeScript(script);
192
if (region.length() > 0) {
193
if (!LanguageTag.isRegion(region)) {
194
throw new LocaleSyntaxException("Ill-formed region: " + region);
196
region = LanguageTag.canonicalizeRegion(region);
198
if (_lenientVariant) {
199
// In lenient variant mode, parse special private use value
200
// reserved for Java Locale.
201
String privuse = extensions.getExtensionValue(Character.valueOf(LanguageTag.PRIVATEUSE.charAt(0)));
202
if (privuse != null) {
203
variant = LanguageTag.getJavaCompatibleVariant(variant, privuse);
206
if (variant.length() > 0) {
207
variant = processVariant(variant);
211
// update builder's internal fields
212
_language = language;
218
if (_extMap == null) {
219
_extMap = new TreeMap<Character, Extension>();
224
Set<Character> extKeys = extensions.getKeys();
225
for (Character key : extKeys) {
226
Extension ext = extensions.getExtension(key);
227
if (_lenientVariant && (ext instanceof PrivateuseExtension)) {
228
String modPrivuse = LanguageTag.getJavaCompatiblePrivateuse(ext.getValue());
229
if (!modPrivuse.equals(ext.getValue())) {
230
ext = new PrivateuseExtension(modPrivuse);
233
_extMap.put(key, ext);
239
public InternalLocaleBuilder clear() {
244
removeLocaleExtensions();
248
public InternalLocaleBuilder removeLocaleExtensions() {
249
if (_extMap != null) {
255
public BaseLocale getBaseLocale() {
256
return BaseLocale.getInstance(_language, _script, _region, _variant);
259
public LocaleExtensions getLocaleExtensions() {
260
if (_extMap != null && _extMap.size() > 0) {
261
return LocaleExtensions.getInstance(_extMap);
263
return LocaleExtensions.EMPTY_EXTENSIONS;
266
private String processVariant(String variant) throws LocaleSyntaxException {
267
StringTokenIterator sti = new StringTokenIterator(variant, LOCALESEP);
268
ParseStatus sts = new ParseStatus();
270
List<String> variants = LanguageTag.DEFAULT_PARSER.parseVariants(sti, sts);
271
if (sts.parseLength != variant.length()) {
272
throw new LocaleSyntaxException("Ill-formed variant: " + variant, sti.currentStart());
275
StringBuilder buf = new StringBuilder();
276
for (String var : variants) {
277
if (buf.length() != 0) {
278
buf.append(LOCALESEP);
282
return buf.toString();