1 // 2016 and later: Unicode, Inc. and others. 2 // License & terms of use: http://www.unicode.org/copyright.html#License 3 /* 4 ******************************************************************************* 5 * Copyright (C) 2009-2014, 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.Entry; 13 import java.util.Set; 14 import java.util.SortedMap; 15 import java.util.SortedSet; 16 import java.util.TreeMap; 17 import java.util.TreeSet; 18 19 public class UnicodeLocaleExtension extends Extension { 20 public static final char SINGLETON = 'u'; 21 22 private static final SortedSet<String> EMPTY_SORTED_SET = new TreeSet<String>(); 23 private static final SortedMap<String, String> EMPTY_SORTED_MAP = new TreeMap<String, String>(); 24 25 private SortedSet<String> _attributes = EMPTY_SORTED_SET; 26 private SortedMap<String, String> _keywords = EMPTY_SORTED_MAP; 27 28 public static final UnicodeLocaleExtension CA_JAPANESE; 29 public static final UnicodeLocaleExtension NU_THAI; 30 31 static { 32 CA_JAPANESE = new UnicodeLocaleExtension(); 33 CA_JAPANESE._keywords = new TreeMap<String, String>(); 34 CA_JAPANESE._keywords.put("ca", "japanese"); 35 CA_JAPANESE._value = "ca-japanese"; 36 37 NU_THAI = new UnicodeLocaleExtension(); 38 NU_THAI._keywords = new TreeMap<String, String>(); 39 NU_THAI._keywords.put("nu", "thai"); 40 NU_THAI._value = "nu-thai"; 41 } 42 43 private UnicodeLocaleExtension() { 44 super(SINGLETON); 45 } 46 47 UnicodeLocaleExtension(SortedSet<String> attributes, SortedMap<String, String> keywords) { 48 this(); 49 if (attributes != null && attributes.size() > 0) { 50 _attributes = attributes; 51 } 52 if (keywords != null && keywords.size() > 0) { 53 _keywords = keywords; 54 } 55 56 if (_attributes.size() > 0 || _keywords.size() > 0) { 57 StringBuilder sb = new StringBuilder(); 58 for (String attribute : _attributes) { 59 sb.append(LanguageTag.SEP).append(attribute); 60 } 61 for (Entry<String, String> keyword : _keywords.entrySet()) { 62 String key = keyword.getKey(); 63 String value = keyword.getValue(); 64 65 sb.append(LanguageTag.SEP).append(key); 66 if (value.length() > 0) { 67 sb.append(LanguageTag.SEP).append(value); 68 } 69 } 70 _value = sb.substring(1); // skip leading '-' 71 } 72 } 73 74 public Set<String> getUnicodeLocaleAttributes() { 75 return Collections.unmodifiableSet(_attributes); 76 } 77 78 public Set<String> getUnicodeLocaleKeys() { 79 return Collections.unmodifiableSet(_keywords.keySet()); 80 } 81 82 public String getUnicodeLocaleType(String unicodeLocaleKey) { 83 return _keywords.get(unicodeLocaleKey); 84 } 85 86 public static boolean isSingletonChar(char c) { 87 return (SINGLETON == AsciiUtil.toLower(c)); 88 } 89 90 public static boolean isAttribute(String s) { 91 // 3*8alphanum 92 return (s.length() >= 3) && (s.length() <= 8) && AsciiUtil.isAlphaNumericString(s); 93 } 94 95 public static boolean isKey(String s) { 96 // 2alphanum 97 return (s.length() == 2) && AsciiUtil.isAlphaNumericString(s); 98 } 99 100 public static boolean isTypeSubtag(String s) { 101 // 3*8alphanum 102 return (s.length() >= 3) && (s.length() <= 8) && AsciiUtil.isAlphaNumericString(s); 103 } 104 105 public static boolean isType(String s) { 106 // sequence of type subtags delimited by '-' 107 int startIdx = 0; 108 boolean sawSubtag = false; 109 while (true) { 110 int idx = s.indexOf(LanguageTag.SEP, startIdx); 111 String subtag = idx < 0 ? s.substring(startIdx) : s.substring(startIdx, idx); 112 if (!isTypeSubtag(subtag)) { 113 return false; 114 } 115 sawSubtag = true; 116 if (idx < 0) { 117 break; 118 } 119 startIdx = idx + 1; 120 } 121 return sawSubtag && startIdx < s.length(); 122 } 123 } 124