mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-21 12:40:02 +00:00
ICU-2203 registration for calendar, breakiterator
X-SVN-Rev: 9948
This commit is contained in:
parent
c9cf5f3592
commit
a90995824f
18 changed files with 1116 additions and 702 deletions
|
@ -5,15 +5,17 @@
|
|||
*******************************************************************************
|
||||
*
|
||||
* $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/dev/test/calendar/CalendarRegression.java,v $
|
||||
* $Date: 2002/08/13 21:53:38 $
|
||||
* $Revision: 1.12 $
|
||||
* $Date: 2002/10/02 20:20:26 $
|
||||
* $Revision: 1.13 $
|
||||
*
|
||||
*******************************************************************************
|
||||
*/
|
||||
package com.ibm.icu.dev.test.calendar;
|
||||
import com.ibm.icu.util.*;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import com.ibm.icu.lang.*;
|
||||
import com.ibm.icu.text.*;
|
||||
|
||||
|
@ -705,6 +707,7 @@ public class CalendarRegression extends com.ibm.icu.dev.test.TestFmwk {
|
|||
|
||||
public void Test4106136() {
|
||||
Locale saveLocale = Locale.getDefault();
|
||||
String[] names = { "Calendar", "DateFormat", "NumberFormat" };
|
||||
try {
|
||||
Locale[] locales = { Locale.CHINESE, Locale.CHINA };
|
||||
for (int i=0; i<locales.length; ++i) {
|
||||
|
@ -716,7 +719,7 @@ public class CalendarRegression extends com.ibm.icu.dev.test.TestFmwk {
|
|||
};
|
||||
for (int j=0; j<n.length; ++j) {
|
||||
if (n[j] == 0)
|
||||
errln("Fail: No locales for " + locales[i]);
|
||||
errln("Fail: " + names[j] + " has no locales for " + locales[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1834,6 +1837,49 @@ public class CalendarRegression extends com.ibm.icu.dev.test.TestFmwk {
|
|||
TimeZone.setDefault(zone);
|
||||
}
|
||||
}
|
||||
|
||||
public void TestRegistration() {
|
||||
Set names = Calendar.getCalendarFactoryNames();
|
||||
|
||||
TimeZone tz = TimeZone.getDefault();
|
||||
Locale loc = Locale.getDefault();
|
||||
Iterator iter = names.iterator();
|
||||
while (iter.hasNext()) {
|
||||
String name = (String)iter.next();
|
||||
logln("Testing factory: " + name);
|
||||
|
||||
Calendar cal = Calendar.getInstance(tz, loc, name);
|
||||
logln("Calendar class: " + cal.getClass());
|
||||
|
||||
DateFormat fmt = cal.getDateTimeFormat(DateFormat.LONG, DateFormat.LONG, loc);
|
||||
|
||||
logln("Date: " + fmt.format(cal.getTime()));
|
||||
}
|
||||
|
||||
// register new default for our locale
|
||||
logln("\nTesting registration");
|
||||
loc = new Locale("en", "US");
|
||||
Object key = Calendar.register(JapaneseCalendar.factory(), loc, true);
|
||||
|
||||
loc = new Locale("en", "US", "TEST");
|
||||
Calendar cal = Calendar.getInstance(loc);
|
||||
logln("Calendar class: " + cal.getClass());
|
||||
DateFormat fmt = cal.getDateTimeFormat(DateFormat.LONG, DateFormat.LONG, loc);
|
||||
logln("Date: " + fmt.format(cal.getTime()));
|
||||
|
||||
// force to use other default anyway
|
||||
logln("\nOverride registration");
|
||||
cal = Calendar.getInstance(tz, loc, "Gregorian");
|
||||
fmt = cal.getDateTimeFormat(DateFormat.LONG, DateFormat.LONG, loc);
|
||||
logln("Date: " + fmt.format(cal.getTime()));
|
||||
|
||||
// unregister default
|
||||
logln("\nUnregistration");
|
||||
logln("Unregister returned: " + Calendar.unregister(key));
|
||||
cal = Calendar.getInstance(tz, loc, "Gregorian");
|
||||
fmt = cal.getDateTimeFormat(DateFormat.LONG, DateFormat.LONG, loc);
|
||||
logln("Date: " + fmt.format(cal.getTime()));
|
||||
}
|
||||
}
|
||||
|
||||
//eof
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
*******************************************************************************
|
||||
*
|
||||
* $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/dev/test/util/ICUServiceTest.java,v $
|
||||
* $Date: 2002/09/14 21:36:30 $
|
||||
* $Revision: 1.5 $
|
||||
* $Date: 2002/10/02 20:20:25 $
|
||||
* $Revision: 1.6 $
|
||||
*
|
||||
*******************************************************************************
|
||||
*/
|
||||
|
@ -24,10 +24,11 @@ import com.ibm.icu.impl.LocaleUtility;
|
|||
import com.ibm.icu.impl.ICULocaleData;
|
||||
import com.ibm.icu.impl.ICULocaleService;
|
||||
import com.ibm.icu.impl.ICULocaleService.LocaleKey;
|
||||
import com.ibm.icu.impl.ICULocaleService.MultipleKeyFactory;
|
||||
import com.ibm.icu.impl.ICULocaleService.LocaleKeyFactory;
|
||||
import com.ibm.icu.impl.ICULocaleService.ICUResourceBundleFactory;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.EventListener;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
@ -69,7 +70,7 @@ public class ICUServiceTest extends TestFmwk
|
|||
|
||||
// use locale keys
|
||||
static final class TestService extends ICUService {
|
||||
protected Key createKey(String id) {
|
||||
public Key createKey(String id) {
|
||||
return LocaleKey.createWithCanonicalFallback(id, null); // no fallback locale
|
||||
}
|
||||
}
|
||||
|
@ -203,7 +204,7 @@ public class ICUServiceTest extends TestFmwk
|
|||
"en_US_SURFER_GAL",
|
||||
"en_US_SURFER_DUDE"
|
||||
};
|
||||
service.registerFactory(new TestMultipleFactory(xids));
|
||||
service.registerFactory(new TestLocaleKeyFactory(xids));
|
||||
}
|
||||
|
||||
// iterate over the visual ids returned by the multiple factory
|
||||
|
@ -246,7 +247,7 @@ public class ICUServiceTest extends TestFmwk
|
|||
String[] xids = {
|
||||
"en_US_SURFER_GAL", "en_US_SILICON", "en_US_SILICON_GEEK", "en_US"
|
||||
};
|
||||
service.registerFactory(new TestMultipleFactory(xids, "Rad dude"));
|
||||
service.registerFactory(new TestLocaleKeyFactory(xids, "Rad dude"));
|
||||
}
|
||||
|
||||
// this time, we have seven display names (we replaced surfer gal)
|
||||
|
@ -332,10 +333,9 @@ public class ICUServiceTest extends TestFmwk
|
|||
|
||||
// resource bundle factory.
|
||||
service.reset();
|
||||
service.registerFactory(new ICUResourceBundleFactory("Countries;Languages", true));
|
||||
service.registerFactory(new ICUResourceBundleFactory());
|
||||
|
||||
// list all of the resources that really define Countries;Languages
|
||||
// this takes a long time to build the visible id list
|
||||
// list all of the resources
|
||||
{
|
||||
Set xids = service.getVisibleIDs();
|
||||
StringBuffer buf = new StringBuffer("{");
|
||||
|
@ -453,16 +453,18 @@ public class ICUServiceTest extends TestFmwk
|
|||
}
|
||||
|
||||
|
||||
static class TestMultipleFactory extends MultipleKeyFactory {
|
||||
protected final String[] ids;
|
||||
static class TestLocaleKeyFactory extends LocaleKeyFactory {
|
||||
protected final Set ids;
|
||||
protected final String factoryID;
|
||||
|
||||
public TestMultipleFactory(String[] ids) {
|
||||
public TestLocaleKeyFactory(String[] ids) {
|
||||
this(ids, "");
|
||||
}
|
||||
|
||||
public TestMultipleFactory(String[] ids, String factoryID) {
|
||||
this.ids = (String[])ids.clone();
|
||||
public TestLocaleKeyFactory(String[] ids, String factoryID) {
|
||||
super(VISIBLE_COVERS);
|
||||
|
||||
this.ids = Collections.unmodifiableSet(new HashSet(Arrays.asList(ids)));
|
||||
|
||||
if (factoryID == null || factoryID.length() == 0) {
|
||||
this.factoryID = "";
|
||||
|
@ -471,21 +473,12 @@ public class ICUServiceTest extends TestFmwk
|
|||
}
|
||||
}
|
||||
|
||||
protected Object handleCreate(Key key) {
|
||||
for (int i = 0; i < ids.length; ++i) {
|
||||
if (key.currentID().equalsIgnoreCase(ids[i])) {
|
||||
return factoryID + key.canonicalID();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
protected Object handleCreate(Locale loc, int kind) {
|
||||
return factoryID + loc.toString();
|
||||
}
|
||||
|
||||
protected Set handleGetSupportedIDs() {
|
||||
return new HashSet(Arrays.asList(ids));
|
||||
}
|
||||
|
||||
protected String handleGetDisplayName(String id, Locale locale) {
|
||||
return factoryID + LocaleUtility.getLocaleFromName(id).getDisplayName(locale);
|
||||
protected Set getSupportedIDs() {
|
||||
return ids;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -535,27 +528,26 @@ public class ICUServiceTest extends TestFmwk
|
|||
}
|
||||
|
||||
static class CalifornioLanguageFactory extends ICUResourceBundleFactory {
|
||||
CalifornioLanguageFactory() {
|
||||
super("Countries;Languages", true);
|
||||
}
|
||||
|
||||
private static String californio = "en_US_CA";
|
||||
private static String valley = californio + "_VALLEY";
|
||||
private static String surfer = californio + "_SURFER";
|
||||
private static String geek = californio + "_GEEK";
|
||||
|
||||
public Set handleGetSupportedIDs() {
|
||||
Set result = super.handleGetSupportedIDs();
|
||||
|
||||
private static Set supportedIDs;
|
||||
static {
|
||||
HashSet result = new HashSet();
|
||||
result.addAll(ICULocaleData.getAvailableLocaleNameSet());
|
||||
result.add(californio);
|
||||
result.add(valley);
|
||||
result.add(surfer);
|
||||
result.add(geek);
|
||||
supportedIDs = Collections.unmodifiableSet(result);
|
||||
}
|
||||
|
||||
return result;
|
||||
public Set getSupportedIDs() {
|
||||
return supportedIDs;
|
||||
}
|
||||
|
||||
protected String handleGetDisplayName(String id, Locale locale) {
|
||||
public String getDisplayName(String id, Locale locale) {
|
||||
String prefix = "";
|
||||
String suffix = "";
|
||||
String ls = locale.toString();
|
||||
|
@ -581,7 +573,7 @@ public class ICUServiceTest extends TestFmwk
|
|||
suffix = "No Habla Englais";
|
||||
}
|
||||
} else {
|
||||
suffix = super.handleGetDisplayName(id, locale);
|
||||
suffix = super.getDisplayName(id, locale);
|
||||
}
|
||||
|
||||
return prefix + suffix;
|
||||
|
@ -624,7 +616,6 @@ public class ICUServiceTest extends TestFmwk
|
|||
|
||||
public void errln(String msg) {
|
||||
System.out.println(msg);
|
||||
(new String[0])[1] = "foo";
|
||||
}
|
||||
|
||||
// misc coverage tests
|
||||
|
@ -730,26 +721,21 @@ public class ICUServiceTest extends TestFmwk
|
|||
// lkey = LocaleKey.create(null, null);
|
||||
LocaleKey lkey = LocaleKey.createWithCanonicalFallback("en_US", "ja_JP");
|
||||
|
||||
// MultipleKeyFactory
|
||||
MultipleKeyFactory mkf = new MKFSubclass(false);
|
||||
logln("obj: " + mkf.create(lkey));
|
||||
logln(mkf.getDisplayName("foo", null));
|
||||
logln(mkf.getDisplayName("bar", null));
|
||||
mkf.updateVisibleIDs(new HashMap());
|
||||
// LocaleKeyFactory
|
||||
LocaleKeyFactory lkf = new LKFSubclass(false);
|
||||
logln("obj: " + lkf.create(lkey));
|
||||
logln(lkf.getDisplayName("foo", null));
|
||||
logln(lkf.getDisplayName("bar", null));
|
||||
lkf.updateVisibleIDs(new HashMap());
|
||||
|
||||
MultipleKeyFactory invisibleMKF = new MKFSubclass(false);
|
||||
logln("obj: " + invisibleMKF.create(lkey));
|
||||
logln(invisibleMKF.getDisplayName("foo", null));
|
||||
logln(invisibleMKF.getDisplayName("bar", null));
|
||||
invisibleMKF.updateVisibleIDs(new HashMap());
|
||||
LocaleKeyFactory invisibleLKF = new LKFSubclass(false);
|
||||
logln("obj: " + invisibleLKF.create(lkey));
|
||||
logln(invisibleLKF.getDisplayName("foo", null));
|
||||
logln(invisibleLKF.getDisplayName("bar", null));
|
||||
invisibleLKF.updateVisibleIDs(new HashMap());
|
||||
|
||||
// ResourceBundleFactory
|
||||
ICUResourceBundleFactory rbf = new ICUResourceBundleFactory(true);
|
||||
logln("RB: " + rbf.create(lkey));
|
||||
// LocaleKey nokey = LocaleKey.create(null, null);
|
||||
// logln("RB: " + rbf.create(nokey));
|
||||
|
||||
rbf = new ICUResourceBundleFactory("foobar", true);
|
||||
ICUResourceBundleFactory rbf = new ICUResourceBundleFactory();
|
||||
logln("RB: " + rbf.create(lkey));
|
||||
|
||||
// ICUNotifier
|
||||
|
@ -813,17 +799,17 @@ public class ICUServiceTest extends TestFmwk
|
|||
}
|
||||
}
|
||||
|
||||
static class MKFSubclass extends MultipleKeyFactory {
|
||||
MKFSubclass(boolean visible) {
|
||||
super(visible);
|
||||
static class LKFSubclass extends LocaleKeyFactory {
|
||||
LKFSubclass(boolean visible) {
|
||||
super(visible ? VISIBLE : INVISIBLE);
|
||||
}
|
||||
|
||||
public Object handleCreate(Key key) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Set handleGetSupportedIDs() {
|
||||
return null;
|
||||
protected Set getSupportedIDs() {
|
||||
return Collections.EMPTY_SET;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
*******************************************************************************
|
||||
*
|
||||
* $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/dev/test/util/ICUServiceThreadTest.java,v $
|
||||
* $Date: 2002/08/13 22:10:20 $
|
||||
* $Revision: 1.4 $
|
||||
* $Date: 2002/10/02 20:20:25 $
|
||||
* $Revision: 1.5 $
|
||||
*
|
||||
*******************************************************************************
|
||||
*/
|
||||
|
@ -22,7 +22,6 @@ import com.ibm.icu.impl.LocaleUtility;
|
|||
import com.ibm.icu.impl.ICULocaleData;
|
||||
import com.ibm.icu.impl.ICULocaleService;
|
||||
import com.ibm.icu.impl.ICULocaleService.LocaleKey;
|
||||
import com.ibm.icu.impl.ICULocaleService.MultipleKeyFactory;
|
||||
import com.ibm.icu.impl.ICULocaleService.ICUResourceBundleFactory;
|
||||
import java.util.Arrays;
|
||||
import java.util.ArrayList;
|
||||
|
|
|
@ -4,10 +4,16 @@
|
|||
|
||||
package com.ibm.icu.impl;
|
||||
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.util.Locale;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Provides information about and access to resource bundles in the
|
||||
|
@ -23,6 +29,9 @@ public class ICULocaleData {
|
|||
|
||||
/**
|
||||
* Returns a list of the installed locales.
|
||||
*
|
||||
* The following note by Rich is obsolete, see below. -- dlf 01 Oct. 2002
|
||||
* -----
|
||||
* @param key A resource tag. Currently, this parameter is ignored. The obvious
|
||||
* intent, however, is for getAvailableLocales() to return a list of only those
|
||||
* locales that contain a resource with the specified resource tag.
|
||||
|
@ -35,7 +44,7 @@ public class ICULocaleData {
|
|||
* inheriting one from another locale. Thus, if fr and fr_CA uniquely define
|
||||
* NumberFormat data, but fr_BE doesn't, the user wouldn't see "French (Belgium)" in
|
||||
* the list and would go for "French (default)" instead. Of course, this means
|
||||
* "English (United States)" would not be in the list, since it is the default locale.
|
||||
* "Engish (United States)" would not be in the list, since it is the default locale.
|
||||
* This might be okay, but might be confusing to some users.
|
||||
*
|
||||
* <p>In addition, the other functions that call getAvailableLocales() don't currently
|
||||
|
@ -44,28 +53,97 @@ public class ICULocaleData {
|
|||
*
|
||||
* <p>We recommend that someone take some careful consideration of these issues before
|
||||
* modifying this function to pay attention to the "key" parameter. --rtg 1/26/98
|
||||
* -----
|
||||
*
|
||||
* Return a list of the locales supported by a collection of resource bundles.
|
||||
* All ICULocaleData-based services that use a particular resource bundle support
|
||||
* all the locales from that bundle. If support for a particular service is spotty,
|
||||
* a different bundle prefix should be used for that service.
|
||||
* @param bundlePrefix the prefix of the resource bundles to use.
|
||||
*/
|
||||
public static Locale[] getAvailableLocales(String key) {
|
||||
// ignore key, just return all locales
|
||||
return getAvailableLocales();
|
||||
public static Locale[] getAvailableLocales(String bundlePrefix) {
|
||||
return (Locale[])getAvailEntry(bundlePrefix).getLocaleList().clone();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return an array of all the locales for which we have resource information.
|
||||
* Convenience method that returns a list of all the avilable LOCALE_ELEMENTS locales.
|
||||
*/
|
||||
public static Locale[] getAvailableLocales() {
|
||||
// creating the locale list is expensive, so be careful to do it
|
||||
// only once
|
||||
if (localeList == null) {
|
||||
synchronized(ICULocaleData.class) {
|
||||
if (localeList == null) {
|
||||
localeList = createLocaleList();
|
||||
}
|
||||
return getAvailableLocales(LOCALE_ELEMENTS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a set of the locale names supported by a collection of resource bundles.
|
||||
* @param bundlePrefix the prefix of the resource bundles to use.
|
||||
*/
|
||||
public static Set getAvailableLocaleNameSet(String bundlePrefix) {
|
||||
return getAvailEntry(bundlePrefix).getLocaleNameSet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a set of the locale names supported by a collection of resource bundles.
|
||||
* @param bundlePrefix the prefix of the resource bundles to use.
|
||||
*/
|
||||
public static Set getAvailableLocaleNameSet() {
|
||||
return getAvailableLocaleNameSet(LOCALE_ELEMENTS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds the prefix, and lazily creates the Locale[] list or the locale name Set as needed.
|
||||
*/
|
||||
private static final class AvailEntry {
|
||||
private String prefix;
|
||||
private Locale[] locales;
|
||||
private Set nameSet;
|
||||
|
||||
AvailEntry(String prefix) {
|
||||
this.prefix = prefix;
|
||||
}
|
||||
|
||||
Locale[] getLocaleList() {
|
||||
if (locales == null) {
|
||||
locales = createLocaleList(prefix);
|
||||
}
|
||||
return locales;
|
||||
}
|
||||
|
||||
Set getLocaleNameSet() {
|
||||
if (nameSet == null) {
|
||||
nameSet = createLocaleNameSet(prefix);
|
||||
}
|
||||
return nameSet;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the locale information in a cache accessed by key (bundle prefix). The
|
||||
* cached objects are AvailEntries. The cache is held by a SoftReference
|
||||
* so it can be GC'd.
|
||||
*/
|
||||
private static AvailEntry getAvailEntry(String key) {
|
||||
AvailEntry ae = null;
|
||||
Map lcache = null;
|
||||
if (lcacheref != null) {
|
||||
lcache = (Map)lcacheref.get();
|
||||
if (lcache != null) {
|
||||
ae = (AvailEntry)lcache.get(key);
|
||||
}
|
||||
}
|
||||
|
||||
return (Locale[])localeList.clone();
|
||||
if (ae == null) {
|
||||
ae = new AvailEntry(key);
|
||||
if (lcache == null) {
|
||||
lcache = new HashMap();
|
||||
lcache.put(key, ae);
|
||||
lcacheref = new SoftReference(lcache);
|
||||
} else {
|
||||
lcache.put(key, ae);
|
||||
}
|
||||
}
|
||||
|
||||
return ae;
|
||||
}
|
||||
private static SoftReference lcacheref;
|
||||
|
||||
/**
|
||||
* The default name for resources containing ICU locale data.
|
||||
|
@ -218,10 +296,33 @@ public class ICULocaleData {
|
|||
|
||||
// ========== privates ==========
|
||||
|
||||
|
||||
private static Locale[] createLocaleList() {
|
||||
private static Set createLocaleNameSet(String bundleName) {
|
||||
try {
|
||||
ResourceBundle index = getLocaleElements(LocaleUtility.getLocaleFromName("index"));
|
||||
ResourceBundle index = getResourceBundle(bundleName, "index");
|
||||
String[] localeNames = index.getStringArray("InstalledLocales");
|
||||
|
||||
// barf gag choke spit hack...
|
||||
// since java's Locale 'fixes' the locale string for some locales,
|
||||
// we have to fix our names to match, otherwise the Locale[] list
|
||||
// won't match the locale name set. What were they thinking?!?
|
||||
for (int i = 0; i < localeNames.length; ++i) {
|
||||
localeNames[i] = LocaleUtility.getLocaleFromName(localeNames[i]).toString();
|
||||
}
|
||||
|
||||
HashSet set = new HashSet();
|
||||
set.addAll(Arrays.asList(localeNames));
|
||||
return Collections.unmodifiableSet(set);
|
||||
}
|
||||
catch (MissingResourceException e) {
|
||||
System.out.println("couldn't find index for bundleName: " + bundleName);
|
||||
Thread.dumpStack();
|
||||
}
|
||||
return Collections.EMPTY_SET;
|
||||
}
|
||||
|
||||
private static Locale[] createLocaleList(String bundleName) {
|
||||
try {
|
||||
ResourceBundle index = getResourceBundle(bundleName, "index");
|
||||
String[] localeNames = index.getStringArray("InstalledLocales");
|
||||
Locale[] locales = new Locale[localeNames.length];
|
||||
for (int i = 0; i < localeNames.length; ++i) {
|
||||
|
@ -230,8 +331,9 @@ public class ICULocaleData {
|
|||
return locales;
|
||||
}
|
||||
catch (MissingResourceException e) {
|
||||
System.out.println("couldn't find index for bundleName: " + bundleName);
|
||||
Thread.dumpStack();
|
||||
}
|
||||
|
||||
return new Locale[0];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
*******************************************************************************
|
||||
*
|
||||
* $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/impl/ICULocaleService.java,v $
|
||||
* $Date: 2002/09/14 21:36:30 $
|
||||
* $Revision: 1.7 $
|
||||
* $Date: 2002/10/02 20:20:21 $
|
||||
* $Revision: 1.8 $
|
||||
*
|
||||
*******************************************************************************
|
||||
*/
|
||||
|
@ -14,6 +14,7 @@ package com.ibm.icu.impl;
|
|||
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
|
@ -29,7 +30,7 @@ public class ICULocaleService extends ICUService {
|
|||
private String fallbackLocaleName;
|
||||
|
||||
/**
|
||||
* Construct an ICULocaleService. This uses the current default locale as a fallback.
|
||||
* Construct an ICULocaleService.
|
||||
*/
|
||||
public ICULocaleService() {
|
||||
}
|
||||
|
@ -42,21 +43,44 @@ public class ICULocaleService extends ICUService {
|
|||
}
|
||||
|
||||
/**
|
||||
* Convenience override for callers using locales.
|
||||
* Convenience override for callers using locales. This calls
|
||||
* get(Locale, int, Locale[]) with KIND_ANY for kind and null for
|
||||
* actualReturn.
|
||||
*/
|
||||
public Object get(Locale locale) {
|
||||
return get(locale, null);
|
||||
return get(locale, LocaleKey.KIND_ANY, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience override for callers using locales.
|
||||
* Convenience override for callers using locales. This calls
|
||||
* get(Locale, int, Locale[]) with a null actualReturn.
|
||||
*/
|
||||
public Object get(Locale locale, int kind) {
|
||||
return get(locale, kind, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience override for callers using locales. This calls
|
||||
* get(Locale, String, Locale[]) with a null kind.
|
||||
*/
|
||||
public Object get(Locale locale, Locale[] actualReturn) {
|
||||
return get(locale, LocaleKey.KIND_ANY, actualReturn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience override for callers using locales. This uses
|
||||
* createKey(Locale.toString(), kind) to create a key, calls getKey, and then
|
||||
* if actualReturn is not null, returns the actualResult from
|
||||
* getKey into a Locale.
|
||||
*/
|
||||
public Object get(Locale locale, int kind, Locale[] actualReturn) {
|
||||
Key key = createKey(locale.toString(), kind);
|
||||
if (actualReturn == null) {
|
||||
return get(locale.toString());
|
||||
return getKey(key);
|
||||
}
|
||||
|
||||
String[] temp = new String[1];
|
||||
Object result = get(locale.toString(), temp);
|
||||
Object result = getKey(key, temp);
|
||||
if (result != null) {
|
||||
actualReturn[0] = LocaleUtility.getLocaleFromName(temp[0]);
|
||||
}
|
||||
|
@ -64,22 +88,35 @@ public class ICULocaleService extends ICUService {
|
|||
}
|
||||
|
||||
/**
|
||||
* Convenience override for callers using locales.
|
||||
* Convenience override for callers using locales. This calls
|
||||
* registerObject(Object, Locale, int kind, int coverage)
|
||||
* passing KIND_ANY for the kind, and VISIBLE for the coverage.
|
||||
*/
|
||||
public Factory registerObject(Object obj, Locale locale) {
|
||||
return registerObject(obj, locale, true);
|
||||
return registerObject(obj, locale, LocaleKey.KIND_ANY, LocaleKeyFactory.VISIBLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience override for callers using locales.
|
||||
* Convenience function for callers using locales. This calls
|
||||
* registerObject(Object, Locale, int kind, int coverage)
|
||||
* passing VISIBLE for the coverage.
|
||||
*/
|
||||
public Factory registerObject(Object obj, Locale locale, boolean visible) {
|
||||
return registerObject(obj, locale.toString(), visible);
|
||||
public Factory registerObject(Object obj, Locale locale, int kind) {
|
||||
return registerObject(obj, locale, kind, LocaleKeyFactory.VISIBLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method for callers using locales. This is the
|
||||
* current typical API for this operation, though perhaps it should change.
|
||||
* Convenience function for callers using locales. This instantiates
|
||||
* a SimpleLocaleKeyFactory, and registers the factory.
|
||||
*/
|
||||
public Factory registerObject(Object obj, Locale locale, int kind, int coverage) {
|
||||
Factory factory = new SimpleLocaleKeyFactory(obj, locale, kind, coverage);
|
||||
return registerFactory(factory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method for callers using locales. This returns the standard
|
||||
* Locale list, built from the Set of visible ids.
|
||||
*/
|
||||
public Locale[] getAvailableLocales() {
|
||||
Set visIDs = getVisibleIDs();
|
||||
|
@ -106,24 +143,26 @@ public class ICULocaleService extends ICUService {
|
|||
* is in upper case, with no trailing underscores.</p>
|
||||
*/
|
||||
public static class LocaleKey extends ICUService.Key {
|
||||
private String prefix;
|
||||
private int kind;
|
||||
private String primaryID;
|
||||
private String fallbackID;
|
||||
private String currentID;
|
||||
|
||||
public static final int KIND_ANY = -1;
|
||||
|
||||
/**
|
||||
* Create a LocaleKey with canonical primary and fallback IDs.
|
||||
*/
|
||||
public static LocaleKey createWithCanonicalFallback(String primaryID, String canonicalFallbackID) {
|
||||
return createWithCanonicalFallback(primaryID, canonicalFallbackID, null);
|
||||
return createWithCanonicalFallback(primaryID, canonicalFallbackID, KIND_ANY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a LocaleKey with canonical primary and fallback IDs.
|
||||
*/
|
||||
public static LocaleKey createWithCanonicalFallback(String primaryID, String canonicalFallbackID, String prefix) {
|
||||
public static LocaleKey createWithCanonicalFallback(String primaryID, String canonicalFallbackID, int kind) {
|
||||
String canonicalPrimaryID = LocaleUtility.canonicalLocaleString(primaryID);
|
||||
return new LocaleKey(primaryID, canonicalPrimaryID, canonicalFallbackID, prefix);
|
||||
return new LocaleKey(primaryID, canonicalPrimaryID, canonicalFallbackID, kind);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -132,10 +171,10 @@ public class ICULocaleService extends ICUService {
|
|||
* fallbackID is the current default locale's string in
|
||||
* canonical form.
|
||||
*/
|
||||
protected LocaleKey(String primaryID, String canonicalPrimaryID, String canonicalFallbackID, String prefix) {
|
||||
protected LocaleKey(String primaryID, String canonicalPrimaryID, String canonicalFallbackID, int kind) {
|
||||
super(primaryID);
|
||||
|
||||
this.prefix = prefix;
|
||||
this.kind = kind;
|
||||
|
||||
if (canonicalPrimaryID == null) {
|
||||
this.primaryID = "";
|
||||
|
@ -156,10 +195,17 @@ public class ICULocaleService extends ICUService {
|
|||
}
|
||||
|
||||
/**
|
||||
* Return the prefix, or null if none was defined.
|
||||
* Return the prefix associated with the kind, or null if the kind is KIND_ANY.
|
||||
*/
|
||||
public String prefix() {
|
||||
return prefix;
|
||||
return kind == KIND_ANY ? null : Integer.toString(kind());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the kind code associated with this key.
|
||||
*/
|
||||
public int kind() {
|
||||
return kind;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -181,8 +227,11 @@ public class ICULocaleService extends ICUService {
|
|||
*/
|
||||
public String currentDescriptor() {
|
||||
String result = currentID();
|
||||
if (result != null && prefix != null) {
|
||||
result = prefix + "/" + result;
|
||||
if (result != null) {
|
||||
result = "/" + result;
|
||||
if (kind != KIND_ANY) {
|
||||
result = prefix() + result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -227,419 +276,299 @@ public class ICULocaleService extends ICUService {
|
|||
}
|
||||
|
||||
/**
|
||||
* This is a factory that handles multiple keys, and records
|
||||
* information about the keys it handles or doesn't handle. This
|
||||
* allows it to quickly filter subsequent queries on keys it has
|
||||
* seen before. Subclasses implement handleCreate instead of
|
||||
* create. Before updateVisibleIDs is called, it keeps track of
|
||||
* keys that it doesn't handle. If its ids are visible, once
|
||||
* updateVisibleIDs is called, it builds a set of all the keys it
|
||||
* does handle and keeps track of the keys it does handle.
|
||||
* A subclass of Factory that uses LocaleKeys, and is able to
|
||||
* 'cover' more specific locales with more general locales that it
|
||||
* supports.
|
||||
*
|
||||
* <p>Covers may be any of the values VISIBLE,
|
||||
* INVISIBLE, VISIBLE_COVERS, INVISIBLE_COVERS, or
|
||||
* VISIBLE_COVERS_REMOVE.
|
||||
*
|
||||
* <p>'Visible' indicates that the specific locale(s) supported by
|
||||
* the factory are registered in getSupportedIDs, 'Invisible'
|
||||
* indicates that they are not. 'Covers' indicates that the
|
||||
* factory preempts previously-registered factories from handling
|
||||
* more specific locales (for one or more kinds); if visible, these
|
||||
* locales remain in visible ids, otherwise they are removed.
|
||||
* 'Visible covers remove' leaves the 'original' locale visible,
|
||||
* but makes the covered sublocales invisible, like
|
||||
* invisible_covers.
|
||||
*
|
||||
* <p>Localization of visible ids (covered or primary) is handled
|
||||
* by the covering factory, regardless of kind.
|
||||
*
|
||||
* <p><b>Example 1:</b> Factory A supports en_US with coverage
|
||||
* VISIBLE_COVERS. Previously-registered factory B supports
|
||||
* en_US_CALIFORNIA. getVisibleIDs will return both en_US and
|
||||
* en_US_CALIFORNIA, Factory A will handle both of them and
|
||||
* localize the ids for both of these.
|
||||
*
|
||||
* <p><b>Example 2:</b> Factory A supports word/en_US with
|
||||
* coverage VISIBLE_COVERS_REMOVE. Previously-registered factory
|
||||
* B supports /en_US_CALIFORNIA (all kinds). getVisibleIDs will
|
||||
* return only en_US and not en_US_CALIFORNIA, Factory A will
|
||||
* handle word/en_US and word/en_US_CALIFORNIA, and also localize
|
||||
* the id en_US. Factory B will handle other kinds of requests
|
||||
* under en_US_CALIFORNIA.
|
||||
*/
|
||||
public static abstract class MultipleKeyFactory implements ICUService.Factory {
|
||||
protected final boolean visible;
|
||||
private SoftReference cacheref;
|
||||
|
||||
private static final class CacheInfo {
|
||||
final Set cache;
|
||||
final boolean included;
|
||||
|
||||
CacheInfo() {
|
||||
this.cache = new HashSet();
|
||||
this.included = false;
|
||||
}
|
||||
|
||||
CacheInfo(Set cache) {
|
||||
this.cache = cache;
|
||||
this.included = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if we're known to support id, or not known to not support id.
|
||||
*/
|
||||
boolean tryCreate(String id) {
|
||||
boolean result = cache.contains(id) == included;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update information about whether we support this id. Since if we are storing
|
||||
* information on included ids, we already know all of them, we only need to
|
||||
* update if we're storing information on ids we don't support and we don't
|
||||
* support the id (the result is null).
|
||||
*/
|
||||
void addCreate(String id, Object result) {
|
||||
if (!included && result == null) {
|
||||
cache.add(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience overload of MultipleKeyFactory(boolean) that defaults
|
||||
* visible to true.
|
||||
*/
|
||||
public MultipleKeyFactory() {
|
||||
this(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a MultipleKeyFactory whose ids are visible iff visible is true.
|
||||
*/
|
||||
public MultipleKeyFactory(boolean visible) {
|
||||
this.visible = visible;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the cache of IDs. These are either the ids that we know we
|
||||
* don't understand, if included is false, or the entire set of ids
|
||||
* we do know we understand, if included is true. If the cache has
|
||||
* been flushed, included is false.
|
||||
*/
|
||||
private CacheInfo getCache() {
|
||||
CacheInfo result = null;
|
||||
if (cacheref != null) {
|
||||
result = (CacheInfo)cacheref.get();
|
||||
}
|
||||
if (result == null) {
|
||||
result = new CacheInfo();
|
||||
cacheref = new SoftReference(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the cache of IDs we understand.
|
||||
*/
|
||||
protected Set getSupportedIDs() {
|
||||
CacheInfo ci = getCache();
|
||||
Set result = ci.cache;
|
||||
if (!ci.included) {
|
||||
result = handleGetSupportedIDs();
|
||||
cacheref = new SoftReference(new CacheInfo(result));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public Object create(Key key) {
|
||||
Object result = null;
|
||||
String id = key.currentID();
|
||||
CacheInfo ci = getCache();
|
||||
if (ci.tryCreate(id)) {
|
||||
result = handleCreate(key);
|
||||
ci.addCreate(id, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public void updateVisibleIDs(Map result) {
|
||||
if (visible) {
|
||||
Iterator iter = getSupportedIDs().iterator();
|
||||
while (iter.hasNext()) {
|
||||
result.put(iter.next(), this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String getDisplayName(String id, Locale locale) {
|
||||
if (visible) {
|
||||
Set cache = getSupportedIDs();
|
||||
if (cache.contains(id)) {
|
||||
return handleGetDisplayName(id, locale);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses implement this instead of create.
|
||||
*/
|
||||
protected abstract Object handleCreate(Key key);
|
||||
|
||||
/**
|
||||
* Subclasses implement this instead of getSupportedIDs. Any
|
||||
* id known to and handled by this class should be included in
|
||||
* the returned Set.
|
||||
*/
|
||||
protected abstract Set handleGetSupportedIDs();
|
||||
|
||||
/**
|
||||
* Subclasses implement this instead of getDisplayName.
|
||||
* Return the display name for the (visible) id in the
|
||||
* provided locale. The default implementation just returns
|
||||
* the id.
|
||||
*/
|
||||
protected String handleGetDisplayName(String id, Locale locale) {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A subclass of MultipleKeyFactory that uses LocaleKeys. It is
|
||||
* able to optionally 'hide' more specific locales with more general
|
||||
* locales that it supports.
|
||||
*/
|
||||
public static abstract class LocaleKeyFactory extends MultipleKeyFactory {
|
||||
protected final boolean hides;
|
||||
public static abstract class LocaleKeyFactory implements Factory {
|
||||
protected final String name;
|
||||
protected final int coverage;
|
||||
|
||||
/**
|
||||
* Create a LocaleKeyFactory.
|
||||
* Coverage value indicating that the factory makes
|
||||
* its locales visible, and does not cover more specific
|
||||
* locales.
|
||||
*/
|
||||
public LocaleKeyFactory(boolean visible, boolean hides) {
|
||||
super(visible);
|
||||
public static final int VISIBLE = 0;
|
||||
|
||||
this.hides = hides;
|
||||
/**
|
||||
* Coverage value indicating that the factory does not make
|
||||
* its locales visible, and does not cover more specific
|
||||
* locales.
|
||||
*/
|
||||
public static final int INVISIBLE = 1;
|
||||
|
||||
/**
|
||||
* Coverage value indicating that the factory makes
|
||||
* its locales visible, covers more specific
|
||||
* locales, and provides localization for the covered
|
||||
* locales.
|
||||
*/
|
||||
public static final int VISIBLE_COVERS = 2;
|
||||
|
||||
/**
|
||||
* Coverage value indicating that the factory does not
|
||||
* make its locales visible, covers more specific
|
||||
* locales, and also does not allow the locales it
|
||||
* covers to be visible.
|
||||
*/
|
||||
public static final int INVISIBLE_COVERS = 3;
|
||||
|
||||
/**
|
||||
* Coverage value indicating that the factory makes
|
||||
* its locales visible, covers more specific
|
||||
* locales, but does not allow the locales it covers
|
||||
* to be visible.
|
||||
*/
|
||||
public static final int VISIBLE_COVERS_REMOVE = 6;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor used by subclasses.
|
||||
*/
|
||||
protected LocaleKeyFactory(int coverage) {
|
||||
this.coverage = coverage;
|
||||
this.name = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override of superclass method. If this is visible, it will update
|
||||
* result with the ids it supports. If this hides ids, more specific
|
||||
* ids already in result will be remapped to this.
|
||||
* Constructor used by subclasses.
|
||||
*/
|
||||
public void updateVisibleIDs(Map result) {
|
||||
if (visible) {
|
||||
Set cache = getSupportedIDs();
|
||||
Map toRemap = new HashMap();
|
||||
Iterator iter = cache.iterator();
|
||||
while (iter.hasNext()) {
|
||||
String id = (String)iter.next();
|
||||
if (hides) {
|
||||
int idlen = id.length();
|
||||
Iterator miter = result.keySet().iterator();
|
||||
while (miter.hasNext()) {
|
||||
String mid = (String)miter.next();
|
||||
if (mid.startsWith(id) &&
|
||||
(mid.length() == idlen ||
|
||||
mid.charAt(idlen) == '_')) {
|
||||
|
||||
toRemap.put(mid, this);
|
||||
miter.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
toRemap.put(id, this);
|
||||
}
|
||||
result.putAll(toRemap);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a localized name for the locale represented by id.
|
||||
*/
|
||||
protected String handleGetDisplayName(String id, Locale locale) {
|
||||
// use java's display name formatting for now
|
||||
return LocaleUtility.getLocaleFromName(id).getDisplayName(locale);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A factory that creates a service based on the ICU locale data.
|
||||
* Subclasses specify a prefix (default is LocaleElements), a
|
||||
* semicolon-separated list of required resources, and a visible flag.
|
||||
* This factory will search the ICU locale data for a bundle with
|
||||
* the exact prefix. Then it will test whether the required resources
|
||||
* are all in this exact bundle. If so, it instantiates the full
|
||||
* resource bundle, and hands it to createServiceFromResource, which
|
||||
* subclasses must implement. Otherwise it returns null.
|
||||
*/
|
||||
public static class ICUResourceBundleFactory extends MultipleKeyFactory {
|
||||
protected final String name;
|
||||
protected final String[][] requiredContents;
|
||||
|
||||
public ICUResourceBundleFactory(boolean visible) {
|
||||
this((String)null, visible);
|
||||
protected LocaleKeyFactory(int coverage, String name) {
|
||||
this.coverage = coverage;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* A service factory based on ICU resource data in the LocaleElements resources.
|
||||
*/
|
||||
public ICUResourceBundleFactory(String requiredContents, boolean visible) {
|
||||
this(ICULocaleData.LOCALE_ELEMENTS, requiredContents, visible);
|
||||
}
|
||||
/**
|
||||
* Implement superclass abstract method. This checks the currentID of
|
||||
* the key against the supported IDs, and passes the canonicalLocale and
|
||||
* kind off to handleCreate (which subclasses must implement).
|
||||
*/
|
||||
public Object create(Key key) {
|
||||
// System.out.println("factory: " + this + "create: " + key.currentID());
|
||||
|
||||
/**
|
||||
* A service factory based on ICU resource data in resources
|
||||
* with the given name. If requiredContents is not null, all
|
||||
* listed resources must come directly from the same bundle.
|
||||
*/
|
||||
public ICUResourceBundleFactory(String name, String requiredContents, boolean visible) {
|
||||
this(name, buildRcAndOr(requiredContents), true, visible);
|
||||
}
|
||||
if (getSupportedIDs().contains(key.currentID())) {
|
||||
LocaleKey lkey = (LocaleKey)key;
|
||||
Locale loc = lkey.canonicalLocale();
|
||||
int kind = lkey.kind();
|
||||
|
||||
private static class Node {
|
||||
public boolean test(ResourceBundle rb) {
|
||||
return rb != null;
|
||||
return handleCreate(loc, kind);
|
||||
} else {
|
||||
// System.out.println("IDs did not support: " + key.currentID());
|
||||
// System.out.println(getSupportedIDs());
|
||||
}
|
||||
}
|
||||
|
||||
private static class ResourceNode {
|
||||
String name;
|
||||
}
|
||||
|
||||
private static class BoolNode extends Node {
|
||||
BoolNode car;
|
||||
BoolNode cdr;
|
||||
}
|
||||
|
||||
private static String[][] buildRcAndOr(String requiredContents) {
|
||||
String[][] rcAndOr = null;
|
||||
if (requiredContents != null) {
|
||||
rcAndOr = new String[][] { parseDelimitedString(requiredContents) };
|
||||
}
|
||||
return rcAndOr;
|
||||
}
|
||||
|
||||
public ICUResourceBundleFactory(String[] rcOr, boolean visible) {
|
||||
this(ICULocaleData.LOCALE_ELEMENTS, rcOr, visible);
|
||||
}
|
||||
|
||||
public ICUResourceBundleFactory(String name, String[] rcOr, boolean visible) {
|
||||
this(name, buildRcAndOr(rcOr), true, visible);
|
||||
}
|
||||
|
||||
private static String[][] buildRcAndOr(String[] rcOr) {
|
||||
String[][] rcOrAnd = null;
|
||||
if (rcOr != null) {
|
||||
rcOrAnd = new String[rcOr.length][];
|
||||
for (int i = 0; i < rcOr.length; ++i) {
|
||||
rcOrAnd[i] = parseDelimitedString(rcOr[i]);
|
||||
}
|
||||
}
|
||||
return rcOrAnd;
|
||||
}
|
||||
|
||||
public ICUResourceBundleFactory(String[][] rcOrAnd, boolean adopt, boolean visible) {
|
||||
this(ICULocaleData.LOCALE_ELEMENTS, rcOrAnd, adopt, visible);
|
||||
}
|
||||
|
||||
private static String[] parseDelimitedString(String str) {
|
||||
if (str != null) {
|
||||
ArrayList list = new ArrayList();
|
||||
for (int i = 0, len = str.length();;) {
|
||||
while (i < len && str.charAt(i) == ';') {
|
||||
++i;
|
||||
}
|
||||
if (i == len) {
|
||||
break;
|
||||
}
|
||||
int j = str.indexOf(';', i);
|
||||
if (j == -1) {
|
||||
j = len;
|
||||
}
|
||||
list.add(str.substring(i, j));
|
||||
i = j;
|
||||
}
|
||||
return (String[])list.toArray(new String[list.size()]);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public ICUResourceBundleFactory(String name, String[][] rcOrAnd, boolean adopt, boolean visible) {
|
||||
super(visible);
|
||||
|
||||
this.name = name;
|
||||
/**
|
||||
* Override of superclass method. This adjusts the result based
|
||||
* on the coverage rule for this factory.
|
||||
*/
|
||||
public void updateVisibleIDs(Map result) {
|
||||
Set cache = getSupportedIDs();
|
||||
|
||||
if (!adopt && rcOrAnd != null) {
|
||||
rcOrAnd = (String[][])rcOrAnd.clone();
|
||||
for (int i = 0; i < rcOrAnd.length; ++i) {
|
||||
rcOrAnd[i] = (String[])(rcOrAnd[i].clone());
|
||||
boolean visible = (coverage & 0x1) == 0;
|
||||
boolean covers = (coverage & 0x2) != 0;
|
||||
boolean removes = !visible || (coverage & 0x4) != 0;
|
||||
|
||||
// System.out.println("vis: " + visible + " covers: " + covers + " removes: " + removes);
|
||||
Map toRemap = new HashMap();
|
||||
Iterator iter = cache.iterator();
|
||||
while (iter.hasNext()) {
|
||||
String id = (String)iter.next();
|
||||
if (covers) {
|
||||
int idlen = id.length();
|
||||
Iterator miter = result.keySet().iterator();
|
||||
while (miter.hasNext()) {
|
||||
String mid = (String)miter.next();
|
||||
if (mid.startsWith(id) &&
|
||||
(mid.length() == idlen ||
|
||||
mid.charAt(idlen) == '_')) {
|
||||
|
||||
if (removes) {
|
||||
miter.remove();
|
||||
} else {
|
||||
toRemap.put(mid, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!visible) {
|
||||
result.remove(id);
|
||||
} else {
|
||||
toRemap.put(id, this);
|
||||
}
|
||||
}
|
||||
this.requiredContents = rcOrAnd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides parent handleCreate call. Parent will filter out keys that it
|
||||
* knows are not accepted by this factory before calling this method.
|
||||
*/
|
||||
protected Object handleCreate(Key key) {
|
||||
Locale loc = LocaleUtility.getLocaleFromName(key.currentID());
|
||||
if (acceptsLocale(loc)) {
|
||||
ResourceBundle bundle = ICULocaleData.getResourceBundle(name, loc); // full resource bundle tree lookup
|
||||
return createFromBundle(bundle, key);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries all the available locales in ICU and adds the names
|
||||
* of those which it accepts to result. This is quite
|
||||
* time-consuming so we don't want to do it more than once if
|
||||
* we have to. This is only called if we are visible.
|
||||
*/
|
||||
protected Set handleGetSupportedIDs() {
|
||||
Set result = new TreeSet(String.CASE_INSENSITIVE_ORDER);
|
||||
Locale[] locales = ICULocaleData.getAvailableLocales(name);
|
||||
for (int i = 0; i < locales.length; ++i) {
|
||||
Locale locale = locales[i];
|
||||
if (acceptsLocale(locale)) {
|
||||
String str = LocaleUtility.canonicalLocaleString(locale.toString());
|
||||
result.add(str);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
result.putAll(toRemap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a localized name for the locale represented by id.
|
||||
*/
|
||||
protected String handleGetDisplayName(String id, Locale locale) {
|
||||
return LocaleUtility.getLocaleFromName(id).getDisplayName(locale);
|
||||
public String getDisplayName(String id, Locale locale) {
|
||||
if (locale == null) {
|
||||
return id;
|
||||
}
|
||||
Locale loc = LocaleUtility.getLocaleFromName(id);
|
||||
return loc.getDisplayName(locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method used by create(Key). Subclasses can implement
|
||||
* this instead of create.
|
||||
*/
|
||||
protected Object handleCreate(Locale loc, int kind) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the set of ids that this factory supports (visible or
|
||||
* otherwise). This can be called often and might need to be
|
||||
* cached if it is expensive to create.
|
||||
*/
|
||||
protected abstract Set getSupportedIDs();
|
||||
|
||||
/**
|
||||
* For debugging.
|
||||
*/
|
||||
public String toString() {
|
||||
StringBuffer buf = new StringBuffer(super.toString());
|
||||
if (name != null) {
|
||||
buf.append(", name: ");
|
||||
buf.append(name);
|
||||
}
|
||||
buf.append(", coverage: ");
|
||||
String[] coverage_names = {
|
||||
"visible", "invisible", "visible_covers", "invisible_covers", "????", "visible_covers_remove"
|
||||
};
|
||||
buf.append(coverage_names[coverage]);
|
||||
return buf.toString();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A LocaleKeyFactory that just returns a single object for a kind/locale.
|
||||
*/
|
||||
public static class SimpleLocaleKeyFactory extends LocaleKeyFactory {
|
||||
private final Object obj;
|
||||
private final String id;
|
||||
private final int kind;
|
||||
|
||||
public SimpleLocaleKeyFactory(Object obj, Locale locale, int kind, int coverage) {
|
||||
this(obj, locale, kind, coverage, null);
|
||||
}
|
||||
|
||||
public SimpleLocaleKeyFactory(Object obj, Locale locale, int kind, int coverage, String name) {
|
||||
super(coverage, name);
|
||||
|
||||
this.obj = obj;
|
||||
this.id = LocaleUtility.canonicalLocaleString(locale.toString());
|
||||
this.kind = kind;
|
||||
}
|
||||
|
||||
public Object create(Key key) {
|
||||
LocaleKey lkey = (LocaleKey)key;
|
||||
if (kind == LocaleKey.KIND_ANY || kind == lkey.kind()) {
|
||||
String keyID = lkey.currentID();
|
||||
if (id.equals(keyID) ||
|
||||
((coverage & 0x2) != 0 && LocaleUtility.isFallbackOf(id, keyID))) {
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected Set getSupportedIDs() {
|
||||
return Collections.singleton(id);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuffer buf = new StringBuffer(super.toString());
|
||||
buf.append(", id: ");
|
||||
buf.append(id);
|
||||
buf.append(", kind: ");
|
||||
buf.append(kind);
|
||||
return buf.toString();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A LocaleKeyFactory that creates a service based on the ICU locale data.
|
||||
* This is a base class for most ICU factories. Subclasses instantiate it
|
||||
* with a constructor that takes a bundle name, which determines the supported
|
||||
* IDs. Subclasses then override handleCreate to create the actual service
|
||||
* object. The default implementation returns a resource bundle.
|
||||
*/
|
||||
public static class ICUResourceBundleFactory extends LocaleKeyFactory {
|
||||
protected final String bundleName;
|
||||
|
||||
/**
|
||||
* Convenience constructor that uses the main ICU bundle name.
|
||||
*/
|
||||
public ICUResourceBundleFactory() {
|
||||
this(ICULocaleData.LOCALE_ELEMENTS);
|
||||
}
|
||||
|
||||
/**
|
||||
* We only accept the locale if there is a bundle for this exact locale and if
|
||||
* all the required resources are directly in this bundle (none is from an
|
||||
* inherited bundle);
|
||||
* A service factory based on ICU resource data in resources
|
||||
* with the given name.
|
||||
*/
|
||||
protected boolean acceptsLocale(Locale loc) {
|
||||
boolean debug = false;
|
||||
if (debug) System.out.println("al name: " + name + " loc: '" + loc + "'");
|
||||
try {
|
||||
ResourceBundle bundle = ICULocaleData.loadResourceBundle(name, loc);
|
||||
if (bundle == null) {
|
||||
if (debug) System.out.println("no bundle");
|
||||
return false;
|
||||
}
|
||||
if (requiredContents == null) {
|
||||
if (debug) System.out.println("always accepts");
|
||||
return true;
|
||||
}
|
||||
public ICUResourceBundleFactory(String bundleName) {
|
||||
super(VISIBLE);
|
||||
|
||||
loop:
|
||||
for (int i = 0; i < requiredContents.length; ++i) {
|
||||
String[] andRC = requiredContents[i];
|
||||
this.bundleName = bundleName;
|
||||
}
|
||||
|
||||
for (int j = 0; j < andRC.length; ++j) {
|
||||
try {
|
||||
if (debug) System.out.println("al["+i+"]["+j+"] " + andRC[j]);
|
||||
bundle.getObject(andRC[j]);
|
||||
}
|
||||
catch (MissingResourceException ex) {
|
||||
if (debug) System.out.println("nope");
|
||||
continue loop;
|
||||
}
|
||||
}
|
||||
if (debug) System.out.println("ok");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
Thread.dumpStack();
|
||||
if (debug) System.out.println("whoops: " + e);
|
||||
System.exit(0);
|
||||
}
|
||||
return false;
|
||||
/**
|
||||
* Return the supported IDs. This is the set of all locale names in ICULocaleData.
|
||||
*/
|
||||
protected Set getSupportedIDs() {
|
||||
return ICULocaleData.getAvailableLocaleNameSet(bundleName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclassers implement this to create their service object based on the bundle and key.
|
||||
* The default implementation just returns the bundle.
|
||||
*/
|
||||
protected Object createFromBundle(ResourceBundle bundle, Key key) {
|
||||
return bundle;
|
||||
}
|
||||
/**
|
||||
* Create the service. The default implementation returns the resource bundle
|
||||
* for the locale, ignoring kind.
|
||||
*/
|
||||
protected Object handleCreate(Locale loc, int kind) {
|
||||
return ICULocaleData.getResourceBundle(bundleName, loc);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return super.toString() + ", bundle: " + bundleName;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -660,7 +589,11 @@ public class ICULocaleService extends ICUService {
|
|||
return fallbackLocaleName;
|
||||
}
|
||||
|
||||
protected Key createKey(String id) {
|
||||
public Key createKey(String id) {
|
||||
return LocaleKey.createWithCanonicalFallback(id, validateFallbackLocale());
|
||||
}
|
||||
|
||||
public Key createKey(String id, int kind) {
|
||||
return LocaleKey.createWithCanonicalFallback(id, validateFallbackLocale(), kind);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,18 +5,21 @@
|
|||
*******************************************************************************
|
||||
*
|
||||
* $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/impl/ICUService.java,v $
|
||||
* $Date: 2002/09/14 21:36:29 $
|
||||
* $Revision: 1.8 $
|
||||
* $Date: 2002/10/02 20:20:21 $
|
||||
* $Revision: 1.9 $
|
||||
*
|
||||
*******************************************************************************
|
||||
*/
|
||||
package com.ibm.icu.impl;
|
||||
|
||||
import com.ibm.icu.text.Collator;
|
||||
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.EventListener;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
@ -58,12 +61,22 @@ import java.util.TreeMap;
|
|||
* longer be located through it. Service objects generated by this
|
||||
* factory and held by the client are unaffected.</p>
|
||||
*
|
||||
* <p>Internally, ICUService uses Keys to query factories and perform
|
||||
* <p>ICUService uses Keys to query factories and perform
|
||||
* fallback. The Key defines the canonical form of the id, and
|
||||
* implements the fallback strategy. Custom Keys can be defined that
|
||||
* parse complex IDs into components that Factories can more easily
|
||||
* use. The Key can cache the results of this parsing to save
|
||||
* repeated effort.</p>
|
||||
* repeated effort. ICUService provides convenience APIs that
|
||||
* take Strings and generate default Keys for use in querying.</p>
|
||||
*
|
||||
* <p>ICUService provides API to get the list of ids publicly
|
||||
* supported by the service (although queries aren't restricted to
|
||||
* this list). This list contains only 'simple' IDs, and not fully
|
||||
* unique ids. Factories are associated with each simple ID and
|
||||
* the responsible factory can also return a human-readable localized
|
||||
* version of the simple ID, for use in user interfaces. ICUService
|
||||
* can also provide a sorted collection of the all the localized visible
|
||||
* ids.</p>
|
||||
*
|
||||
* <p>ICUService implements ICUNotifier, so that clients can register
|
||||
* to receive notification when factories are added or removed from
|
||||
|
@ -114,11 +127,22 @@ public class ICUService extends ICUNotifier {
|
|||
|
||||
/**
|
||||
* Keys are used to communicate with factories to generate an
|
||||
* instance of the service. They define how ids are
|
||||
* instance of the service. Keys define how ids are
|
||||
* canonicalized, provide both a current id and a current
|
||||
* descriptor to use in querying the cache and factories, and
|
||||
* determine the fallback strategy. The default key has no
|
||||
* fallbacks.
|
||||
* determine the fallback strategy.</p>
|
||||
*
|
||||
* <p>Keys provide both a currentDescriptor and a currentID.
|
||||
* The descriptor contains an optional prefix, followed by '/'
|
||||
* and the currentID. Factories that handle complex keys,
|
||||
* for example number format factories that generate multiple
|
||||
* kinds of formatters for the same locale, use the descriptor
|
||||
* to provide a fully unique identifier for the service object,
|
||||
* while using the currentID (in this case, the locale string),
|
||||
* as the visible IDs that can be localized.
|
||||
*
|
||||
* <p> The default implementation of Key has no fallbacks and
|
||||
* has no custom descriptors.</p>
|
||||
*/
|
||||
public static class Key {
|
||||
private final String id;
|
||||
|
@ -156,14 +180,14 @@ public class ICUService extends ICUNotifier {
|
|||
/**
|
||||
* Return the current descriptor. This implementation returns
|
||||
* the current ID. The current descriptor is used to fully
|
||||
* identify an instance of the service in the cache. The
|
||||
* current ID is that part of the descriptor that a factory
|
||||
* can examine to identify whether it handles the key. The
|
||||
* factory can either parse the descriptor or use custom API
|
||||
* on the key in order to instantiate the service.
|
||||
* identify an instance of the service in the cache. A
|
||||
* factory may handle all descriptors for an ID, or just a
|
||||
* particular descriptor. The factory can either parse the
|
||||
* descriptor or use custom API on the key in order to
|
||||
* instantiate the service.
|
||||
*/
|
||||
public String currentDescriptor() {
|
||||
return currentID();
|
||||
return "/" + currentID();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -185,6 +209,7 @@ public class ICUService extends ICUNotifier {
|
|||
* a supported id.
|
||||
*/
|
||||
public static interface Factory {
|
||||
|
||||
/**
|
||||
* Create a service object from the key, if this factory
|
||||
* supports the key. Otherwise, return null.
|
||||
|
@ -192,18 +217,26 @@ public class ICUService extends ICUNotifier {
|
|||
public Object create(Key key);
|
||||
|
||||
/**
|
||||
* Add IDs this factory publicly handles to the result map,
|
||||
* with this factory as the value. If this factory hides IDs
|
||||
* currently in result, it should remove or reset the mappings
|
||||
* for those IDs. Result should contain only ids, not
|
||||
* descriptors.
|
||||
* Update the result IDs (not descriptors) to reflect the IDs
|
||||
* this factory handles. This function and getDisplayName are
|
||||
* used to support ICUService.getDisplayNames. Basically, the
|
||||
* factory has to determine which IDs it will permit to be
|
||||
* available, and of those, which it will provide localized
|
||||
* display names for. In most cases this reflects the IDs that
|
||||
* the factory directly supports. A factory might, however,
|
||||
* 'cover' existing IDs already in result (for example, variant
|
||||
* locales) and support them itself. In this case it needs to
|
||||
* remap those IDs to itself if it wishes to provide the
|
||||
* display names for them, or remove those IDs from result
|
||||
* if it wishes them to be invisible.
|
||||
*/
|
||||
public void updateVisibleIDs(Map result);
|
||||
|
||||
/**
|
||||
* Return the display name for this id in the provided locale.
|
||||
* If the id is not visible or not defined by the factory,
|
||||
* return null. This is an id, not a descriptor.
|
||||
* This is an localized id, not a descriptor. If the id is
|
||||
* not visible or not defined by the factory, return null.
|
||||
* If locale is null, return id unchanged.
|
||||
*/
|
||||
public String getDisplayName(String id, Locale locale);
|
||||
}
|
||||
|
@ -211,11 +244,11 @@ public class ICUService extends ICUNotifier {
|
|||
/**
|
||||
* A default implementation of factory. This provides default
|
||||
* implementations for subclasses, and implements a singleton
|
||||
* factory that matches a single id and returns a single
|
||||
* (possibly deferred-initialized) instance. If visible is
|
||||
* true, updates the map passed to updateVisibleIDs with a
|
||||
* mapping from id to itself. This ignores the key descriptor
|
||||
* and only examines the id.
|
||||
* factory that matches a single id and returns a single
|
||||
* (possibly deferred-initialized) instance. This implements
|
||||
* updateVisibleIDs to add a mapping from its ID to itself
|
||||
* if visible is true, or to remove any existing mapping
|
||||
* for its ID if visible is false.
|
||||
*/
|
||||
public static class SimpleFactory implements Factory {
|
||||
protected Object instance;
|
||||
|
@ -245,7 +278,8 @@ public class ICUService extends ICUNotifier {
|
|||
}
|
||||
|
||||
/**
|
||||
* Return the service instance if id equals the key's currentID.
|
||||
* Return the service instance if the factory's id is equal to
|
||||
* the key's currentID.
|
||||
*/
|
||||
public Object create(Key key) {
|
||||
if (id.equals(key.currentID())) {
|
||||
|
@ -255,19 +289,37 @@ public class ICUService extends ICUNotifier {
|
|||
}
|
||||
|
||||
/**
|
||||
* If visible, adds a mapping from id -> this to the result.
|
||||
* If visible, adds a mapping from id -> this to the result,
|
||||
* otherwise removes id from result.
|
||||
*/
|
||||
public void updateVisibleIDs(Map result) {
|
||||
if (visible) result.put(id, this);
|
||||
if (visible) {
|
||||
result.put(id, this);
|
||||
} else {
|
||||
result.remove(id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If id equals this.id, returns id regardless of locale, otherwise
|
||||
* returns null.
|
||||
*/
|
||||
* If this.id equals id, returns id regardless of locale,
|
||||
* otherwise returns null. (This default implementation has
|
||||
* no localized id information.)
|
||||
*/
|
||||
public String getDisplayName(String id, Locale locale) {
|
||||
return (visible && id.equals(this.id)) ? id : null;
|
||||
return (visible && this.id.equals(id)) ? id : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* For debugging.
|
||||
*/
|
||||
public String toString() {
|
||||
StringBuffer buf = new StringBuffer(super.toString());
|
||||
buf.append(", id: ");
|
||||
buf.append(id);
|
||||
buf.append(", visible: ");
|
||||
buf.append(visible);
|
||||
return buf.toString();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -313,7 +365,7 @@ public class ICUService extends ICUNotifier {
|
|||
*/
|
||||
public Object getKey(Key key, String[] actualReturn) {
|
||||
if (factories.size() == 0) {
|
||||
return null;
|
||||
return handleDefault(key, actualReturn);
|
||||
}
|
||||
|
||||
boolean debug = false;
|
||||
|
@ -353,7 +405,9 @@ public class ICUService extends ICUNotifier {
|
|||
if (result != null) {
|
||||
if (debug) System.out.println(name + " found with descriptor: " + currentDescriptor);
|
||||
break outer;
|
||||
}
|
||||
} else {
|
||||
if (debug) System.out.println("did not find: " + currentDescriptor + " in cache");
|
||||
}
|
||||
|
||||
// first test of cache failed, so we'll have to update
|
||||
// the cache if we eventually succeed.
|
||||
|
@ -362,12 +416,16 @@ public class ICUService extends ICUNotifier {
|
|||
int n = 0;
|
||||
Iterator fi = factories.iterator();
|
||||
while (fi.hasNext()) {
|
||||
Object service = ((Factory)fi.next()).create(key);
|
||||
Factory f = (Factory)fi.next();
|
||||
if (debug) System.out.println("trying factory: " + f.toString());
|
||||
Object service = f.create(key);
|
||||
if (service != null) {
|
||||
result = new CacheEntry(currentDescriptor, service);
|
||||
if (debug) System.out.println(name + " factory cache with descriptor: " + currentDescriptor);
|
||||
if (debug) System.out.println(name + " factory supported: " + currentDescriptor + ", caching");
|
||||
break outer;
|
||||
}
|
||||
} else {
|
||||
if (debug) System.out.println("factory did not support: " + currentDescriptor);
|
||||
}
|
||||
}
|
||||
|
||||
// prepare to load the cache with all additional ids that
|
||||
|
@ -402,7 +460,12 @@ public class ICUService extends ICUNotifier {
|
|||
}
|
||||
|
||||
if (actualReturn != null) {
|
||||
actualReturn[0] = result.actualDescriptor;
|
||||
// strip null prefix
|
||||
if (result.actualDescriptor.indexOf("/") == 0) {
|
||||
actualReturn[0] = result.actualDescriptor.substring(1);
|
||||
} else {
|
||||
actualReturn[0] = result.actualDescriptor;
|
||||
}
|
||||
}
|
||||
|
||||
if (debug) System.out.println("found in service: " + name);
|
||||
|
@ -417,7 +480,7 @@ public class ICUService extends ICUNotifier {
|
|||
|
||||
if (debug) System.out.println("not found in service: " + name);
|
||||
|
||||
return null;
|
||||
return handleDefault(key, actualReturn);
|
||||
}
|
||||
private SoftReference cacheref;
|
||||
|
||||
|
@ -432,6 +495,15 @@ public class ICUService extends ICUNotifier {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Default handler for this service if no factory in the list
|
||||
* handled the key.
|
||||
*/
|
||||
protected Object handleDefault(Key key, String[] actualIDReturn) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a snapshot of the visible IDs for this service. This
|
||||
* set will not change as Factories are added or removed, but the
|
||||
|
@ -459,7 +531,7 @@ public class ICUService extends ICUNotifier {
|
|||
// grab the factory list and update it ourselves
|
||||
try {
|
||||
factoryLock.acquireRead();
|
||||
idcache = new TreeMap(String.CASE_INSENSITIVE_ORDER);
|
||||
idcache = new HashMap();
|
||||
ListIterator lIter = factories.listIterator(factories.size());
|
||||
while (lIter.hasPrevious()) {
|
||||
Factory f = (Factory)lIter.previous();
|
||||
|
@ -512,6 +584,15 @@ public class ICUService extends ICUNotifier {
|
|||
return getDisplayNames(Locale.getDefault());
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience override of getDisplayNames(Locale, Collator) that
|
||||
* uses the default collator for the locale as the comparator.
|
||||
*/
|
||||
public Map getDisplayNames(Locale locale) {
|
||||
Collator col = Collator.getInstance(locale);
|
||||
return getDisplayNames(locale, col);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a snapshot of the mapping from display names to visible
|
||||
* IDs for this service. This set will not change as factories
|
||||
|
@ -519,19 +600,19 @@ public class ICUService extends ICUNotifier {
|
|||
* no guarantee that all and only the ids in the returned map will
|
||||
* be visible and supported by the service in subsequent calls,
|
||||
* nor is there any guarantee that the current display names match
|
||||
* those in the set.
|
||||
* those in the set. The display names are sorted based on the
|
||||
* comparator provided.
|
||||
*/
|
||||
public Map getDisplayNames(Locale locale) {
|
||||
public Map getDisplayNames(Locale locale, Comparator col) {
|
||||
Map dncache = null;
|
||||
LocaleRef ref = dnref;
|
||||
if (ref != null) {
|
||||
dncache = ref.get(locale);
|
||||
dncache = ref.get(locale, col);
|
||||
}
|
||||
while (dncache == null) {
|
||||
synchronized (this) {
|
||||
if (ref == dnref || dnref == null) {
|
||||
dncache = new TreeMap(String.CASE_INSENSITIVE_ORDER);
|
||||
//dncache = new TreeMap(/* locale-specific collator */);
|
||||
dncache = new TreeMap(col); // sorted
|
||||
|
||||
Map m = getVisibleIDMap();
|
||||
Iterator ei = m.entrySet().iterator();
|
||||
|
@ -543,30 +624,37 @@ public class ICUService extends ICUNotifier {
|
|||
}
|
||||
|
||||
dncache = Collections.unmodifiableMap(dncache);
|
||||
dnref = new LocaleRef(dncache, locale);
|
||||
dnref = new LocaleRef(dncache, locale, col);
|
||||
} else {
|
||||
ref = dnref;
|
||||
dncache = ref.get(locale);
|
||||
dncache = ref.get(locale, col);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dncache;
|
||||
}
|
||||
// we define a class so we get atomic simultaneous access to both the
|
||||
// locale and corresponding map
|
||||
private static class LocaleRef {
|
||||
final Locale locale;
|
||||
final SoftReference ref;
|
||||
|
||||
LocaleRef(Map dnCache, Locale locale) {
|
||||
// we define a class so we get atomic simultaneous access to the
|
||||
// locale, comparator, and corresponding map.
|
||||
private static class LocaleRef {
|
||||
private final Locale locale;
|
||||
private SoftReference ref;
|
||||
private Comparator col;
|
||||
|
||||
LocaleRef(Map dnCache, Locale locale, Comparator col) {
|
||||
this.locale = locale;
|
||||
this.col = col;
|
||||
this.ref = new SoftReference(dnCache);
|
||||
}
|
||||
|
||||
Map get(Locale locale) {
|
||||
if (this.locale.equals(locale)) {
|
||||
return (Map)ref.get();
|
||||
Map get(Locale locale, Comparator col) {
|
||||
Map m = (Map)ref.get();
|
||||
if (m != null &&
|
||||
this.locale.equals(locale) &&
|
||||
(this.col == col || (this.col != null && this.col.equals(col)))) {
|
||||
|
||||
return m;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -602,8 +690,8 @@ public class ICUService extends ICUNotifier {
|
|||
* getVisibleIDs if visible is true.
|
||||
*/
|
||||
public Factory registerObject(Object obj, String id, boolean visible) {
|
||||
id = createKey(id).canonicalID();
|
||||
return registerFactory(new SimpleFactory(obj, id, visible));
|
||||
String canonicalID = createKey(id).canonicalID();
|
||||
return registerFactory(new SimpleFactory(obj, canonicalID, visible));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -682,12 +770,20 @@ public class ICUService extends ICUNotifier {
|
|||
factories.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the service is in its default state. The default
|
||||
* implementation returns true if there are no factories registered.
|
||||
*/
|
||||
public boolean isDefault() {
|
||||
return factories.size() == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a key from an id. This creates a Key instance.
|
||||
* Subclasses can override to define more useful keys appropriate
|
||||
* to the factories they accept.
|
||||
*/
|
||||
protected Key createKey(String id) {
|
||||
public Key createKey(String id) {
|
||||
return new Key(id);
|
||||
}
|
||||
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
*******************************************************************************
|
||||
*
|
||||
* $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/impl/LocaleUtility.java,v $
|
||||
* $Date: 2002/09/14 21:36:29 $
|
||||
* $Revision: 1.5 $
|
||||
* $Date: 2002/10/02 20:20:21 $
|
||||
* $Revision: 1.6 $
|
||||
* *****************************************************************************************
|
||||
*/
|
||||
|
||||
|
@ -70,6 +70,14 @@ public class LocaleUtility {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convenience method that calls canonicalLocaleString(String) with
|
||||
* locale.toString();
|
||||
*/
|
||||
public static String canonicalLocaleString(Locale locale) {
|
||||
return canonicalLocaleString(locale.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* You'd think that Locale canonicalizes, since it munges the
|
||||
* renamed languages, but it doesn't quite. It forces the region
|
||||
|
|
|
@ -5,14 +5,20 @@
|
|||
*******************************************************************************
|
||||
*
|
||||
* $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/text/BreakIterator.java,v $
|
||||
* $Date: 2002/03/20 05:11:15 $
|
||||
* $Revision: 1.8 $
|
||||
* $Date: 2002/10/02 20:20:21 $
|
||||
* $Revision: 1.9 $
|
||||
*
|
||||
*****************************************************************************************
|
||||
*/
|
||||
package com.ibm.icu.text;
|
||||
|
||||
import com.ibm.icu.impl.ICULocaleData;
|
||||
import com.ibm.icu.impl.ICULocaleService;
|
||||
import com.ibm.icu.impl.ICULocaleService.LocaleKey;
|
||||
import com.ibm.icu.impl.ICULocaleService.ICUResourceBundleFactory;
|
||||
import com.ibm.icu.impl.ICUService.Factory;
|
||||
import com.ibm.icu.impl.ICUService.Key;
|
||||
import com.ibm.icu.impl.LocaleUtility;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
|
@ -397,11 +403,18 @@ public abstract class BreakIterator implements Cloneable
|
|||
*/
|
||||
public abstract void setText(CharacterIterator newText);
|
||||
|
||||
public static final int KIND_CHARACTER = 0;
|
||||
public static final int KIND_WORD = 1;
|
||||
public static final int KIND_LINE = 2;
|
||||
public static final int KIND_SENTENCE = 3;
|
||||
public static final int KIND_TITLE = 4;
|
||||
/*
|
||||
private static final int CHARACTER_INDEX = 0;
|
||||
private static final int WORD_INDEX = 1;
|
||||
private static final int LINE_INDEX = 2;
|
||||
private static final int SENTENCE_INDEX = 3;
|
||||
private static final int TITLE_INDEX = 4;
|
||||
*/
|
||||
private static final SoftReference[] iterCache = new SoftReference[5];
|
||||
|
||||
/**
|
||||
|
@ -423,10 +436,7 @@ public abstract class BreakIterator implements Cloneable
|
|||
*/
|
||||
public static BreakIterator getWordInstance(Locale where)
|
||||
{
|
||||
return getBreakInstance(where,
|
||||
WORD_INDEX,
|
||||
"WordBreakRules",
|
||||
"WordBreakDictionary");
|
||||
return getBreakInstance(where, KIND_WORD);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -450,10 +460,7 @@ public abstract class BreakIterator implements Cloneable
|
|||
*/
|
||||
public static BreakIterator getLineInstance(Locale where)
|
||||
{
|
||||
return getBreakInstance(where,
|
||||
LINE_INDEX,
|
||||
"LineBreakRules",
|
||||
"LineBreakDictionary");
|
||||
return getBreakInstance(where, KIND_LINE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -477,10 +484,7 @@ public abstract class BreakIterator implements Cloneable
|
|||
*/
|
||||
public static BreakIterator getCharacterInstance(Locale where)
|
||||
{
|
||||
return getBreakInstance(where,
|
||||
CHARACTER_INDEX,
|
||||
"CharacterBreakRules",
|
||||
"CharacterBreakDictionary");
|
||||
return getBreakInstance(where, KIND_CHARACTER);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -501,10 +505,7 @@ public abstract class BreakIterator implements Cloneable
|
|||
*/
|
||||
public static BreakIterator getSentenceInstance(Locale where)
|
||||
{
|
||||
return getBreakInstance(where,
|
||||
SENTENCE_INDEX,
|
||||
"SentenceBreakRules",
|
||||
"SentenceBreakDictionary");
|
||||
return getBreakInstance(where, KIND_SENTENCE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -525,19 +526,64 @@ public abstract class BreakIterator implements Cloneable
|
|||
*/
|
||||
public static BreakIterator getTitleInstance(Locale where)
|
||||
{
|
||||
return getBreakInstance(where,
|
||||
TITLE_INDEX,
|
||||
"TitleBreakRules",
|
||||
"TitleBreakDictionary");
|
||||
return getBreakInstance(where, KIND_TITLE);
|
||||
}
|
||||
|
||||
private static BreakIterator getBreakInstance(Locale where,
|
||||
int type,
|
||||
String rulesName,
|
||||
String dictionaryName) {
|
||||
public static Object register(BreakIterator iter, Locale locale, int kind) {
|
||||
try {
|
||||
return getService().registerObject(iter, locale, kind);
|
||||
}
|
||||
catch (IndexOutOfBoundsException e) {
|
||||
throw new IllegalArgumentException("unknown kind: " + kind);
|
||||
}
|
||||
}
|
||||
|
||||
if (iterCache[type] != null) {
|
||||
BreakIteratorCache cache = (BreakIteratorCache) iterCache[type].get();
|
||||
public static boolean unregister(Object key) {
|
||||
if (service != null) {
|
||||
return service.unregisterFactory((Factory)key);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static ICULocaleService service;
|
||||
private static ICULocaleService getService() {
|
||||
if (service == null) {
|
||||
ICULocaleService newService = new ICULocaleService("BreakIterator");
|
||||
|
||||
class RBBreakIteratorFactory extends ICUResourceBundleFactory {
|
||||
protected Object handleCreate(Locale loc, int kind) {
|
||||
return createBreakInstance(loc, kind);
|
||||
}
|
||||
}
|
||||
newService.registerFactory(new RBBreakIteratorFactory());
|
||||
|
||||
synchronized (BreakIterator.class) {
|
||||
if (service == null) {
|
||||
service = newService;
|
||||
}
|
||||
}
|
||||
}
|
||||
return service;
|
||||
}
|
||||
|
||||
private static final String[] KIND_NAMES = {
|
||||
"Character", "Word", "Line", "Sentence", "Title"
|
||||
};
|
||||
|
||||
private static BreakIterator createBreakInstance(Locale locale, int kind) {
|
||||
String prefix = KIND_NAMES[kind];
|
||||
return createBreakInstance(locale,
|
||||
kind,
|
||||
prefix + "BreakRules",
|
||||
prefix + "BreakDictionary");
|
||||
}
|
||||
|
||||
// end of registration
|
||||
|
||||
private static BreakIterator getBreakInstance(Locale where, int kind) {
|
||||
|
||||
if (iterCache[kind] != null) {
|
||||
BreakIteratorCache cache = (BreakIteratorCache) iterCache[kind].get();
|
||||
if (cache != null) {
|
||||
if (cache.getLocale().equals(where)) {
|
||||
return cache.createBreakInstance();
|
||||
|
@ -545,17 +591,14 @@ public abstract class BreakIterator implements Cloneable
|
|||
}
|
||||
}
|
||||
|
||||
BreakIterator result = createBreakInstance(where,
|
||||
type,
|
||||
rulesName,
|
||||
dictionaryName);
|
||||
BreakIterator result = createBreakInstance(where, kind);
|
||||
BreakIteratorCache cache = new BreakIteratorCache(where, result);
|
||||
iterCache[type] = new SoftReference(cache);
|
||||
iterCache[kind] = new SoftReference(cache);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static BreakIterator createBreakInstance(Locale where,
|
||||
int type,
|
||||
int kind,
|
||||
String rulesName,
|
||||
String dictionaryName) {
|
||||
|
||||
|
@ -566,10 +609,10 @@ public abstract class BreakIterator implements Cloneable
|
|||
|
||||
String rules = bundle.getString(rulesName);
|
||||
|
||||
if (classNames[type].equals("RuleBasedBreakIterator")) {
|
||||
if (classNames[kind].equals("RuleBasedBreakIterator")) {
|
||||
return new RuleBasedBreakIterator(rules);
|
||||
}
|
||||
else if (classNames[type].equals("DictionaryBasedBreakIterator")) {
|
||||
else if (classNames[kind].equals("DictionaryBasedBreakIterator")) {
|
||||
try {
|
||||
// System.out.println(dictionaryName);
|
||||
Object t = bundle.getObject(dictionaryName);
|
||||
|
@ -586,7 +629,7 @@ public abstract class BreakIterator implements Cloneable
|
|||
}
|
||||
else
|
||||
throw new IllegalArgumentException("Invalid break iterator class \"" +
|
||||
classNames[type] + "\"");
|
||||
classNames[kind] + "\"");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -596,8 +639,11 @@ public abstract class BreakIterator implements Cloneable
|
|||
*/
|
||||
public static synchronized Locale[] getAvailableLocales()
|
||||
{
|
||||
// returns all locales
|
||||
return ICULocaleData.getAvailableLocales();
|
||||
if (service == null) {
|
||||
return ICULocaleData.getAvailableLocales();
|
||||
} else {
|
||||
return service.getAvailableLocales();
|
||||
}
|
||||
}
|
||||
|
||||
private static final class BreakIteratorCache {
|
||||
|
|
|
@ -574,7 +574,7 @@ public abstract class DateFormat extends Format {
|
|||
*/
|
||||
public static Locale[] getAvailableLocales()
|
||||
{
|
||||
return ICULocaleData.getAvailableLocales("DateTimePatterns");
|
||||
return ICULocaleData.getAvailableLocales();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
*******************************************************************************
|
||||
*
|
||||
* $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/text/NumberFormat.java,v $
|
||||
* $Date: 2002/09/14 21:36:28 $
|
||||
* $Revision: 1.14 $
|
||||
* $Date: 2002/10/02 20:20:21 $
|
||||
* $Revision: 1.15 $
|
||||
*
|
||||
*****************************************************************************************
|
||||
*/
|
||||
|
@ -21,6 +21,7 @@ import java.text.FieldPosition;
|
|||
import java.text.Format;
|
||||
import java.text.ParseException;
|
||||
import java.text.ParsePosition;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Locale;
|
||||
|
@ -162,7 +163,7 @@ import com.ibm.icu.impl.LocaleUtility;
|
|||
*
|
||||
* see DecimalFormat
|
||||
* see java.text.ChoiceFormat
|
||||
* @version $Revision: 1.14 $
|
||||
* @version $Revision: 1.15 $
|
||||
* @author Mark Davis
|
||||
* @author Helena Shih
|
||||
* @author Alan Liu
|
||||
|
@ -483,18 +484,19 @@ public abstract class NumberFormat extends Format{
|
|||
public static final int FORMAT_INTEGER = INTEGERSTYLE;
|
||||
|
||||
/**
|
||||
* Return true if this factory will 'hide' other locales that
|
||||
* Return true if this factory will 'cover' other locales that
|
||||
* are more specific than the ones in this factory. E.g., if
|
||||
* this 'hides' other locales, then by supporting the 'en'
|
||||
* this 'covers' other locales, then by supporting the 'en'
|
||||
* locale, this also supports 'en_US', 'en_US_ETC' and so on,
|
||||
* even though only the 'en' locale is listed.
|
||||
*/
|
||||
public abstract boolean hasGenericLocales();
|
||||
public abstract boolean covers();
|
||||
|
||||
/**
|
||||
* Return an array of the locales directly supported by this factory.
|
||||
* Return an unmodifiable collection of the locale names directly
|
||||
* supported by this factory.
|
||||
*/
|
||||
public abstract Locale[] getSupportedLocales();
|
||||
public abstract Set getSupportedLocaleNames();
|
||||
|
||||
/**
|
||||
* Return a number format of the appropriate type. If the locale
|
||||
|
@ -505,20 +507,20 @@ public abstract class NumberFormat extends Format{
|
|||
}
|
||||
|
||||
public static abstract class SimpleNumberFormatFactory extends NumberFormatFactory {
|
||||
final Locale locale;
|
||||
final boolean isGeneric;
|
||||
final Set localeNames;
|
||||
final boolean covers;
|
||||
|
||||
public SimpleNumberFormatFactory(Locale locale, boolean isGeneric) {
|
||||
this.locale = locale;
|
||||
this.isGeneric = isGeneric;
|
||||
public SimpleNumberFormatFactory(Locale locale, boolean covers) {
|
||||
localeNames = Collections.singleton(LocaleUtility.canonicalLocaleString(locale));
|
||||
this.covers = covers;
|
||||
}
|
||||
|
||||
public final boolean hasGenericLocales() {
|
||||
return isGeneric;
|
||||
public final boolean covers() {
|
||||
return covers;
|
||||
}
|
||||
|
||||
public final Locale[] getSupportedLocales() {
|
||||
return new Locale[] { locale };
|
||||
public final Set getSupportedLocaleNames() {
|
||||
return localeNames;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -526,25 +528,17 @@ public abstract class NumberFormat extends Format{
|
|||
private NumberFormatFactory delegate;
|
||||
|
||||
NFFactory(NumberFormatFactory delegate) {
|
||||
super(true, delegate.hasGenericLocales());
|
||||
super(delegate.covers() ? VISIBLE_COVERS : VISIBLE);
|
||||
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
protected Object handleCreate(Key key) {
|
||||
NFKey nfkey = (NFKey)key;
|
||||
Locale loc = nfkey.canonicalLocale();
|
||||
int choice = nfkey.choice();
|
||||
return delegate.createFormat(loc, choice);
|
||||
protected Object handleCreate(Locale loc, int kind) {
|
||||
return delegate.createFormat(loc, kind);
|
||||
}
|
||||
|
||||
protected Set handleGetSupportedIDs() {
|
||||
Locale[] locales = delegate.getSupportedLocales();
|
||||
Set result = new HashSet();
|
||||
for (int i = 0; i < locales.length; ++i) {
|
||||
result.add(locales.toString());
|
||||
}
|
||||
return result;
|
||||
protected Set getSupportedIDs() {
|
||||
return delegate.getSupportedLocaleNames();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -553,30 +547,10 @@ public abstract class NumberFormat extends Format{
|
|||
* @return available locales
|
||||
*/
|
||||
public static Locale[] getAvailableLocales() {
|
||||
// return ICULocaleData.getAvailableLocales("NumberPatterns");
|
||||
return getService().getAvailableLocales();
|
||||
}
|
||||
|
||||
private static final class NFKey extends LocaleKey {
|
||||
private int choice;
|
||||
|
||||
private static String[] CHOICE_NAMES = {
|
||||
"number", "currency", "percent", "scientific", "integer"
|
||||
};
|
||||
|
||||
private NFKey(String id, String canonicalID, String canonicalFallback, int choice) {
|
||||
super(id, canonicalID, canonicalFallback, CHOICE_NAMES[choice]);
|
||||
this.choice = choice;
|
||||
}
|
||||
|
||||
int choice() {
|
||||
return choice;
|
||||
}
|
||||
|
||||
static NFKey createKey(ICULocaleService service, Locale locale, int choice) {
|
||||
String id = LocaleUtility.canonicalLocaleString(locale.toString());
|
||||
String fallback = service.validateFallbackLocale();
|
||||
return new NFKey(id, id, fallback, choice);
|
||||
if (service == null) {
|
||||
return ICULocaleData.getAvailableLocales();
|
||||
} else {
|
||||
return service.getAvailableLocales();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -597,46 +571,36 @@ public abstract class NumberFormat extends Format{
|
|||
* registerInstance).
|
||||
*/
|
||||
public static boolean unregister(Object registryKey) {
|
||||
return getService().unregisterFactory((Factory)registryKey);
|
||||
if (service == null) {
|
||||
return false;
|
||||
} else {
|
||||
return service.unregisterFactory((Factory)registryKey);
|
||||
}
|
||||
}
|
||||
|
||||
private static ICULocaleService service = null;
|
||||
private static ICULocaleService getService() {
|
||||
if (service == null) {
|
||||
|
||||
final String[][] pattern = {
|
||||
new String[] { "NumberPatterns" },
|
||||
new String[] { "NumberElements" },
|
||||
new String[] { "CurrencyElements" },
|
||||
};
|
||||
|
||||
class RBNumberFormatFactory extends ICUResourceBundleFactory {
|
||||
RBNumberFormatFactory() {
|
||||
super ("LocaleElements", pattern, true, true);
|
||||
}
|
||||
|
||||
protected Object handleCreate(Key key) {
|
||||
NFKey nfkey = (NFKey)key;
|
||||
Locale locale = nfkey.currentLocale();
|
||||
// System.out.println("testing locale: " + locale);
|
||||
if (acceptsLocale(locale)) {
|
||||
// System.out.println("creating with locale: " + nfkey.canonicalLocale());
|
||||
return createInstance(nfkey.canonicalLocale(), nfkey.choice());
|
||||
}
|
||||
// System.out.println("did not support locale");
|
||||
return null;
|
||||
protected Object handleCreate(Locale loc, int kind) {
|
||||
return createInstance(loc, kind);
|
||||
}
|
||||
}
|
||||
|
||||
ICULocaleService newService = new ICULocaleService("NumberFormat");
|
||||
|
||||
newService.registerFactory(new RBNumberFormatFactory());
|
||||
|
||||
service = newService; // atomic
|
||||
|
||||
synchronized (NumberFormat.class) {
|
||||
if (service == null) {
|
||||
service = newService;
|
||||
}
|
||||
}
|
||||
}
|
||||
return service;
|
||||
}
|
||||
|
||||
// ===== End of factory stuff =====
|
||||
|
||||
/**
|
||||
* Overrides hashCode
|
||||
*/
|
||||
|
@ -800,8 +764,7 @@ public abstract class NumberFormat extends Format{
|
|||
// Hook for service
|
||||
private static NumberFormat getInstance(Locale desiredLocale, int choice) {
|
||||
ICULocaleService service = getService();
|
||||
NFKey key = NFKey.createKey(service, desiredLocale, choice);
|
||||
NumberFormat result = (NumberFormat)service.getKey(key);
|
||||
NumberFormat result = (NumberFormat)service.get(desiredLocale, choice);
|
||||
|
||||
//System.out.println("desired locale: " + desiredLocale + " service result:" + result);
|
||||
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
*******************************************************************************
|
||||
*
|
||||
* $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/util/BuddhistCalendar.java,v $
|
||||
* $Date: 2002/02/16 03:06:24 $
|
||||
* $Revision: 1.8 $
|
||||
* $Date: 2002/10/02 20:20:25 $
|
||||
* $Revision: 1.9 $
|
||||
*
|
||||
*****************************************************************************************
|
||||
*/
|
||||
|
@ -187,4 +187,20 @@ public class BuddhistCalendar extends GregorianCalendar {
|
|||
}
|
||||
return super.handleGetLimit(field, limitType);
|
||||
}
|
||||
|
||||
private static CalendarFactory factory;
|
||||
public static CalendarFactory factory() {
|
||||
if (factory == null) {
|
||||
factory = new CalendarFactory() {
|
||||
public Calendar create(TimeZone tz, Locale loc) {
|
||||
return new BuddhistCalendar(tz, loc);
|
||||
}
|
||||
|
||||
public String factoryName() {
|
||||
return "Buddhist";
|
||||
}
|
||||
};
|
||||
}
|
||||
return factory;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,14 @@
|
|||
package com.ibm.icu.util;
|
||||
|
||||
import com.ibm.icu.impl.ICULocaleData;
|
||||
import com.ibm.icu.impl.ICUService;
|
||||
import com.ibm.icu.impl.ICUService.Key;
|
||||
import com.ibm.icu.impl.ICUService.Factory;
|
||||
import com.ibm.icu.impl.ICULocaleService;
|
||||
import com.ibm.icu.impl.ICULocaleService.ICUResourceBundleFactory;
|
||||
import com.ibm.icu.impl.ICULocaleService.LocaleKey;
|
||||
import com.ibm.icu.impl.ICULocaleService.LocaleKeyFactory;
|
||||
import com.ibm.icu.impl.LocaleUtility;
|
||||
import com.ibm.icu.text.DateFormat;
|
||||
import com.ibm.icu.text.DateFormatSymbols;
|
||||
import com.ibm.icu.text.SimpleDateFormat;
|
||||
|
@ -16,11 +24,15 @@ import java.io.ObjectInputStream;
|
|||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.Hashtable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* <code>Calendar</code> is an abstract base class for converting between
|
||||
|
@ -620,7 +632,7 @@ import java.util.ResourceBundle;
|
|||
* @see GregorianCalendar
|
||||
* @see TimeZone
|
||||
* @see DateFormat
|
||||
* @version $Revision: 1.30 $ $Date: 2002/08/21 18:39:56 $
|
||||
* @version $Revision: 1.31 $ $Date: 2002/10/02 20:20:25 $
|
||||
* @author Mark Davis, David Goldsmith, Chen-Lieh Huang, Alan Liu, Laura Werner
|
||||
* @since JDK1.1
|
||||
*/
|
||||
|
@ -1422,7 +1434,7 @@ public abstract class Calendar implements Serializable, Cloneable {
|
|||
*/
|
||||
public static synchronized Calendar getInstance()
|
||||
{
|
||||
return new GregorianCalendar();
|
||||
return getInstance(TimeZone.getDefault(), Locale.getDefault(), null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1432,7 +1444,7 @@ public abstract class Calendar implements Serializable, Cloneable {
|
|||
*/
|
||||
public static synchronized Calendar getInstance(TimeZone zone)
|
||||
{
|
||||
return new GregorianCalendar(zone, Locale.getDefault());
|
||||
return getInstance(zone, Locale.getDefault(), null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1442,7 +1454,7 @@ public abstract class Calendar implements Serializable, Cloneable {
|
|||
*/
|
||||
public static synchronized Calendar getInstance(Locale aLocale)
|
||||
{
|
||||
return new GregorianCalendar(TimeZone.getDefault(), aLocale);
|
||||
return getInstance(TimeZone.getDefault(), aLocale, null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1452,20 +1464,138 @@ public abstract class Calendar implements Serializable, Cloneable {
|
|||
* @return a Calendar.
|
||||
*/
|
||||
public static synchronized Calendar getInstance(TimeZone zone,
|
||||
Locale aLocale)
|
||||
Locale aLocale) {
|
||||
return getInstance(zone, aLocale, null);
|
||||
}
|
||||
|
||||
// ==== Factory Stuff ====
|
||||
|
||||
/**
|
||||
* Return a calendar of for the TimeZone and locale. If calType is
|
||||
* not null, looks in the collection of CalendarFactories for a match
|
||||
* and uses that factory to instantiate the calendar. Otherwise, it
|
||||
* uses the default factory that has been registered for that locale.
|
||||
*/
|
||||
public static synchronized Calendar getInstance(TimeZone zone,
|
||||
Locale locale,
|
||||
String factoryName)
|
||||
{
|
||||
return new GregorianCalendar(zone, aLocale);
|
||||
CalendarFactory factory = null;
|
||||
if (factoryName != null) {
|
||||
factory = (CalendarFactory)getFactoryMap().get(factoryName);
|
||||
}
|
||||
|
||||
if (factory == null && service != null) {
|
||||
factory = (CalendarFactory)service.get(locale);
|
||||
}
|
||||
|
||||
if (factory == null) {
|
||||
return new GregorianCalendar(zone, locale);
|
||||
} else {
|
||||
return factory.create(zone, locale);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the list of locales for which Calendars are installed.
|
||||
* @return the list of locales for which Calendars are installed.
|
||||
*/
|
||||
public static synchronized Locale[] getAvailableLocales()
|
||||
public static Locale[] getAvailableLocales()
|
||||
{
|
||||
return DateFormat.getAvailableLocales();
|
||||
return service == null
|
||||
? ICULocaleData.getAvailableLocales()
|
||||
: service.getAvailableLocales();
|
||||
}
|
||||
|
||||
private static Map factoryMap;
|
||||
private static Map getFactoryMap() {
|
||||
if (factoryMap == null) {
|
||||
Map m = new HashMap(5);
|
||||
addFactory(m, BuddhistCalendar.factory());
|
||||
addFactory(m, ChineseCalendar.factory());
|
||||
addFactory(m, GregorianCalendar.factory());
|
||||
addFactory(m, HebrewCalendar.factory());
|
||||
addFactory(m, IslamicCalendar.factory());
|
||||
addFactory(m, JapaneseCalendar.factory());
|
||||
factoryMap = m;
|
||||
}
|
||||
return factoryMap;
|
||||
}
|
||||
|
||||
private static void addFactory(Map m, CalendarFactory f) {
|
||||
m.put(f.factoryName(), f);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a set of all the registered calendar factory names.
|
||||
*/
|
||||
public static Set getCalendarFactoryNames() {
|
||||
return Collections.unmodifiableSet(getFactoryMap().keySet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a new CalendarFactory. getInstance(TimeZone, Locale, String) will
|
||||
* try to locate a registered factories matching the factoryName. Only registered
|
||||
* factories will be found.
|
||||
*/
|
||||
public static void registerFactory(CalendarFactory factory) {
|
||||
if (factory == null) {
|
||||
throw new IllegalArgumentException("Factory must not be null");
|
||||
}
|
||||
getFactoryMap().put(factory.factoryName(), factory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a default CalendarFactory for the provided locale.
|
||||
* If covers is true, this factory is also used for all locales
|
||||
* that are more specific than the provided locale. The returned
|
||||
* object is a key that can be used to unregister this
|
||||
* CalendarFactory. If the factory has not already been
|
||||
* registered with registerFactory, it will be.
|
||||
*/
|
||||
public static Object register(CalendarFactory factory, Locale locale, boolean covers) {
|
||||
if (factory == null) {
|
||||
throw new IllegalArgumentException("calendar must not be null");
|
||||
}
|
||||
registerFactory(factory);
|
||||
return getService().registerObject(factory, locale, covers
|
||||
? LocaleKeyFactory.VISIBLE_COVERS
|
||||
: LocaleKeyFactory.VISIBLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister the CalendarFactory associated with this key
|
||||
* (obtained from register).
|
||||
*/
|
||||
public static boolean unregister(Object registryKey) {
|
||||
return service == null
|
||||
? false
|
||||
: service.unregisterFactory((Factory)registryKey);
|
||||
}
|
||||
|
||||
private static ICULocaleService service = null;
|
||||
private static ICULocaleService getService() {
|
||||
if (service == null) {
|
||||
ICULocaleService newService = new ICULocaleService("Calendar");
|
||||
|
||||
class RBCalendarFactory extends ICUResourceBundleFactory {
|
||||
protected Object handleCreate(Locale locale, int kind) {
|
||||
return GregorianCalendar.factory();
|
||||
}
|
||||
}
|
||||
|
||||
newService.registerFactory(new RBCalendarFactory());
|
||||
synchronized (Calendar.class) {
|
||||
if (service == null) {
|
||||
service = newService;
|
||||
}
|
||||
}
|
||||
}
|
||||
return service;
|
||||
}
|
||||
|
||||
// ==== End of factory Stuff ====
|
||||
|
||||
/**
|
||||
* Gets this Calendar's current time.
|
||||
* @return the current time.
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
* others. All Rights Reserved.
|
||||
*********************************************************************
|
||||
* $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/util/ChineseCalendar.java,v $
|
||||
* $Date: 2002/02/16 03:06:26 $
|
||||
* $Revision: 1.10 $
|
||||
* $Date: 2002/10/02 20:20:25 $
|
||||
* $Revision: 1.11 $
|
||||
*/
|
||||
package com.ibm.icu.util;
|
||||
import com.ibm.icu.lang.*;
|
||||
|
@ -550,8 +550,14 @@ public class ChineseCalendar extends Calendar {
|
|||
*/
|
||||
private boolean hasNoMajorSolarTerm(int newMoon) {
|
||||
|
||||
int mst = majorSolarTerm(newMoon);
|
||||
int nmn = newMoonNear(newMoon + SYNODIC_GAP, true);
|
||||
int mstt = majorSolarTerm(nmn);
|
||||
return mst == mstt;
|
||||
/*
|
||||
return majorSolarTerm(newMoon) ==
|
||||
majorSolarTerm(newMoonNear(newMoon + SYNODIC_GAP, true));
|
||||
*/
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
|
@ -779,4 +785,20 @@ public class ChineseCalendar extends Calendar {
|
|||
|
||||
return julianDay - 1;
|
||||
}
|
||||
|
||||
private static CalendarFactory factory;
|
||||
public static CalendarFactory factory() {
|
||||
if (factory == null) {
|
||||
factory = new CalendarFactory() {
|
||||
public Calendar create(TimeZone tz, Locale loc) {
|
||||
return new ChineseCalendar(tz, loc);
|
||||
}
|
||||
|
||||
public String factoryName() {
|
||||
return "Chinese";
|
||||
}
|
||||
};
|
||||
}
|
||||
return factory;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
*******************************************************************************
|
||||
*
|
||||
* $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/util/Currency.java,v $
|
||||
* $Date: 2002/09/14 21:36:30 $
|
||||
* $Revision: 1.6 $
|
||||
* $Date: 2002/10/02 20:20:25 $
|
||||
* $Revision: 1.7 $
|
||||
*
|
||||
*******************************************************************************
|
||||
*/
|
||||
|
@ -56,20 +56,23 @@ public class Currency implements Serializable {
|
|||
|
||||
private static ICULocaleService getService() {
|
||||
if (service == null) {
|
||||
service = new ICULocaleService("Currency");
|
||||
ICULocaleService newService = new ICULocaleService("Currency");
|
||||
|
||||
class CurrencyFactory extends ICUResourceBundleFactory {
|
||||
CurrencyFactory() {
|
||||
super("CurrencyElements", true);
|
||||
}
|
||||
|
||||
protected Object createFromBundle(ResourceBundle bundle, Key key) {
|
||||
protected Object handleCreate(Locale loc, int kind) {
|
||||
ResourceBundle bundle = ICULocaleData.getLocaleElements(loc);
|
||||
String[] ce = bundle.getStringArray("CurrencyElements");
|
||||
// System.out.println("currency factory loc: " + loc + " rb: " + bundle + "ce[1]" + ce[1]);
|
||||
return new Currency(ce[1]);
|
||||
}
|
||||
}
|
||||
|
||||
service.registerFactory(new CurrencyFactory());
|
||||
|
||||
newService.registerFactory(new CurrencyFactory());
|
||||
synchronized (Currency.class) {
|
||||
if (service == null) {
|
||||
service = newService;
|
||||
}
|
||||
}
|
||||
}
|
||||
return service;
|
||||
}
|
||||
|
|
|
@ -902,4 +902,20 @@ public class GregorianCalendar extends Calendar {
|
|||
|
||||
return julianDay;
|
||||
}
|
||||
|
||||
private static CalendarFactory factory;
|
||||
public static CalendarFactory factory() {
|
||||
if (factory == null) {
|
||||
factory = new CalendarFactory() {
|
||||
public Calendar create(TimeZone tz, Locale loc) {
|
||||
return new GregorianCalendar(tz, loc);
|
||||
}
|
||||
|
||||
public String factoryName() {
|
||||
return "Gregorian";
|
||||
}
|
||||
};
|
||||
}
|
||||
return factory;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
*******************************************************************************
|
||||
*
|
||||
* $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/util/HebrewCalendar.java,v $
|
||||
* $Date: 2002/08/07 03:10:20 $
|
||||
* $Revision: 1.9 $
|
||||
* $Date: 2002/10/02 20:20:24 $
|
||||
* $Revision: 1.10 $
|
||||
*
|
||||
*****************************************************************************************
|
||||
*/
|
||||
|
@ -765,4 +765,20 @@ public class HebrewCalendar extends Calendar {
|
|||
|
||||
return (int) (day + 347997);
|
||||
}
|
||||
|
||||
private static CalendarFactory factory;
|
||||
public static CalendarFactory factory() {
|
||||
if (factory == null) {
|
||||
factory = new CalendarFactory() {
|
||||
public Calendar create(TimeZone tz, Locale loc) {
|
||||
return new HebrewCalendar(tz, loc);
|
||||
}
|
||||
|
||||
public String factoryName() {
|
||||
return "Hebrew";
|
||||
}
|
||||
};
|
||||
}
|
||||
return factory;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
*******************************************************************************
|
||||
*
|
||||
* $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/util/IslamicCalendar.java,v $
|
||||
* $Date: 2002/08/07 03:10:18 $
|
||||
* $Revision: 1.11 $
|
||||
* $Date: 2002/10/02 20:20:24 $
|
||||
* $Revision: 1.12 $
|
||||
*
|
||||
*****************************************************************************************
|
||||
*/
|
||||
|
@ -560,4 +560,20 @@ public class IslamicCalendar extends Calendar {
|
|||
internalSet(DAY_OF_MONTH, dayOfMonth);
|
||||
internalSet(DAY_OF_YEAR, dayOfYear);
|
||||
}
|
||||
|
||||
private static CalendarFactory factory;
|
||||
public static CalendarFactory factory() {
|
||||
if (factory == null) {
|
||||
factory = new CalendarFactory() {
|
||||
public Calendar create(TimeZone tz, Locale loc) {
|
||||
return new IslamicCalendar(tz, loc);
|
||||
}
|
||||
|
||||
public String factoryName() {
|
||||
return "Islamic";
|
||||
}
|
||||
};
|
||||
}
|
||||
return factory;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
*******************************************************************************
|
||||
*
|
||||
* $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/util/JapaneseCalendar.java,v $
|
||||
* $Date: 2002/02/16 03:06:29 $
|
||||
* $Revision: 1.8 $
|
||||
* $Date: 2002/10/02 20:20:24 $
|
||||
* $Revision: 1.9 $
|
||||
*
|
||||
*****************************************************************************************
|
||||
*/
|
||||
|
@ -535,4 +535,20 @@ public class JapaneseCalendar extends GregorianCalendar {
|
|||
return super.handleGetLimit(field, limitType);
|
||||
}
|
||||
}
|
||||
|
||||
private static CalendarFactory factory;
|
||||
public static CalendarFactory factory() {
|
||||
if (factory == null) {
|
||||
factory = new CalendarFactory() {
|
||||
public Calendar create(TimeZone tz, Locale loc) {
|
||||
return new JapaneseCalendar(tz, loc);
|
||||
}
|
||||
|
||||
public String factoryName() {
|
||||
return "Japanese";
|
||||
}
|
||||
};
|
||||
}
|
||||
return factory;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue