1/* 2 ******************************************************************************* 3 * Copyright (C) 2009-2015, International Business Machines Corporation and * 4 * others. All Rights Reserved. * 5 ******************************************************************************* 6 */ 7package com.ibm.icu.text; 8 9import java.lang.reflect.InvocationTargetException; 10import java.lang.reflect.Method; 11import java.util.Collections; 12import java.util.Comparator; 13import java.util.List; 14import java.util.Locale; 15import java.util.Set; 16 17import com.ibm.icu.impl.ICUConfig; 18import com.ibm.icu.lang.UScript; 19import com.ibm.icu.text.DisplayContext.Type; 20import com.ibm.icu.util.IllformedLocaleException; 21import com.ibm.icu.util.ULocale; 22 23/** 24 * Returns display names of ULocales and components of ULocales. For 25 * more information on language, script, region, variant, key, and 26 * values, see {@link com.ibm.icu.util.ULocale}. 27 * @stable ICU 4.4 28 */ 29public abstract class LocaleDisplayNames { 30 /** 31 * Enum used in {@link #getInstance(ULocale, DialectHandling)}. 32 * @stable ICU 4.4 33 */ 34 public enum DialectHandling { 35 /** 36 * Use standard names when generating a locale name, 37 * e.g. en_GB displays as 'English (United Kingdom)'. 38 * @stable ICU 4.4 39 */ 40 STANDARD_NAMES, 41 /** 42 * Use dialect names when generating a locale name, 43 * e.g. en_GB displays as 'British English'. 44 * @stable ICU 4.4 45 */ 46 DIALECT_NAMES 47 } 48 49 // factory methods 50 /** 51 * Convenience overload of {@link #getInstance(ULocale, DialectHandling)} that specifies 52 * STANDARD dialect handling. 53 * @param locale the display locale 54 * @return a LocaleDisplayNames instance 55 * @stable ICU 4.4 56 */ 57 public static LocaleDisplayNames getInstance(ULocale locale) { 58 return getInstance(locale, DialectHandling.STANDARD_NAMES); 59 }; 60 61 /** 62 * Convenience overload of {@link #getInstance(Locale, DisplayContext...)} that specifies 63 * {@link DisplayContext#STANDARD_NAMES}. 64 * @param locale the display JDK locale 65 * @return a LocaleDisplayNames instance 66 * @draft ICU 54 67 * @provisional This API might change or be removed in a future release. 68 */ 69 public static LocaleDisplayNames getInstance(Locale locale) { 70 return getInstance(ULocale.forLocale(locale)); 71 }; 72 73 /** 74 * Returns an instance of LocaleDisplayNames that returns names formatted for the provided locale, 75 * using the provided dialectHandling. 76 * @param locale the display locale 77 * @param dialectHandling how to select names for locales 78 * @return a LocaleDisplayNames instance 79 * @stable ICU 4.4 80 */ 81 public static LocaleDisplayNames getInstance(ULocale locale, DialectHandling dialectHandling) { 82 LocaleDisplayNames result = null; 83 if (FACTORY_DIALECTHANDLING != null) { 84 try { 85 result = (LocaleDisplayNames) FACTORY_DIALECTHANDLING.invoke(null, 86 locale, dialectHandling); 87 } catch (InvocationTargetException e) { 88 // fall through 89 } catch (IllegalAccessException e) { 90 // fall through 91 } 92 } 93 if (result == null) { 94 result = new LastResortLocaleDisplayNames(locale, dialectHandling); 95 } 96 return result; 97 } 98 99 /** 100 * Returns an instance of LocaleDisplayNames that returns names formatted for the provided locale, 101 * using the provided DisplayContext settings 102 * @param locale the display locale 103 * @param contexts one or more context settings (e.g. for dialect 104 * handling, capitalization, etc. 105 * @return a LocaleDisplayNames instance 106 * @stable ICU 51 107 */ 108 public static LocaleDisplayNames getInstance(ULocale locale, DisplayContext... contexts) { 109 LocaleDisplayNames result = null; 110 if (FACTORY_DISPLAYCONTEXT != null) { 111 try { 112 result = (LocaleDisplayNames) FACTORY_DISPLAYCONTEXT.invoke(null, 113 locale, (Object[])contexts); 114 } catch (InvocationTargetException e) { 115 // fall through 116 } catch (IllegalAccessException e) { 117 // fall through 118 } 119 } 120 if (result == null) { 121 result = new LastResortLocaleDisplayNames(locale, contexts); 122 } 123 return result; 124 } 125 126 /** 127 * Returns an instance of LocaleDisplayNames that returns names formatted for the provided JDK 128 * locale, using the provided DisplayContext settings 129 * @param locale the display JDK locale 130 * @param contexts one or more context settings (e.g. for dialect 131 * handling, capitalization, etc. 132 * @return a LocaleDisplayNames instance 133 * @draft ICU 54 134 * @provisional This API might change or be removed in a future release. 135 */ 136 public static LocaleDisplayNames getInstance(Locale locale, DisplayContext... contexts) { 137 return getInstance(ULocale.forLocale(locale), contexts); 138 } 139 140 // getters for state 141 /** 142 * Returns the locale used to determine the display names. This is not necessarily the same 143 * locale passed to {@link #getInstance}. 144 * @return the display locale 145 * @stable ICU 4.4 146 */ 147 public abstract ULocale getLocale(); 148 149 /** 150 * Returns the dialect handling used in the display names. 151 * @return the dialect handling enum 152 * @stable ICU 4.4 153 */ 154 public abstract DialectHandling getDialectHandling(); 155 156 /** 157 * Returns the current value for a specified DisplayContext.Type. 158 * @param type the DisplayContext.Type whose value to return 159 * @return the current DisplayContext setting for the specified type 160 * @stable ICU 51 161 */ 162 public abstract DisplayContext getContext(DisplayContext.Type type); 163 164 // names for entire locales 165 /** 166 * Returns the display name of the provided ulocale. 167 * @param locale the locale whose display name to return 168 * @return the display name of the provided locale 169 * @stable ICU 4.4 170 */ 171 public abstract String localeDisplayName(ULocale locale); 172 173 /** 174 * Returns the display name of the provided locale. 175 * @param locale the locale whose display name to return 176 * @return the display name of the provided locale 177 * @stable ICU 4.4 178 */ 179 public abstract String localeDisplayName(Locale locale); 180 181 /** 182 * Returns the display name of the provided locale id. 183 * @param localeId the id of the locale whose display name to return 184 * @return the display name of the provided locale 185 * @stable ICU 4.4 186 */ 187 public abstract String localeDisplayName(String localeId); 188 189 // names for components of a locale id 190 /** 191 * Returns the display name of the provided language code. 192 * @param lang the language code 193 * @return the display name of the provided language code 194 * @stable ICU 4.4 195 */ 196 public abstract String languageDisplayName(String lang); 197 198 /** 199 * Returns the display name of the provided script code. 200 * @param script the script code 201 * @return the display name of the provided script code 202 * @stable ICU 4.4 203 */ 204 public abstract String scriptDisplayName(String script); 205 206 /** 207 * Returns the display name of the provided script code 208 * when used in the context of a full locale name. 209 * @param script the script code 210 * @return the display name of the provided script code 211 * @internal ICU 49 212 * @deprecated This API is ICU internal only. 213 */ 214 @Deprecated 215 public String scriptDisplayNameInContext(String script) { 216 return scriptDisplayName(script); 217 } 218 219 /** 220 * Returns the display name of the provided script code. See 221 * {@link com.ibm.icu.lang.UScript} for recognized script codes. 222 * @param scriptCode the script code number 223 * @return the display name of the provided script code 224 * @stable ICU 4.4 225 */ 226 public abstract String scriptDisplayName(int scriptCode); 227 228 /** 229 * Returns the display name of the provided region code. 230 * @param region the region code 231 * @return the display name of the provided region code 232 * @stable ICU 4.4 233 */ 234 public abstract String regionDisplayName(String region); 235 236 /** 237 * Returns the display name of the provided variant. 238 * @param variant the variant string 239 * @return the display name of the provided variant 240 * @stable ICU 4.4 241 */ 242 public abstract String variantDisplayName(String variant); 243 244 /** 245 * Returns the display name of the provided locale key. 246 * @param key the locale key name 247 * @return the display name of the provided locale key 248 * @stable ICU 4.4 249 */ 250 public abstract String keyDisplayName(String key); 251 252 /** 253 * Returns the display name of the provided value (used with the provided key). 254 * @param key the locale key name 255 * @param value the locale key's value 256 * @return the display name of the provided value 257 * @stable ICU 4.4 258 */ 259 public abstract String keyValueDisplayName(String key, String value); 260 261 262 /** 263 * Return a list of information used to construct a UI list of locale names. 264 * @param collator how to collate—should normally be Collator.getInstance(getDisplayLocale()) 265 * @param inSelf if true, compares the nameInSelf, otherwise the nameInDisplayLocale. 266 * Set depending on which field (displayLocale vs self) is to show up in the UI. 267 * If both are to show up in the UI, then it should be the one used for the primary sort order. 268 * @param localeSet a list of locales to present in a UI list. The casing uses the settings in the LocaleDisplayNames instance. 269 * @return an ordered list of UiListItems. 270 * @throws IllformedLocaleException if any of the locales in localeSet are malformed. 271 * @draft ICU 55 272 * @provisional This API might change or be removed in a future release. 273 */ 274 public List<UiListItem> getUiList(Set<ULocale> localeSet, boolean inSelf, Comparator<Object> collator) { 275 return getUiListCompareWholeItems(localeSet, UiListItem.getComparator(collator, inSelf)); 276 } 277 278 /** 279 * Return a list of information used to construct a UI list of locale names, providing more access to control the sorting. 280 * Normally use getUiList instead. 281 * @param comparator how to sort the UiListItems in the result. 282 * @param localeSet a list of locales to present in a UI list. The casing uses the settings in the LocaleDisplayNames instance. 283 * @return an ordered list of UiListItems. 284 * @throws IllformedLocaleException if any of the locales in localeSet are malformed. 285 * @draft ICU 55 286 * @provisional This API might change or be removed in a future release. 287 */ 288 public abstract List<UiListItem> getUiListCompareWholeItems(Set<ULocale> localeSet, Comparator<UiListItem> comparator); 289 290 /** 291 * Struct-like class used to return information for constructing a UI list, each corresponding to a locale. 292 * @draft ICU 55 293 * @provisional This API might change or be removed in a future release. 294 */ 295 public static class UiListItem { 296 /** 297 * Returns the minimized locale for an input locale, such as sr-Cyrl → sr 298 * @draft ICU 55 299 * @provisional This API might change or be removed in a future release. 300 */ 301 public final ULocale minimized; 302 /** 303 * Returns the modified locale for an input locale, such as sr → sr-Cyrl, where there is also an sr-Latn in the list 304 * @draft ICU 55 305 * @provisional This API might change or be removed in a future release. 306 */ 307 public final ULocale modified; 308 /** 309 * Returns the name of the modified locale in the display locale, such as "Englisch (VS)" (for 'en-US', where the display locale is 'de'). 310 * @draft ICU 55 311 * @provisional This API might change or be removed in a future release. 312 */ 313 public final String nameInDisplayLocale; 314 /** 315 * Returns the name of the modified locale in itself, such as "English (US)" (for 'en-US'). 316 * @draft ICU 55 317 * @provisional This API might change or be removed in a future release. 318 */ 319 public final String nameInSelf; 320 321 /** 322 * Constructor, normally only called internally. 323 * @param minimized locale for an input locale 324 * @param modified modified for an input locale 325 * @param nameInDisplayLocale name of the modified locale in the display locale 326 * @param nameInSelf name of the modified locale in itself 327 * @draft ICU 55 328 * @provisional This API might change or be removed in a future release. 329 */ 330 public UiListItem(ULocale minimized, ULocale modified, String nameInDisplayLocale, String nameInSelf) { 331 this.minimized = minimized; 332 this.modified = modified; 333 this.nameInDisplayLocale = nameInDisplayLocale; 334 this.nameInSelf = nameInSelf; 335 } 336 337 /** 338 * {@inheritDoc} 339 * 340 * @draft ICU 55 341 * @provisional This API might change or be removed in a future release. 342 */ 343 @Override 344 public boolean equals(Object obj) { 345 UiListItem other = (UiListItem)obj; 346 return nameInDisplayLocale.equals(other.nameInDisplayLocale) 347 && nameInSelf.equals(other.nameInSelf) 348 && minimized.equals(other.minimized) 349 && modified.equals(other.modified); 350 } 351 352 /** 353 * {@inheritDoc} 354 * 355 * @draft ICU 55 356 * @provisional This API might change or be removed in a future release. 357 */ 358 @Override 359 public int hashCode() { 360 return modified.hashCode() ^ nameInDisplayLocale.hashCode(); 361 } 362 363 /** 364 * {@inheritDoc} 365 * 366 * @draft ICU 55 367 * @provisional This API might change or be removed in a future release. 368 */ 369 @Override 370 public String toString() { 371 return "{" + minimized + ", " + modified + ", " + nameInDisplayLocale + ", " + nameInSelf + "}"; 372 } 373 374 /** 375 * Return a comparator that compares the locale names for the display locale or the in-self names, 376 * depending on an input parameter. 377 * @param inSelf if true, compares the nameInSelf, otherwise the nameInDisplayLocale 378 * @param comparator (meant for strings, but because Java Collator doesn't have <String>...) 379 * @return UiListItem comparator 380 * @draft ICU 55 381 * @provisional This API might change or be removed in a future release. 382 */ 383 public static Comparator<UiListItem> getComparator(Comparator<Object> comparator, boolean inSelf) { 384 return new UiListItemComparator(comparator, inSelf); 385 } 386 387 private static class UiListItemComparator implements Comparator<UiListItem> { 388 private final Comparator<Object> collator; 389 private final boolean useSelf; 390 UiListItemComparator(Comparator<Object> collator, boolean useSelf) { 391 this.collator = collator; 392 this.useSelf = useSelf; 393 } 394 public int compare(UiListItem o1, UiListItem o2) { 395 int result = useSelf ? collator.compare(o1.nameInSelf, o2.nameInSelf) 396 : collator.compare(o1.nameInDisplayLocale, o2.nameInDisplayLocale); 397 return result != 0 ? result : o1.modified.compareTo(o2.modified); // just in case 398 } 399 } 400 } 401 /** 402 * Sole constructor. (For invocation by subclass constructors, 403 * typically implicit.) 404 * @internal 405 * @deprecated This API is ICU internal only. 406 */ 407 @Deprecated 408 protected LocaleDisplayNames() { 409 } 410 411 private static final Method FACTORY_DIALECTHANDLING; 412 private static final Method FACTORY_DISPLAYCONTEXT; 413 414 static { 415 String implClassName = ICUConfig.get("com.ibm.icu.text.LocaleDisplayNames.impl", "com.ibm.icu.impl.LocaleDisplayNamesImpl"); 416 417 Method factoryDialectHandling = null; 418 Method factoryDisplayContext = null; 419 420 try { 421 Class<?> implClass = Class.forName(implClassName); 422 try { 423 factoryDialectHandling = implClass.getMethod("getInstance", 424 ULocale.class, DialectHandling.class); 425 } catch (NoSuchMethodException e) { 426 } 427 try { 428 factoryDisplayContext = implClass.getMethod("getInstance", 429 ULocale.class, DisplayContext[].class); 430 } catch (NoSuchMethodException e) { 431 } 432 433 } catch (ClassNotFoundException e) { 434 // fallback to last resort impl 435 } 436 437 FACTORY_DIALECTHANDLING = factoryDialectHandling; 438 FACTORY_DISPLAYCONTEXT = factoryDisplayContext; 439 } 440 441 /** 442 * Minimum implementation of LocaleDisplayNames 443 */ 444 private static class LastResortLocaleDisplayNames extends LocaleDisplayNames { 445 446 private ULocale locale; 447 private DisplayContext[] contexts; 448 449 private LastResortLocaleDisplayNames(ULocale locale, DialectHandling dialectHandling) { 450 this.locale = locale; 451 DisplayContext context = (dialectHandling == DialectHandling.DIALECT_NAMES) ? 452 DisplayContext.DIALECT_NAMES : DisplayContext.STANDARD_NAMES; 453 this.contexts = new DisplayContext[] {context}; 454 } 455 456 private LastResortLocaleDisplayNames(ULocale locale, DisplayContext... contexts) { 457 this.locale = locale; 458 this.contexts = new DisplayContext[contexts.length]; 459 System.arraycopy(contexts, 0, this.contexts, 0, contexts.length); 460 } 461 462 @Override 463 public ULocale getLocale() { 464 return locale; 465 } 466 467 @Override 468 public DialectHandling getDialectHandling() { 469 DialectHandling result = DialectHandling.STANDARD_NAMES; 470 for (DisplayContext context : contexts) { 471 if (context.type() == DisplayContext.Type.DIALECT_HANDLING) { 472 if (context.value() == DisplayContext.DIALECT_NAMES.ordinal()) { 473 result = DialectHandling.DIALECT_NAMES; 474 break; 475 } 476 } 477 } 478 return result; 479 } 480 481 @Override 482 public DisplayContext getContext(Type type) { 483 DisplayContext result = DisplayContext.STANDARD_NAMES; // final fallback 484 for (DisplayContext context : contexts) { 485 if (context.type() == type) { 486 result = context; 487 break; 488 } 489 } 490 return result; 491 } 492 493 @Override 494 public String localeDisplayName(ULocale locale) { 495 return locale.getName(); 496 } 497 498 @Override 499 public String localeDisplayName(Locale locale) { 500 return ULocale.forLocale(locale).getName(); 501 } 502 503 @Override 504 public String localeDisplayName(String localeId) { 505 return new ULocale(localeId).getName(); 506 } 507 508 @Override 509 public String languageDisplayName(String lang) { 510 return lang; 511 } 512 513 @Override 514 public String scriptDisplayName(String script) { 515 return script; 516 } 517 518 @Override 519 public String scriptDisplayName(int scriptCode) { 520 return UScript.getShortName(scriptCode); 521 } 522 523 @Override 524 public String regionDisplayName(String region) { 525 return region; 526 } 527 528 @Override 529 public String variantDisplayName(String variant) { 530 return variant; 531 } 532 533 @Override 534 public String keyDisplayName(String key) { 535 return key; 536 } 537 538 @Override 539 public String keyValueDisplayName(String key, String value) { 540 return value; 541 } 542 543 @Override 544 public List<UiListItem> getUiListCompareWholeItems(Set<ULocale> localeSet, Comparator<UiListItem> comparator) { 545 return Collections.emptyList(); 546 } 547 } 548} 549