12d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert// © 2016 and later: Unicode, Inc. and others. 22d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert// License & terms of use: http://www.unicode.org/copyright.html#License 37935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/** 47935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert******************************************************************************* 52d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert* Copyright (C) 2003-2016, International Business Machines Corporation and 67935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert* others. All Rights Reserved. 77935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert******************************************************************************* 87935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert*/ 97935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpackage com.ibm.icu.text; 117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Locale; 137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.MissingResourceException; 147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Set; 157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 162d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubertimport com.ibm.icu.impl.ICUData; 177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.impl.ICULocaleService; 187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.impl.ICULocaleService.LocaleKeyFactory; 197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.impl.ICUResourceBundle; 207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.impl.ICUService; 217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.impl.ICUService.Factory; 227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.impl.coll.CollationLoader; 237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.impl.coll.CollationTailoring; 247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.text.Collator.CollatorFactory; 257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.util.ICUCloneNotSupportedException; 267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.util.Output; 277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.util.ULocale; 287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertfinal class CollatorServiceShim extends Collator.ServiceShim { 307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 312d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert @Override 327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Collator getInstance(ULocale locale) { 337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // use service cache, it's faster than instantiation 347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// if (service.isDefault()) { 357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// return new RuleBasedCollator(locale); 367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// } 377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert try { 387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ULocale[] actualLoc = new ULocale[1]; 397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Collator coll = (Collator)service.get(locale, actualLoc); 407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (coll == null) { 417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ///CLOVER:OFF 427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert //Can't really change coll after it's been initialized 437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new MissingResourceException("Could not locate Collator data", "", ""); 447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ///CLOVER:ON 457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return (Collator) coll.clone(); 477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert catch (CloneNotSupportedException e) { 497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ///CLOVER:OFF 507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new ICUCloneNotSupportedException(e); 517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ///CLOVER:ON 527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 552d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert @Override 567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Object registerInstance(Collator collator, ULocale locale) { 577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Set the collator locales while registering so that getInstance() 587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // need not guess whether the collator's locales are already set properly 597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // (as they are by the data loader). 607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert collator.setLocale(locale, locale); 617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return service.registerObject(collator, locale); 627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 642d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert @Override 657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Object registerFactory(CollatorFactory f) { 667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert class CFactory extends LocaleKeyFactory { 677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert CollatorFactory delegate; 687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert CFactory(CollatorFactory fctry) { 707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert super(fctry.visible()); 717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this.delegate = fctry; 727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 742d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert @Override 757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public Object handleCreate(ULocale loc, int kind, ICUService srvc) { 767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Object coll = delegate.createCollator(loc); 777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return coll; 787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 802d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert @Override 817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public String getDisplayName(String id, ULocale displayLocale) { 827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ULocale objectLocale = new ULocale(id); 837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return delegate.getDisplayName(objectLocale, displayLocale); 847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 862d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert @Override 877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public Set<String> getSupportedIDs() { 887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return delegate.getSupportedLocaleIDs(); 897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return service.registerFactory(new CFactory(f)); 937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 952d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert @Override 967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boolean unregister(Object registryKey) { 977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return service.unregisterFactory((Factory)registryKey); 987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1002d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert @Override 1017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Locale[] getAvailableLocales() { 1027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // TODO rewrite this to just wrap getAvailableULocales later 1037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Locale[] result; 1047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (service.isDefault()) { 1052d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert result = ICUResourceBundle.getAvailableLocales(ICUData.ICU_COLLATION_BASE_NAME, 1067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ICUResourceBundle.ICU_DATA_CLASS_LOADER); 1077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 1087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result = service.getAvailableLocales(); 1097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return result; 1117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1132d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert @Override 1147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ULocale[] getAvailableULocales() { 1157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ULocale[] result; 1167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (service.isDefault()) { 1172d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert result = ICUResourceBundle.getAvailableULocales(ICUData.ICU_COLLATION_BASE_NAME, 1187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ICUResourceBundle.ICU_DATA_CLASS_LOADER); 1197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 1207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert result = service.getAvailableULocales(); 1217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return result; 1237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1252d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert @Override 1267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String getDisplayName(ULocale objectLocale, ULocale displayLocale) { 1277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert String id = objectLocale.getName(); 1287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return service.getDisplayName(id, displayLocale); 1297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static class CService extends ICULocaleService { 1327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert CService() { 1337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert super("Collator"); 1347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert class CollatorFactory extends ICUResourceBundleFactory { 1367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert CollatorFactory() { 1372d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert super(ICUData.ICU_COLLATION_BASE_NAME); 1387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 140f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert @Override 1417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert protected Object handleCreate(ULocale uloc, int kind, ICUService srvc) { 1427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return makeInstance(uloc); 1437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this.registerFactory(new CollatorFactory()); 1477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert markDefault(); 1487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 149f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert 150f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert /** 151f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert * makeInstance() returns an appropriate Collator for any locale. 152f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert * It falls back to root if there is no specific data. 153f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert * 154f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert * <p>Without this override, the service code would fall back to the default locale 155f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert * which is not desirable for an algorithm with a good Unicode default, 156f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert * like collation. 157f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert */ 158f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert @Override 159f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert public String validateFallbackLocale() { 160f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert return ""; 161f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert } 162f716bda031dccdec5e47bb40e758c5901d209729Fredrik Roubert 1637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ///CLOVER:OFF 1647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // The following method can not be reached by testing 1652d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert @Override 1667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert protected Object handleDefault(Key key, String[] actualIDReturn) { 1677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (actualIDReturn != null) { 1687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert actualIDReturn[0] = "root"; 1697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert try { 1717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return makeInstance(ULocale.ROOT); 1727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert catch (MissingResourceException e) { 1747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return null; 1757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ///CLOVER:ON 1787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Ported from C++ Collator::makeInstance(). 1817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static final Collator makeInstance(ULocale desiredLocale) { 1827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Output<ULocale> validLocale = new Output<ULocale>(ULocale.ROOT); 1837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert CollationTailoring t = 1847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert CollationLoader.loadTailoring(desiredLocale, validLocale); 1857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return new RuleBasedCollator(t, validLocale.value); 1867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private static ICULocaleService service = new CService(); 1897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert} 190