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) 2001-2016, International Business Machines Corporation and 7 * others. All Rights Reserved. 8 ******************************************************************************* 9 */ 10 package ohos.global.icu.impl; 11 12 import java.util.Collections; 13 import java.util.Locale; 14 import java.util.Map; 15 import java.util.Set; 16 17 import ohos.global.icu.util.ULocale; 18 19 /** 20 * @hide exposed on OHOS 21 */ 22 public class ICULocaleService extends ICUService { 23 private ULocale fallbackLocale; 24 private String fallbackLocaleName; 25 26 /** 27 * Construct an ICULocaleService. 28 */ ICULocaleService()29 public ICULocaleService() { 30 } 31 32 /** 33 * Construct an ICULocaleService with a name (useful for debugging). 34 */ ICULocaleService(String name)35 public ICULocaleService(String name) { 36 super(name); 37 } 38 39 /** 40 * Convenience override for callers using locales. This calls 41 * get(ULocale, int, ULocale[]) with KIND_ANY for kind and null for 42 * actualReturn. 43 */ get(ULocale locale)44 public Object get(ULocale locale) { 45 return get(locale, LocaleKey.KIND_ANY, null); 46 } 47 48 /** 49 * Convenience override for callers using locales. This calls 50 * get(ULocale, int, ULocale[]) with a null actualReturn. 51 */ get(ULocale locale, int kind)52 public Object get(ULocale locale, int kind) { 53 return get(locale, kind, null); 54 } 55 56 /** 57 * Convenience override for callers using locales. This calls 58 * get(ULocale, int, ULocale[]) with KIND_ANY for kind. 59 */ get(ULocale locale, ULocale[] actualReturn)60 public Object get(ULocale locale, ULocale[] actualReturn) { 61 return get(locale, LocaleKey.KIND_ANY, actualReturn); 62 } 63 64 /** 65 * Convenience override for callers using locales. This uses 66 * createKey(ULocale.toString(), kind) to create a key, calls getKey, and then 67 * if actualReturn is not null, returns the actualResult from 68 * getKey (stripping any prefix) into a ULocale. 69 */ get(ULocale locale, int kind, ULocale[] actualReturn)70 public Object get(ULocale locale, int kind, ULocale[] actualReturn) { 71 Key key = createKey(locale, kind); 72 if (actualReturn == null) { 73 return getKey(key); 74 } 75 76 String[] temp = new String[1]; 77 Object result = getKey(key, temp); 78 if (result != null) { 79 int n = temp[0].indexOf("/"); 80 if (n >= 0) { 81 temp[0] = temp[0].substring(n+1); 82 } 83 actualReturn[0] = new ULocale(temp[0]); 84 } 85 return result; 86 } 87 88 /** 89 * Convenience override for callers using locales. This calls 90 * registerObject(Object, ULocale, int kind, boolean visible) 91 * passing KIND_ANY for the kind, and true for the visibility. 92 */ registerObject(Object obj, ULocale locale)93 public Factory registerObject(Object obj, ULocale locale) { 94 return registerObject(obj, locale, LocaleKey.KIND_ANY, true); 95 } 96 97 /** 98 * Convenience override for callers using locales. This calls 99 * registerObject(Object, ULocale, int kind, boolean visible) 100 * passing KIND_ANY for the kind. 101 */ registerObject(Object obj, ULocale locale, boolean visible)102 public Factory registerObject(Object obj, ULocale locale, boolean visible) { 103 return registerObject(obj, locale, LocaleKey.KIND_ANY, visible); 104 } 105 106 /** 107 * Convenience function for callers using locales. This calls 108 * registerObject(Object, ULocale, int kind, boolean visible) 109 * passing true for the visibility. 110 */ registerObject(Object obj, ULocale locale, int kind)111 public Factory registerObject(Object obj, ULocale locale, int kind) { 112 return registerObject(obj, locale, kind, true); 113 } 114 115 /** 116 * Convenience function for callers using locales. This instantiates 117 * a SimpleLocaleKeyFactory, and registers the factory. 118 */ registerObject(Object obj, ULocale locale, int kind, boolean visible)119 public Factory registerObject(Object obj, ULocale locale, int kind, boolean visible) { 120 Factory factory = new SimpleLocaleKeyFactory(obj, locale, kind, visible); 121 return registerFactory(factory); 122 } 123 124 /** 125 * Convenience method for callers using locales. This returns the standard 126 * Locale list, built from the Set of visible ids. 127 */ getAvailableLocales()128 public Locale[] getAvailableLocales() { 129 // TODO make this wrap getAvailableULocales later 130 Set<String> visIDs = getVisibleIDs(); 131 Locale[] locales = new Locale[visIDs.size()]; 132 int n = 0; 133 for (String id : visIDs) { 134 Locale loc = LocaleUtility.getLocaleFromName(id); 135 locales[n++] = loc; 136 } 137 return locales; 138 } 139 140 /** 141 * Convenience method for callers using locales. This returns the standard 142 * ULocale list, built from the Set of visible ids. 143 */ getAvailableULocales()144 public ULocale[] getAvailableULocales() { 145 Set<String> visIDs = getVisibleIDs(); 146 ULocale[] locales = new ULocale[visIDs.size()]; 147 int n = 0; 148 for (String id : visIDs) { 149 locales[n++] = new ULocale(id); 150 } 151 return locales; 152 } 153 154 /** 155 * A subclass of Key that implements a locale fallback mechanism. 156 * The first locale to search for is the locale provided by the 157 * client, and the fallback locale to search for is the current 158 * default locale. If a prefix is present, the currentDescriptor 159 * includes it before the locale proper, separated by "/". This 160 * is the default key instantiated by ICULocaleService.</p> 161 * 162 * <p>Canonicalization adjusts the locale string so that the 163 * section before the first understore is in lower case, and the rest 164 * is in upper case, with no trailing underscores.</p> 165 * @hide exposed on OHOS 166 */ 167 public static class LocaleKey extends ICUService.Key { 168 private int kind; 169 private int varstart; 170 private String primaryID; 171 private String fallbackID; 172 private String currentID; 173 174 public static final int KIND_ANY = -1; 175 176 /** 177 * Create a LocaleKey with canonical primary and fallback IDs. 178 */ createWithCanonicalFallback(String primaryID, String canonicalFallbackID)179 public static LocaleKey createWithCanonicalFallback(String primaryID, String canonicalFallbackID) { 180 return createWithCanonicalFallback(primaryID, canonicalFallbackID, KIND_ANY); 181 } 182 183 /** 184 * Create a LocaleKey with canonical primary and fallback IDs. 185 */ createWithCanonicalFallback(String primaryID, String canonicalFallbackID, int kind)186 public static LocaleKey createWithCanonicalFallback(String primaryID, String canonicalFallbackID, int kind) { 187 if (primaryID == null) { 188 return null; 189 } 190 String canonicalPrimaryID = ULocale.getName(primaryID); 191 return new LocaleKey(primaryID, canonicalPrimaryID, canonicalFallbackID, kind); 192 } 193 194 /** 195 * Create a LocaleKey with canonical primary and fallback IDs. 196 */ createWithCanonical(ULocale locale, String canonicalFallbackID, int kind)197 public static LocaleKey createWithCanonical(ULocale locale, String canonicalFallbackID, int kind) { 198 if (locale == null) { 199 return null; 200 } 201 String canonicalPrimaryID = locale.getName(); 202 return new LocaleKey(canonicalPrimaryID, canonicalPrimaryID, canonicalFallbackID, kind); 203 } 204 205 /** 206 * PrimaryID is the user's requested locale string, 207 * canonicalPrimaryID is this string in canonical form, 208 * fallbackID is the current default locale's string in 209 * canonical form. 210 */ LocaleKey(String primaryID, String canonicalPrimaryID, String canonicalFallbackID, int kind)211 protected LocaleKey(String primaryID, String canonicalPrimaryID, String canonicalFallbackID, int kind) { 212 super(primaryID); 213 this.kind = kind; 214 215 if (canonicalPrimaryID == null || canonicalPrimaryID.equalsIgnoreCase("root")) { 216 this.primaryID = ""; 217 this.fallbackID = null; 218 } else { 219 int idx = canonicalPrimaryID.indexOf('@'); 220 if (idx == 4 && canonicalPrimaryID.regionMatches(true, 0, "root", 0, 4)) { 221 this.primaryID = canonicalPrimaryID.substring(4); 222 this.varstart = 0; 223 this.fallbackID = null; 224 } else { 225 this.primaryID = canonicalPrimaryID; 226 this.varstart = idx; 227 228 if (canonicalFallbackID == null || this.primaryID.equals(canonicalFallbackID)) { 229 this.fallbackID = ""; 230 } else { 231 this.fallbackID = canonicalFallbackID; 232 } 233 } 234 } 235 236 this.currentID = varstart == -1 ? this.primaryID : this.primaryID.substring(0, varstart); 237 } 238 239 /** 240 * Return the prefix associated with the kind, or null if the kind is KIND_ANY. 241 */ prefix()242 public String prefix() { 243 return kind == KIND_ANY ? null : Integer.toString(kind()); 244 } 245 246 /** 247 * Return the kind code associated with this key. 248 */ kind()249 public int kind() { 250 return kind; 251 } 252 253 /** 254 * Return the (canonical) original ID. 255 */ 256 @Override canonicalID()257 public String canonicalID() { 258 return primaryID; 259 } 260 261 /** 262 * Return the (canonical) current ID, or null if no current id. 263 */ 264 @Override currentID()265 public String currentID() { 266 return currentID; 267 } 268 269 /** 270 * Return the (canonical) current descriptor, or null if no current id. 271 * Includes the keywords, whereas the ID does not include keywords. 272 */ 273 @Override currentDescriptor()274 public String currentDescriptor() { 275 String result = currentID(); 276 if (result != null) { 277 StringBuilder buf = new StringBuilder(); // default capacity 16 is usually good enough 278 if (kind != KIND_ANY) { 279 buf.append(prefix()); 280 } 281 buf.append('/'); 282 buf.append(result); 283 if (varstart != -1) { 284 buf.append(primaryID.substring(varstart, primaryID.length())); 285 } 286 result = buf.toString(); 287 } 288 return result; 289 } 290 291 /** 292 * Convenience method to return the locale corresponding to the (canonical) original ID. 293 */ canonicalLocale()294 public ULocale canonicalLocale() { 295 return new ULocale(primaryID); 296 } 297 298 /** 299 * Convenience method to return the ulocale corresponding to the (canonical) currentID. 300 */ currentLocale()301 public ULocale currentLocale() { 302 if (varstart == -1) { 303 return new ULocale(currentID); 304 } else { 305 return new ULocale(currentID + primaryID.substring(varstart)); 306 } 307 } 308 309 /** 310 * If the key has a fallback, modify the key and return true, 311 * otherwise return false.</p> 312 * 313 * <p>First falls back through the primary ID, then through 314 * the fallbackID. The final fallback is "" (root) 315 * unless the primary id was "" (root), in which case 316 * there is no fallback. 317 */ 318 @Override fallback()319 public boolean fallback() { 320 int x = currentID.lastIndexOf('_'); 321 if (x != -1) { 322 while (--x >= 0 && currentID.charAt(x) == '_') { // handle zh__PINYIN 323 } 324 currentID = currentID.substring(0, x+1); 325 return true; 326 } 327 if (fallbackID != null) { 328 currentID = fallbackID; 329 if (fallbackID.length() == 0) { 330 fallbackID = null; 331 } else { 332 fallbackID = ""; 333 } 334 return true; 335 } 336 currentID = null; 337 return false; 338 } 339 340 /** 341 * If a key created from id would eventually fallback to match the 342 * canonical ID of this key, return true. 343 */ 344 @Override isFallbackOf(String id)345 public boolean isFallbackOf(String id) { 346 return LocaleUtility.isFallbackOf(canonicalID(), id); 347 } 348 } 349 350 /** 351 * A subclass of Factory that uses LocaleKeys. If 'visible' the 352 * factory reports its IDs. 353 * @hide exposed on OHOS 354 */ 355 public static abstract class LocaleKeyFactory implements Factory { 356 protected final String name; 357 protected final boolean visible; 358 359 public static final boolean VISIBLE = true; 360 public static final boolean INVISIBLE = false; 361 362 /** 363 * Constructor used by subclasses. 364 */ LocaleKeyFactory(boolean visible)365 protected LocaleKeyFactory(boolean visible) { 366 this.visible = visible; 367 this.name = null; 368 } 369 370 /** 371 * Constructor used by subclasses. 372 */ LocaleKeyFactory(boolean visible, String name)373 protected LocaleKeyFactory(boolean visible, String name) { 374 this.visible = visible; 375 this.name = name; 376 } 377 378 /** 379 * Implement superclass abstract method. This checks the currentID of 380 * the key against the supported IDs, and passes the canonicalLocale and 381 * kind off to handleCreate (which subclasses must implement). 382 */ 383 @Override create(Key key, ICUService service)384 public Object create(Key key, ICUService service) { 385 if (handlesKey(key)) { 386 LocaleKey lkey = (LocaleKey)key; 387 int kind = lkey.kind(); 388 389 ULocale uloc = lkey.currentLocale(); 390 return handleCreate(uloc, kind, service); 391 } else { 392 // System.out.println("factory: " + this + " did not support id: " + key.currentID()); 393 // System.out.println("supported ids: " + getSupportedIDs()); 394 } 395 return null; 396 } 397 handlesKey(Key key)398 protected boolean handlesKey(Key key) { 399 if (key != null) { 400 String id = key.currentID(); 401 Set<String> supported = getSupportedIDs(); 402 return supported.contains(id); 403 } 404 return false; 405 } 406 407 /** 408 * Override of superclass method. 409 */ 410 @Override updateVisibleIDs(Map<String, Factory> result)411 public void updateVisibleIDs(Map<String, Factory> result) { 412 Set<String> cache = getSupportedIDs(); 413 for (String id : cache) { 414 if (visible) { 415 result.put(id, this); 416 } else { 417 result.remove(id); 418 } 419 } 420 } 421 422 /** 423 * Return a localized name for the locale represented by id. 424 */ 425 @Override getDisplayName(String id, ULocale locale)426 public String getDisplayName(String id, ULocale locale) { 427 // assume if the user called this on us, we must have handled some fallback of this id 428 // if (isSupportedID(id)) { 429 if (locale == null) { 430 return id; 431 } 432 ULocale loc = new ULocale(id); 433 return loc.getDisplayName(locale); 434 // } 435 // return null; 436 } 437 438 ///CLOVER:OFF 439 /** 440 * Utility method used by create(Key, ICUService). Subclasses can 441 * implement this instead of create. 442 */ handleCreate(ULocale loc, int kind, ICUService service)443 protected Object handleCreate(ULocale loc, int kind, ICUService service) { 444 return null; 445 } 446 ///CLOVER:ON 447 448 /** 449 * Return true if this id is one the factory supports (visible or 450 * otherwise). 451 */ isSupportedID(String id)452 protected boolean isSupportedID(String id) { 453 return getSupportedIDs().contains(id); 454 } 455 456 /** 457 * Return the set of ids that this factory supports (visible or 458 * otherwise). This can be called often and might need to be 459 * cached if it is expensive to create. 460 */ getSupportedIDs()461 protected Set<String> getSupportedIDs() { 462 return Collections.emptySet(); 463 } 464 465 /** 466 * For debugging. 467 */ 468 @Override toString()469 public String toString() { 470 StringBuilder buf = new StringBuilder(super.toString()); 471 if (name != null) { 472 buf.append(", name: "); 473 buf.append(name); 474 } 475 buf.append(", visible: "); 476 buf.append(visible); 477 return buf.toString(); 478 } 479 } 480 481 /** 482 * A LocaleKeyFactory that just returns a single object for a kind/locale. 483 * @hide exposed on OHOS 484 */ 485 public static class SimpleLocaleKeyFactory extends LocaleKeyFactory { 486 private final Object obj; 487 private final String id; 488 private final int kind; 489 490 // TODO: remove when we no longer need this SimpleLocaleKeyFactory(Object obj, ULocale locale, int kind, boolean visible)491 public SimpleLocaleKeyFactory(Object obj, ULocale locale, int kind, boolean visible) { 492 this(obj, locale, kind, visible, null); 493 } 494 SimpleLocaleKeyFactory(Object obj, ULocale locale, int kind, boolean visible, String name)495 public SimpleLocaleKeyFactory(Object obj, ULocale locale, int kind, boolean visible, String name) { 496 super(visible, name); 497 498 this.obj = obj; 499 this.id = locale.getBaseName(); 500 this.kind = kind; 501 } 502 503 /** 504 * Returns the service object if kind/locale match. Service is not used. 505 */ 506 @Override create(Key key, ICUService service)507 public Object create(Key key, ICUService service) { 508 if (!(key instanceof LocaleKey)) { 509 return null; 510 } 511 512 LocaleKey lkey = (LocaleKey)key; 513 if (kind != LocaleKey.KIND_ANY && kind != lkey.kind()) { 514 return null; 515 } 516 if (!id.equals(lkey.currentID())) { 517 return null; 518 } 519 520 return obj; 521 } 522 523 @Override isSupportedID(String idToCheck)524 protected boolean isSupportedID(String idToCheck) { 525 return this.id.equals(idToCheck); 526 } 527 528 @Override updateVisibleIDs(Map<String, Factory> result)529 public void updateVisibleIDs(Map<String, Factory> result) { 530 if (visible) { 531 result.put(id, this); 532 } else { 533 result.remove(id); 534 } 535 } 536 537 @Override toString()538 public String toString() { 539 StringBuilder buf = new StringBuilder(super.toString()); 540 buf.append(", id: "); 541 buf.append(id); 542 buf.append(", kind: "); 543 buf.append(kind); 544 return buf.toString(); 545 } 546 } 547 548 /** 549 * A LocaleKeyFactory that creates a service based on the ICU locale data. 550 * This is a base class for most ICU factories. Subclasses instantiate it 551 * with a constructor that takes a bundle name, which determines the supported 552 * IDs. Subclasses then override handleCreate to create the actual service 553 * object. The default implementation returns a resource bundle. 554 * @hide exposed on OHOS 555 */ 556 public static class ICUResourceBundleFactory extends LocaleKeyFactory { 557 protected final String bundleName; 558 559 /** 560 * Convenience constructor that uses the main ICU bundle name. 561 */ ICUResourceBundleFactory()562 public ICUResourceBundleFactory() { 563 this(ICUData.ICU_BASE_NAME); 564 } 565 566 /** 567 * A service factory based on ICU resource data in resources 568 * with the given name. 569 */ ICUResourceBundleFactory(String bundleName)570 public ICUResourceBundleFactory(String bundleName) { 571 super(true); 572 573 this.bundleName = bundleName; 574 } 575 576 /** 577 * Return the supported IDs. This is the set of all locale names for the bundleName. 578 */ 579 @Override getSupportedIDs()580 protected Set<String> getSupportedIDs() { 581 return ICUResourceBundle.getFullLocaleNameSet(bundleName, loader()); 582 } 583 584 /** 585 * Override of superclass method. 586 */ 587 @Override updateVisibleIDs(Map<String, Factory> result)588 public void updateVisibleIDs(Map<String, Factory> result) { 589 Set<String> visibleIDs = ICUResourceBundle.getAvailableLocaleNameSet(bundleName, loader()); // only visible ids 590 for (String id : visibleIDs) { 591 result.put(id, this); 592 } 593 } 594 595 /** 596 * Create the service. The default implementation returns the resource bundle 597 * for the locale, ignoring kind, and service. 598 */ 599 @Override handleCreate(ULocale loc, int kind, ICUService service)600 protected Object handleCreate(ULocale loc, int kind, ICUService service) { 601 return ICUResourceBundle.getBundleInstance(bundleName, loc, loader()); 602 } 603 loader()604 protected ClassLoader loader() { 605 return ClassLoaderUtil.getClassLoader(getClass()); 606 } 607 608 @Override toString()609 public String toString() { 610 return super.toString() + ", bundle: " + bundleName; 611 } 612 } 613 614 /** 615 * Return the name of the current fallback locale. If it has changed since this was 616 * last accessed, the service cache is cleared. 617 */ validateFallbackLocale()618 public String validateFallbackLocale() { 619 ULocale loc = ULocale.getDefault(); 620 if (loc != fallbackLocale) { 621 synchronized (this) { 622 if (loc != fallbackLocale) { 623 fallbackLocale = loc; 624 fallbackLocaleName = loc.getBaseName(); 625 clearServiceCache(); 626 } 627 } 628 } 629 return fallbackLocaleName; 630 } 631 632 @Override createKey(String id)633 public Key createKey(String id) { 634 return LocaleKey.createWithCanonicalFallback(id, validateFallbackLocale()); 635 } 636 createKey(String id, int kind)637 public Key createKey(String id, int kind) { 638 return LocaleKey.createWithCanonicalFallback(id, validateFallbackLocale(), kind); 639 } 640 createKey(ULocale l, int kind)641 public Key createKey(ULocale l, int kind) { 642 return LocaleKey.createWithCanonical(l, validateFallbackLocale(), kind); 643 } 644 } 645