314
315 if (!LocaleUtils.isEmpty(bcpExtensions)) {
316 Set<CaseInsensitiveChar> done = new HashSet<>(bcpExtensions.size());
317 for (String bcpExt : bcpExtensions) {
318 CaseInsensitiveChar key = new CaseInsensitiveChar(bcpExt);
319 // ignore duplicates
320 if (!done.contains(key)) {
321 // each extension string contains singleton, e.g. "a-abc-def"
322 if (UnicodeLocaleExtension.isSingletonChar(key.value())) {
323 setUnicodeLocaleExtension(bcpExt.substring(2));
324 } else {
325 if (extensions == null) {
326 extensions = new HashMap<>(4);
327 }
328 extensions.put(key, bcpExt.substring(2));
329 }
330 }
331 done.add(key);
332 }
333 }
334 if (privateuse != null && privateuse.length() > 0) {
335 // privateuse string contains prefix, e.g. "x-abc-def"
336 if (extensions == null) {
337 extensions = new HashMap<>(1);
338 }
339 extensions.put(new CaseInsensitiveChar(privateuse), privateuse.substring(2));
340 }
341
342 return this;
343 }
344
345 /*
346 * Reset Builder's internal state with the given language tag
347 */
348 public InternalLocaleBuilder setLanguageTag(LanguageTag langtag) {
349 clear();
350 if (!langtag.getExtlangs().isEmpty()) {
351 language = langtag.getExtlangs().get(0);
352 } else {
353 String lang = langtag.getLanguage();
354 if (!lang.equals(LanguageTag.UNDETERMINED)) {
389 variant = "";
390 }
391 // Exception 2 - th_TH_TH
392 else if (language.equals("th") && region.equals("TH") && variant.equals("TH")) {
393 // When locale th_TH_TH is created, nu-thai is always there.
394 // The builder ignores the variant "TH"
395 assert("thai".equals(localeExtensions.getUnicodeLocaleType("nu")));
396 variant = "";
397 }
398 // Exception 3 - no_NO_NY
399 else if (language.equals("no") && region.equals("NO") && variant.equals("NY")) {
400 // no_NO_NY is a valid locale and used by Java 6 or older versions.
401 // The build ignores the variant "NY" and change the language to "nn".
402 language = "nn";
403 variant = "";
404 }
405
406 // Validate base locale fields before updating internal state.
407 // LocaleExtensions always store validated/canonicalized values,
408 // so no checks are necessary.
409 if (language.length() > 0 && !LanguageTag.isLanguage(language)) {
410 throw new LocaleSyntaxException("Ill-formed language: " + language);
411 }
412
413 if (script.length() > 0 && !LanguageTag.isScript(script)) {
414 throw new LocaleSyntaxException("Ill-formed script: " + script);
415 }
416
417 if (region.length() > 0 && !LanguageTag.isRegion(region)) {
418 throw new LocaleSyntaxException("Ill-formed region: " + region);
419 }
420
421 if (variant.length() > 0) {
422 int errIdx = checkVariants(variant, BaseLocale.SEP);
423 if (errIdx != -1) {
424 throw new LocaleSyntaxException("Ill-formed variant: " + variant, errIdx);
425 }
426 }
427
428 // The input locale is validated at this point.
429 // Now, updating builder's internal fields.
430 this.language = language;
431 this.script = script;
432 this.region = region;
433 this.variant = variant;
434 clearExtensions();
435
436 Set<Character> extKeys = (localeExtensions == null) ? null : localeExtensions.getKeys();
437 if (extKeys != null) {
438 // map localeExtensions back to builder's internal format
439 for (Character key : extKeys) {
440 Extension e = localeExtensions.getExtension(key);
441 if (e instanceof UnicodeLocaleExtension) {
|
314
315 if (!LocaleUtils.isEmpty(bcpExtensions)) {
316 Set<CaseInsensitiveChar> done = new HashSet<>(bcpExtensions.size());
317 for (String bcpExt : bcpExtensions) {
318 CaseInsensitiveChar key = new CaseInsensitiveChar(bcpExt);
319 // ignore duplicates
320 if (!done.contains(key)) {
321 // each extension string contains singleton, e.g. "a-abc-def"
322 if (UnicodeLocaleExtension.isSingletonChar(key.value())) {
323 setUnicodeLocaleExtension(bcpExt.substring(2));
324 } else {
325 if (extensions == null) {
326 extensions = new HashMap<>(4);
327 }
328 extensions.put(key, bcpExt.substring(2));
329 }
330 }
331 done.add(key);
332 }
333 }
334 if (privateuse != null && !privateuse.isEmpty()) {
335 // privateuse string contains prefix, e.g. "x-abc-def"
336 if (extensions == null) {
337 extensions = new HashMap<>(1);
338 }
339 extensions.put(new CaseInsensitiveChar(privateuse), privateuse.substring(2));
340 }
341
342 return this;
343 }
344
345 /*
346 * Reset Builder's internal state with the given language tag
347 */
348 public InternalLocaleBuilder setLanguageTag(LanguageTag langtag) {
349 clear();
350 if (!langtag.getExtlangs().isEmpty()) {
351 language = langtag.getExtlangs().get(0);
352 } else {
353 String lang = langtag.getLanguage();
354 if (!lang.equals(LanguageTag.UNDETERMINED)) {
389 variant = "";
390 }
391 // Exception 2 - th_TH_TH
392 else if (language.equals("th") && region.equals("TH") && variant.equals("TH")) {
393 // When locale th_TH_TH is created, nu-thai is always there.
394 // The builder ignores the variant "TH"
395 assert("thai".equals(localeExtensions.getUnicodeLocaleType("nu")));
396 variant = "";
397 }
398 // Exception 3 - no_NO_NY
399 else if (language.equals("no") && region.equals("NO") && variant.equals("NY")) {
400 // no_NO_NY is a valid locale and used by Java 6 or older versions.
401 // The build ignores the variant "NY" and change the language to "nn".
402 language = "nn";
403 variant = "";
404 }
405
406 // Validate base locale fields before updating internal state.
407 // LocaleExtensions always store validated/canonicalized values,
408 // so no checks are necessary.
409 if (!language.isEmpty() && !LanguageTag.isLanguage(language)) {
410 throw new LocaleSyntaxException("Ill-formed language: " + language);
411 }
412
413 if (!script.isEmpty() && !LanguageTag.isScript(script)) {
414 throw new LocaleSyntaxException("Ill-formed script: " + script);
415 }
416
417 if (!region.isEmpty() && !LanguageTag.isRegion(region)) {
418 throw new LocaleSyntaxException("Ill-formed region: " + region);
419 }
420
421 if (!variant.isEmpty()) {
422 int errIdx = checkVariants(variant, BaseLocale.SEP);
423 if (errIdx != -1) {
424 throw new LocaleSyntaxException("Ill-formed variant: " + variant, errIdx);
425 }
426 }
427
428 // The input locale is validated at this point.
429 // Now, updating builder's internal fields.
430 this.language = language;
431 this.script = script;
432 this.region = region;
433 this.variant = variant;
434 clearExtensions();
435
436 Set<Character> extKeys = (localeExtensions == null) ? null : localeExtensions.getKeys();
437 if (extKeys != null) {
438 // map localeExtensions back to builder's internal format
439 for (Character key : extKeys) {
440 Extension e = localeExtensions.getExtension(key);
441 if (e instanceof UnicodeLocaleExtension) {
|