1 /* GENERATED SOURCE. DO NOT MODIFY. */ 2 // © 2016 and later: Unicode, Inc. and others. 3 // License & terms of use: http://www.unicode.org/copyright.html#License 4 /* 5 ******************************************************************************* 6 * Copyright (C) 2014-2016, International Business Machines Corporation and 7 * others. All Rights Reserved. 8 ******************************************************************************* 9 */ 10 package ohos.global.icu.impl.locale; 11 12 import java.util.Collections; 13 import java.util.EnumSet; 14 import java.util.HashMap; 15 import java.util.HashSet; 16 import java.util.LinkedHashMap; 17 import java.util.LinkedHashSet; 18 import java.util.Map; 19 import java.util.MissingResourceException; 20 import java.util.Set; 21 import java.util.regex.Pattern; 22 23 import ohos.global.icu.impl.ICUData; 24 import ohos.global.icu.impl.ICUResourceBundle; 25 import ohos.global.icu.util.Output; 26 import ohos.global.icu.util.UResourceBundle; 27 import ohos.global.icu.util.UResourceBundleIterator; 28 29 /** 30 * @hide exposed on OHOS 31 */ 32 public class KeyTypeData { 33 34 /** 35 * @hide exposed on OHOS 36 */ 37 public enum ValueType { 38 single, multiple, incremental, any 39 } 40 41 private static abstract class SpecialTypeHandler { isWellFormed(String value)42 abstract boolean isWellFormed(String value); // doesn't test validity, just whether it is well formed. canonicalize(String value)43 String canonicalize(String value) { 44 return AsciiUtil.toLowerString(value); 45 } 46 } 47 48 private static class CodepointsTypeHandler extends SpecialTypeHandler { 49 private static final Pattern pat = Pattern.compile("[0-9a-fA-F]{4,6}(-[0-9a-fA-F]{4,6})*"); 50 @Override isWellFormed(String value)51 boolean isWellFormed(String value) { 52 return pat.matcher(value).matches(); 53 } 54 } 55 56 private static class ReorderCodeTypeHandler extends SpecialTypeHandler { 57 private static final Pattern pat = Pattern.compile("[a-zA-Z]{3,8}(-[a-zA-Z]{3,8})*"); 58 @Override isWellFormed(String value)59 boolean isWellFormed(String value) { 60 return pat.matcher(value).matches(); 61 } 62 } 63 64 private static class RgKeyValueTypeHandler extends SpecialTypeHandler { 65 private static final Pattern pat = Pattern.compile("([a-zA-Z]{2}|[0-9]{3})[zZ]{4}"); 66 @Override isWellFormed(String value)67 boolean isWellFormed(String value) { 68 return pat.matcher(value).matches(); 69 } 70 } 71 72 private static class SubdivisionKeyValueTypeHandler extends SpecialTypeHandler { 73 private static final Pattern pat = Pattern.compile("([a-zA-Z]{2}|[0-9]{3})"); 74 @Override isWellFormed(String value)75 boolean isWellFormed(String value) { 76 return pat.matcher(value).matches(); 77 } 78 } 79 80 private static class PrivateUseKeyValueTypeHandler extends SpecialTypeHandler { 81 private static final Pattern pat = Pattern.compile("[a-zA-Z0-9]{3,8}(-[a-zA-Z0-9]{3,8})*"); 82 @Override isWellFormed(String value)83 boolean isWellFormed(String value) { 84 return pat.matcher(value).matches(); 85 } 86 } 87 88 private enum SpecialType { 89 CODEPOINTS(new CodepointsTypeHandler()), 90 REORDER_CODE(new ReorderCodeTypeHandler()), 91 RG_KEY_VALUE(new RgKeyValueTypeHandler()), 92 SUBDIVISION_CODE(new SubdivisionKeyValueTypeHandler()), 93 PRIVATE_USE(new PrivateUseKeyValueTypeHandler()), 94 ; 95 SpecialTypeHandler handler; SpecialType(SpecialTypeHandler handler)96 SpecialType(SpecialTypeHandler handler) { 97 this.handler = handler; 98 } 99 }; 100 101 private static class KeyData { 102 String legacyId; 103 String bcpId; 104 Map<String, Type> typeMap; 105 EnumSet<SpecialType> specialTypes; 106 KeyData(String legacyId, String bcpId, Map<String, Type> typeMap, EnumSet<SpecialType> specialTypes)107 KeyData(String legacyId, String bcpId, Map<String, Type> typeMap, 108 EnumSet<SpecialType> specialTypes) { 109 this.legacyId = legacyId; 110 this.bcpId = bcpId; 111 this.typeMap = typeMap; 112 this.specialTypes = specialTypes; 113 } 114 } 115 116 private static class Type { 117 String legacyId; 118 String bcpId; 119 Type(String legacyId, String bcpId)120 Type(String legacyId, String bcpId) { 121 this.legacyId = legacyId; 122 this.bcpId = bcpId; 123 } 124 } 125 toBcpKey(String key)126 public static String toBcpKey(String key) { 127 key = AsciiUtil.toLowerString(key); 128 KeyData keyData = KEYMAP.get(key); 129 if (keyData != null) { 130 return keyData.bcpId; 131 } 132 return null; 133 } 134 toLegacyKey(String key)135 public static String toLegacyKey(String key) { 136 key = AsciiUtil.toLowerString(key); 137 KeyData keyData = KEYMAP.get(key); 138 if (keyData != null) { 139 return keyData.legacyId; 140 } 141 return null; 142 } 143 toBcpType(String key, String type, Output<Boolean> isKnownKey, Output<Boolean> isSpecialType)144 public static String toBcpType(String key, String type, 145 Output<Boolean> isKnownKey, Output<Boolean> isSpecialType) { 146 147 if (isKnownKey != null) { 148 isKnownKey.value = false; 149 } 150 if (isSpecialType != null) { 151 isSpecialType.value = false; 152 } 153 154 key = AsciiUtil.toLowerString(key); 155 type = AsciiUtil.toLowerString(type); 156 157 KeyData keyData = KEYMAP.get(key); 158 if (keyData != null) { 159 if (isKnownKey != null) { 160 isKnownKey.value = Boolean.TRUE; 161 } 162 Type t = keyData.typeMap.get(type); 163 if (t != null) { 164 return t.bcpId; 165 } 166 if (keyData.specialTypes != null) { 167 for (SpecialType st : keyData.specialTypes) { 168 if (st.handler.isWellFormed(type)) { 169 if (isSpecialType != null) { 170 isSpecialType.value = true; 171 } 172 return st.handler.canonicalize(type); 173 } 174 } 175 } 176 } 177 return null; 178 } 179 180 toLegacyType(String key, String type, Output<Boolean> isKnownKey, Output<Boolean> isSpecialType)181 public static String toLegacyType(String key, String type, 182 Output<Boolean> isKnownKey, Output<Boolean> isSpecialType) { 183 184 if (isKnownKey != null) { 185 isKnownKey.value = false; 186 } 187 if (isSpecialType != null) { 188 isSpecialType.value = false; 189 } 190 191 key = AsciiUtil.toLowerString(key); 192 type = AsciiUtil.toLowerString(type); 193 194 KeyData keyData = KEYMAP.get(key); 195 if (keyData != null) { 196 if (isKnownKey != null) { 197 isKnownKey.value = Boolean.TRUE; 198 } 199 Type t = keyData.typeMap.get(type); 200 if (t != null) { 201 return t.legacyId; 202 } 203 if (keyData.specialTypes != null) { 204 for (SpecialType st : keyData.specialTypes) { 205 if (st.handler.isWellFormed(type)) { 206 if (isSpecialType != null) { 207 isSpecialType.value = true; 208 } 209 return st.handler.canonicalize(type); 210 } 211 } 212 } 213 } 214 return null; 215 } 216 initFromResourceBundle()217 private static void initFromResourceBundle() { 218 UResourceBundle keyTypeDataRes = ICUResourceBundle.getBundleInstance( 219 ICUData.ICU_BASE_NAME, 220 "keyTypeData", 221 ICUResourceBundle.ICU_DATA_CLASS_LOADER, 222 ICUResourceBundle.OpenType.DIRECT); 223 224 getKeyInfo(keyTypeDataRes.get("keyInfo")); 225 getTypeInfo(keyTypeDataRes.get("typeInfo")); 226 227 UResourceBundle keyMapRes = keyTypeDataRes.get("keyMap"); 228 UResourceBundle typeMapRes = keyTypeDataRes.get("typeMap"); 229 230 // alias data is optional 231 UResourceBundle typeAliasRes = null; 232 UResourceBundle bcpTypeAliasRes = null; 233 234 try { 235 typeAliasRes = keyTypeDataRes.get("typeAlias"); 236 } catch (MissingResourceException e) { 237 // fall through 238 } 239 240 try { 241 bcpTypeAliasRes = keyTypeDataRes.get("bcpTypeAlias"); 242 } catch (MissingResourceException e) { 243 // fall through 244 } 245 246 // iterate through keyMap resource 247 UResourceBundleIterator keyMapItr = keyMapRes.getIterator(); 248 Map<String,Set<String>> _Bcp47Keys = new LinkedHashMap<String,Set<String>>(); 249 250 while (keyMapItr.hasNext()) { 251 UResourceBundle keyMapEntry = keyMapItr.next(); 252 String legacyKeyId = keyMapEntry.getKey(); 253 String bcpKeyId = keyMapEntry.getString(); 254 255 boolean hasSameKey = false; 256 if (bcpKeyId.length() == 0) { 257 // Empty value indicates that BCP key is same with the legacy key. 258 bcpKeyId = legacyKeyId; 259 hasSameKey = true; 260 } 261 final LinkedHashSet<String> _bcp47Types = new LinkedHashSet<String>(); 262 _Bcp47Keys.put(bcpKeyId, Collections.unmodifiableSet(_bcp47Types)); 263 264 boolean isTZ = legacyKeyId.equals("timezone"); 265 266 // reverse type alias map 267 Map<String, Set<String>> typeAliasMap = null; 268 if (typeAliasRes != null) { 269 UResourceBundle typeAliasResByKey = null; 270 try { 271 typeAliasResByKey = typeAliasRes.get(legacyKeyId); 272 } catch (MissingResourceException e) { 273 // fall through 274 } 275 if (typeAliasResByKey != null) { 276 typeAliasMap = new HashMap<String, Set<String>>(); 277 UResourceBundleIterator typeAliasResItr = typeAliasResByKey.getIterator(); 278 while (typeAliasResItr.hasNext()) { 279 UResourceBundle typeAliasDataEntry = typeAliasResItr.next(); 280 String from = typeAliasDataEntry.getKey(); 281 String to = typeAliasDataEntry.getString(); 282 if (isTZ) { 283 from = from.replace(':', '/'); 284 } 285 Set<String> aliasSet = typeAliasMap.get(to); 286 if (aliasSet == null) { 287 aliasSet = new HashSet<String>(); 288 typeAliasMap.put(to, aliasSet); 289 } 290 aliasSet.add(from); 291 } 292 } 293 } 294 295 // reverse bcp type alias map 296 Map<String, Set<String>> bcpTypeAliasMap = null; 297 if (bcpTypeAliasRes != null) { 298 UResourceBundle bcpTypeAliasResByKey = null; 299 try { 300 bcpTypeAliasResByKey = bcpTypeAliasRes.get(bcpKeyId); 301 } catch (MissingResourceException e) { 302 // fall through 303 } 304 if (bcpTypeAliasResByKey != null) { 305 bcpTypeAliasMap = new HashMap<String, Set<String>>(); 306 UResourceBundleIterator bcpTypeAliasResItr = bcpTypeAliasResByKey.getIterator(); 307 while (bcpTypeAliasResItr.hasNext()) { 308 UResourceBundle bcpTypeAliasDataEntry = bcpTypeAliasResItr.next(); 309 String from = bcpTypeAliasDataEntry.getKey(); 310 String to = bcpTypeAliasDataEntry.getString(); 311 Set<String> aliasSet = bcpTypeAliasMap.get(to); 312 if (aliasSet == null) { 313 aliasSet = new HashSet<String>(); 314 bcpTypeAliasMap.put(to, aliasSet); 315 } 316 aliasSet.add(from); 317 } 318 } 319 } 320 321 Map<String, Type> typeDataMap = new HashMap<String, Type>(); 322 EnumSet<SpecialType> specialTypeSet = null; 323 324 // look up type map for the key, and walk through the mapping data 325 UResourceBundle typeMapResByKey = null; 326 try { 327 typeMapResByKey = typeMapRes.get(legacyKeyId); 328 } catch (MissingResourceException e) { 329 // type map for each key must exist 330 assert false; 331 } 332 if (typeMapResByKey != null) { 333 UResourceBundleIterator typeMapResByKeyItr = typeMapResByKey.getIterator(); 334 while (typeMapResByKeyItr.hasNext()) { 335 UResourceBundle typeMapEntry = typeMapResByKeyItr.next(); 336 String legacyTypeId = typeMapEntry.getKey(); 337 String bcpTypeId = typeMapEntry.getString(); 338 339 // special types 340 final char first = legacyTypeId.charAt(0); 341 final boolean isSpecialType = '9' < first && first < 'a' && bcpTypeId.length() == 0; 342 if (isSpecialType) { 343 if (specialTypeSet == null) { 344 specialTypeSet = EnumSet.noneOf(SpecialType.class); 345 } 346 specialTypeSet.add(SpecialType.valueOf(legacyTypeId)); 347 _bcp47Types.add(legacyTypeId); 348 continue; 349 } 350 351 if (isTZ) { 352 // a timezone key uses a colon instead of a slash in the resource. 353 // e.g. America:Los_Angeles 354 legacyTypeId = legacyTypeId.replace(':', '/'); 355 } 356 357 boolean hasSameType = false; 358 if (bcpTypeId.length() == 0) { 359 // Empty value indicates that BCP type is same with the legacy type. 360 bcpTypeId = legacyTypeId; 361 hasSameType = true; 362 } 363 _bcp47Types.add(bcpTypeId); 364 365 // Note: legacy type value should never be 366 // equivalent to bcp type value of a different 367 // type under the same key. So we use a single 368 // map for lookup. 369 Type t = new Type(legacyTypeId, bcpTypeId); 370 typeDataMap.put(AsciiUtil.toLowerString(legacyTypeId), t); 371 if (!hasSameType) { 372 typeDataMap.put(AsciiUtil.toLowerString(bcpTypeId), t); 373 } 374 375 // Also put aliases in the map 376 if (typeAliasMap != null) { 377 Set<String> typeAliasSet = typeAliasMap.get(legacyTypeId); 378 if (typeAliasSet != null) { 379 for (String alias : typeAliasSet) { 380 typeDataMap.put(AsciiUtil.toLowerString(alias), t); 381 } 382 } 383 } 384 if (bcpTypeAliasMap != null) { 385 Set<String> bcpTypeAliasSet = bcpTypeAliasMap.get(bcpTypeId); 386 if (bcpTypeAliasSet != null) { 387 for (String alias : bcpTypeAliasSet) { 388 typeDataMap.put(AsciiUtil.toLowerString(alias), t); 389 } 390 } 391 } 392 } 393 } 394 395 KeyData keyData = new KeyData(legacyKeyId, bcpKeyId, typeDataMap, specialTypeSet); 396 397 KEYMAP.put(AsciiUtil.toLowerString(legacyKeyId), keyData); 398 if (!hasSameKey) { 399 KEYMAP.put(AsciiUtil.toLowerString(bcpKeyId), keyData); 400 } 401 } 402 BCP47_KEYS = Collections.unmodifiableMap(_Bcp47Keys); 403 } 404 405 static Set<String> DEPRECATED_KEYS = Collections.emptySet(); // default for no resources 406 static Map<String, ValueType> VALUE_TYPES = Collections.emptyMap(); // default for no resources 407 static Map<String, Set<String>> DEPRECATED_KEY_TYPES = Collections.emptyMap(); // default for no resources 408 409 private enum KeyInfoType {deprecated, valueType} 410 private enum TypeInfoType {deprecated} 411 412 /** Reads 413 keyInfo{ 414 deprecated{ 415 kh{"true"} 416 vt{"true"} 417 } 418 valueType{ 419 ca{"incremental"} 420 h0{"single"} 421 kr{"multiple"} 422 vt{"multiple"} 423 x0{"any"} 424 } 425 } 426 */ 427 private static void getKeyInfo(UResourceBundle keyInfoRes) { 428 Set<String> _deprecatedKeys = new LinkedHashSet<String>(); 429 Map<String, ValueType> _valueTypes = new LinkedHashMap<String, ValueType>(); 430 for (UResourceBundleIterator keyInfoIt = keyInfoRes.getIterator(); keyInfoIt.hasNext();) { 431 UResourceBundle keyInfoEntry = keyInfoIt.next(); 432 String key = keyInfoEntry.getKey(); 433 KeyInfoType keyInfo = KeyInfoType.valueOf(key); 434 for (UResourceBundleIterator keyInfoIt2 = keyInfoEntry.getIterator(); keyInfoIt2.hasNext();) { 435 UResourceBundle keyInfoEntry2 = keyInfoIt2.next(); 436 String key2 = keyInfoEntry2.getKey(); 437 String value2 = keyInfoEntry2.getString(); 438 switch (keyInfo) { 439 case deprecated: 440 _deprecatedKeys.add(key2); 441 break; 442 case valueType: 443 _valueTypes.put(key2, ValueType.valueOf(value2)); 444 break; 445 } 446 } 447 } 448 DEPRECATED_KEYS = Collections.unmodifiableSet(_deprecatedKeys); 449 VALUE_TYPES = Collections.unmodifiableMap(_valueTypes); 450 } 451 452 /** Reads: 453 typeInfo{ 454 deprecated{ 455 co{ 456 direct{"true"} 457 } 458 tz{ 459 camtr{"true"} 460 } 461 } 462 } 463 */ 464 private static void getTypeInfo(UResourceBundle typeInfoRes) { 465 Map<String,Set<String>> _deprecatedKeyTypes = new LinkedHashMap<String,Set<String>>(); 466 for (UResourceBundleIterator keyInfoIt = typeInfoRes.getIterator(); keyInfoIt.hasNext();) { 467 UResourceBundle keyInfoEntry = keyInfoIt.next(); 468 String key = keyInfoEntry.getKey(); 469 TypeInfoType typeInfo = TypeInfoType.valueOf(key); 470 for (UResourceBundleIterator keyInfoIt2 = keyInfoEntry.getIterator(); keyInfoIt2.hasNext();) { 471 UResourceBundle keyInfoEntry2 = keyInfoIt2.next(); 472 String key2 = keyInfoEntry2.getKey(); 473 Set<String> _deprecatedTypes = new LinkedHashSet<String>(); 474 for (UResourceBundleIterator keyInfoIt3 = keyInfoEntry2.getIterator(); keyInfoIt3.hasNext();) { 475 UResourceBundle keyInfoEntry3 = keyInfoIt3.next(); 476 String key3 = keyInfoEntry3.getKey(); 477 switch (typeInfo) { // allow for expansion 478 case deprecated: 479 _deprecatedTypes.add(key3); 480 break; 481 } 482 } 483 _deprecatedKeyTypes.put(key2, Collections.unmodifiableSet(_deprecatedTypes)); 484 } 485 } 486 DEPRECATED_KEY_TYPES = Collections.unmodifiableMap(_deprecatedKeyTypes); 487 } 488 489 // 490 // Note: The key-type data is currently read from ICU resource bundle keyTypeData.res. 491 // In future, we may import the data into code like below directly from CLDR to 492 // avoid cyclic dependency between ULocale and UResourceBundle. For now, the code 493 // below is just for proof of concept, and commented out. 494 // 495 496 // private static final String[][] TYPE_DATA_CA = { 497 // // {<legacy type>, <bcp type - if different>}, 498 // {"buddhist", null}, 499 // {"chinese", null}, 500 // {"coptic", null}, 501 // {"dangi", null}, 502 // {"ethiopic", null}, 503 // {"ethiopic-amete-alem", "ethioaa"}, 504 // {"gregorian", "gregory"}, 505 // {"hebrew", null}, 506 // {"indian", null}, 507 // {"islamic", null}, 508 // {"islamic-civil", null}, 509 // {"islamic-rgsa", null}, 510 // {"islamic-tbla", null}, 511 // {"islamic-umalqura", null}, 512 // {"iso8601", null}, 513 // {"japanese", null}, 514 // {"persian", null}, 515 // {"roc", null}, 516 // }; 517 // 518 // private static final String[][] TYPE_DATA_KS = { 519 // // {<legacy type>, <bcp type - if different>}, 520 // {"identical", "identic"}, 521 // {"primary", "level1"}, 522 // {"quaternary", "level4"}, 523 // {"secondary", "level2"}, 524 // {"tertiary", "level3"}, 525 // }; 526 // 527 // private static final String[][] TYPE_ALIAS_KS = { 528 // // {<legacy alias>, <legacy canonical>}, 529 // {"quarternary", "quaternary"}, 530 // }; 531 // 532 // private static final String[][] BCP_TYPE_ALIAS_CA = { 533 // // {<bcp deprecated>, <bcp preferred> 534 // {"islamicc", "islamic-civil"}, 535 // }; 536 // 537 // private static final Object[][] KEY_DATA = { 538 // // {<legacy key>, <bcp key - if different>, <type map>, <type alias>, <bcp type alias>}, 539 // {"calendar", "ca", TYPE_DATA_CA, null, BCP_TYPE_ALIAS_CA}, 540 // {"colstrength", "ks", TYPE_DATA_KS, TYPE_ALIAS_KS, null}, 541 // }; 542 543 private static final Object[][] KEY_DATA = {}; 544 545 @SuppressWarnings("unused") 546 private static void initFromTables() { 547 for (Object[] keyDataEntry : KEY_DATA) { 548 String legacyKeyId = (String)keyDataEntry[0]; 549 String bcpKeyId = (String)keyDataEntry[1]; 550 String[][] typeData = (String[][])keyDataEntry[2]; 551 String[][] typeAliasData = (String[][])keyDataEntry[3]; 552 String[][] bcpTypeAliasData = (String[][])keyDataEntry[4]; 553 554 boolean hasSameKey = false; 555 if (bcpKeyId == null) { 556 bcpKeyId = legacyKeyId; 557 hasSameKey = true; 558 } 559 560 // reverse type alias map 561 Map<String, Set<String>> typeAliasMap = null; 562 if (typeAliasData != null) { 563 typeAliasMap = new HashMap<String, Set<String>>(); 564 for (String[] typeAliasDataEntry : typeAliasData) { 565 String from = typeAliasDataEntry[0]; 566 String to = typeAliasDataEntry[1]; 567 Set<String> aliasSet = typeAliasMap.get(to); 568 if (aliasSet == null) { 569 aliasSet = new HashSet<String>(); 570 typeAliasMap.put(to, aliasSet); 571 } 572 aliasSet.add(from); 573 } 574 } 575 576 // BCP type alias map data 577 Map<String, Set<String>> bcpTypeAliasMap = null; 578 if (bcpTypeAliasData != null) { 579 bcpTypeAliasMap = new HashMap<String, Set<String>>(); 580 for (String[] bcpTypeAliasDataEntry : bcpTypeAliasData) { 581 String from = bcpTypeAliasDataEntry[0]; 582 String to = bcpTypeAliasDataEntry[1]; 583 Set<String> aliasSet = bcpTypeAliasMap.get(to); 584 if (aliasSet == null) { 585 aliasSet = new HashSet<String>(); 586 bcpTypeAliasMap.put(to, aliasSet); 587 } 588 aliasSet.add(from); 589 } 590 } 591 592 // Type map data 593 assert typeData != null; 594 Map<String, Type> typeDataMap = new HashMap<String, Type>(); 595 Set<SpecialType> specialTypeSet = null; 596 597 for (String[] typeDataEntry : typeData) { 598 String legacyTypeId = typeDataEntry[0]; 599 String bcpTypeId = typeDataEntry[1]; 600 601 // special types 602 boolean isSpecialType = false; 603 for (SpecialType st : SpecialType.values()) { 604 if (legacyTypeId.equals(st.toString())) { 605 isSpecialType = true; 606 if (specialTypeSet == null) { 607 specialTypeSet = new HashSet<SpecialType>(); 608 } 609 specialTypeSet.add(st); 610 break; 611 } 612 } 613 if (isSpecialType) { 614 continue; 615 } 616 617 boolean hasSameType = false; 618 if (bcpTypeId == null) { 619 bcpTypeId = legacyTypeId; 620 hasSameType = true; 621 } 622 623 // Note: legacy type value should never be 624 // equivalent to bcp type value of a different 625 // type under the same key. So we use a single 626 // map for lookup. 627 Type t = new Type(legacyTypeId, bcpTypeId); 628 typeDataMap.put(AsciiUtil.toLowerString(legacyTypeId), t); 629 if (!hasSameType) { 630 typeDataMap.put(AsciiUtil.toLowerString(bcpTypeId), t); 631 } 632 633 // Also put aliases in the index 634 Set<String> typeAliasSet = typeAliasMap.get(legacyTypeId); 635 if (typeAliasSet != null) { 636 for (String alias : typeAliasSet) { 637 typeDataMap.put(AsciiUtil.toLowerString(alias), t); 638 } 639 } 640 Set<String> bcpTypeAliasSet = bcpTypeAliasMap.get(bcpTypeId); 641 if (bcpTypeAliasSet != null) { 642 for (String alias : bcpTypeAliasSet) { 643 typeDataMap.put(AsciiUtil.toLowerString(alias), t); 644 } 645 } 646 } 647 648 EnumSet<SpecialType> specialTypes = null; 649 if (specialTypeSet != null) { 650 specialTypes = EnumSet.copyOf(specialTypeSet); 651 } 652 653 KeyData keyData = new KeyData(legacyKeyId, bcpKeyId, typeDataMap, specialTypes); 654 655 KEYMAP.put(AsciiUtil.toLowerString(legacyKeyId), keyData); 656 if (!hasSameKey) { 657 KEYMAP.put(AsciiUtil.toLowerString(bcpKeyId), keyData); 658 } 659 } 660 } 661 662 private static final Map<String, KeyData> KEYMAP = new HashMap<String, KeyData>(); 663 private static Map<String, Set<String>> BCP47_KEYS; 664 665 static { 666 // initFromTables(); 667 initFromResourceBundle(); 668 } 669 670 public static Set<String> getBcp47Keys() { 671 return BCP47_KEYS.keySet(); 672 }; 673 674 public static Set<String> getBcp47KeyTypes(String key) { 675 return BCP47_KEYS.get(key); 676 }; 677 678 public static boolean isDeprecated(String key) { 679 return DEPRECATED_KEYS.contains(key); 680 } 681 682 public static boolean isDeprecated(String key, String type) { 683 Set<String> deprecatedTypes = DEPRECATED_KEY_TYPES.get(key); 684 if (deprecatedTypes == null) { 685 return false; 686 } 687 return deprecatedTypes.contains(type); 688 } 689 690 public static ValueType getValueType(String key) { 691 ValueType type = VALUE_TYPES.get(key); 692 return type == null ? ValueType.single : type; 693 } 694 } 695