ICU-2203 (also 1949) service registration for number format, and
associated changes to service APIs X-SVN-Rev: 9860
This commit is contained in:
parent
821c8a97b5
commit
daf555a88b
@ -1,7 +1,7 @@
|
||||
/*****************************************************************************************
|
||||
* $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/dev/test/format/NumberRegression.java,v $
|
||||
* $Date: 2002/08/21 00:05:59 $
|
||||
* $Revision: 1.11 $
|
||||
* $Date: 2002/09/14 21:36:28 $
|
||||
* $Revision: 1.12 $
|
||||
*
|
||||
*****************************************************************************************
|
||||
**/
|
||||
@ -634,7 +634,7 @@ public class NumberRegression extends com.ibm.icu.dev.test.TestFmwk {
|
||||
if (tempString.equals(expectedDefault)) {
|
||||
logln ("Bug 4071859 default test passed.");
|
||||
} else {
|
||||
errln("Failed:" +
|
||||
errln("a) Failed:" +
|
||||
" Expected " + expectedDefault +
|
||||
" Received " + tempString );
|
||||
}
|
||||
@ -645,7 +645,7 @@ public class NumberRegression extends com.ibm.icu.dev.test.TestFmwk {
|
||||
if (tempString.equals(expectedCurrency) ) {
|
||||
logln ("Bug 4071859 currency test passed.");
|
||||
} else {
|
||||
errln("Failed:" +
|
||||
errln("b) Failed:" +
|
||||
" Expected " + expectedCurrency +
|
||||
" Received " + tempString );
|
||||
}
|
||||
@ -656,7 +656,7 @@ public class NumberRegression extends com.ibm.icu.dev.test.TestFmwk {
|
||||
if (tempString.equals(expectedPercent) ) {
|
||||
logln ("Bug 4071859 percentage test passed.");
|
||||
} else {
|
||||
errln("Failed:" +
|
||||
errln("c) Failed:" +
|
||||
" Expected " + expectedPercent +
|
||||
" Received " + tempString );
|
||||
}
|
||||
|
@ -5,8 +5,8 @@
|
||||
*******************************************************************************
|
||||
*
|
||||
* $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/dev/test/util/ICUServiceTest.java,v $
|
||||
* $Date: 2002/08/13 22:10:20 $
|
||||
* $Revision: 1.4 $
|
||||
* $Date: 2002/09/14 21:36:30 $
|
||||
* $Revision: 1.5 $
|
||||
*
|
||||
*******************************************************************************
|
||||
*/
|
||||
@ -30,6 +30,7 @@ import com.ibm.icu.impl.ICULocaleService.ICUResourceBundleFactory;
|
||||
import java.util.Arrays;
|
||||
import java.util.EventListener;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
@ -479,11 +480,10 @@ public class ICUServiceTest extends TestFmwk
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void handleUpdateVisibleIDs(Set result) {
|
||||
for (int i = 0; i < ids.length; ++i) {
|
||||
result.add(ids[i]);
|
||||
}
|
||||
protected Set handleGetSupportedIDs() {
|
||||
return new HashSet(Arrays.asList(ids));
|
||||
}
|
||||
|
||||
protected String handleGetDisplayName(String id, Locale locale) {
|
||||
return factoryID + LocaleUtility.getLocaleFromName(id).getDisplayName(locale);
|
||||
}
|
||||
@ -544,13 +544,15 @@ public class ICUServiceTest extends TestFmwk
|
||||
private static String surfer = californio + "_SURFER";
|
||||
private static String geek = californio + "_GEEK";
|
||||
|
||||
public void handleUpdateVisibleIDs(Set result) {
|
||||
super.handleUpdateVisibleIDs(result);
|
||||
public Set handleGetSupportedIDs() {
|
||||
Set result = super.handleGetSupportedIDs();
|
||||
|
||||
result.add(californio);
|
||||
result.add(valley);
|
||||
result.add(surfer);
|
||||
result.add(geek);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected String handleGetDisplayName(String id, Locale locale) {
|
||||
@ -620,6 +622,11 @@ public class ICUServiceTest extends TestFmwk
|
||||
confirmEqual("test with en locale", "root", target);
|
||||
}
|
||||
|
||||
public void errln(String msg) {
|
||||
System.out.println(msg);
|
||||
(new String[0])[1] = "foo";
|
||||
}
|
||||
|
||||
// misc coverage tests
|
||||
public void TestCoverage() {
|
||||
// Key
|
||||
@ -640,7 +647,7 @@ public class ICUServiceTest extends TestFmwk
|
||||
logln("OK: " + e.getMessage());
|
||||
}
|
||||
catch (Exception e) {
|
||||
errln("threw wrong exception");
|
||||
errln("threw wrong exception" + e);
|
||||
}
|
||||
logln(sf.getDisplayName("object", null));
|
||||
|
||||
@ -655,10 +662,11 @@ public class ICUServiceTest extends TestFmwk
|
||||
catch (NullPointerException e) {
|
||||
logln("OK: " + e.getMessage());
|
||||
}
|
||||
/*
|
||||
catch (Exception e) {
|
||||
errln("threw wrong exception");
|
||||
errln("threw wrong exception" + e);
|
||||
}
|
||||
|
||||
*/
|
||||
try {
|
||||
service.registerFactory(null);
|
||||
errln("didn't throw exception");
|
||||
@ -667,7 +675,7 @@ public class ICUServiceTest extends TestFmwk
|
||||
logln("OK: " + e.getMessage());
|
||||
}
|
||||
catch (Exception e) {
|
||||
errln("threw wrong exception");
|
||||
errln("threw wrong exception" + e);
|
||||
}
|
||||
|
||||
try {
|
||||
@ -678,7 +686,7 @@ public class ICUServiceTest extends TestFmwk
|
||||
logln("OK: " + e.getMessage());
|
||||
}
|
||||
catch (Exception e) {
|
||||
errln("threw wrong exception");
|
||||
errln("threw wrong exception" + e);
|
||||
}
|
||||
|
||||
logln("object is: " + service.get("object"));
|
||||
@ -718,9 +726,9 @@ public class ICUServiceTest extends TestFmwk
|
||||
}
|
||||
|
||||
// LocaleKey
|
||||
LocaleKey lkey = LocaleKey.create("en_US", "ja_JP");
|
||||
lkey = LocaleKey.create(null, null);
|
||||
lkey = LocaleKey.createWithCanonical("en_US", "ja_JP");
|
||||
// LocaleKey lkey = LocaleKey.create("en_US", "ja_JP");
|
||||
// lkey = LocaleKey.create(null, null);
|
||||
LocaleKey lkey = LocaleKey.createWithCanonicalFallback("en_US", "ja_JP");
|
||||
|
||||
// MultipleKeyFactory
|
||||
MultipleKeyFactory mkf = new MKFSubclass(false);
|
||||
@ -736,10 +744,10 @@ public class ICUServiceTest extends TestFmwk
|
||||
invisibleMKF.updateVisibleIDs(new HashMap());
|
||||
|
||||
// ResourceBundleFactory
|
||||
ICUResourceBundleFactory rbf = new ICUResourceBundleFactory(null, true);
|
||||
ICUResourceBundleFactory rbf = new ICUResourceBundleFactory(true);
|
||||
logln("RB: " + rbf.create(lkey));
|
||||
LocaleKey nokey = LocaleKey.create(null, null);
|
||||
logln("RB: " + rbf.create(nokey));
|
||||
// LocaleKey nokey = LocaleKey.create(null, null);
|
||||
// logln("RB: " + rbf.create(nokey));
|
||||
|
||||
rbf = new ICUResourceBundleFactory("foobar", true);
|
||||
logln("RB: " + rbf.create(lkey));
|
||||
@ -814,7 +822,8 @@ public class ICUServiceTest extends TestFmwk
|
||||
return null;
|
||||
}
|
||||
|
||||
public void handleUpdateVisibleIDs(Set result) {
|
||||
public Set handleGetSupportedIDs() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -185,7 +185,7 @@ public class ICULocaleData {
|
||||
* returns an 'unparented' bundle that exactly matches the bundle name and locale name.
|
||||
*/
|
||||
public static ResourceBundle loadResourceBundle(String bundleName, String localeName) {
|
||||
if (localeName != null) {
|
||||
if (localeName != null && localeName.length() > 0) {
|
||||
bundleName = bundleName + "_" + localeName;
|
||||
}
|
||||
for (int i = 0; i < packageNames.length; ++i) {
|
||||
|
@ -5,8 +5,8 @@
|
||||
*******************************************************************************
|
||||
*
|
||||
* $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/impl/ICULocaleService.java,v $
|
||||
* $Date: 2002/09/07 00:15:33 $
|
||||
* $Revision: 1.6 $
|
||||
* $Date: 2002/09/14 21:36:30 $
|
||||
* $Revision: 1.7 $
|
||||
*
|
||||
*******************************************************************************
|
||||
*/
|
||||
@ -14,25 +14,31 @@ package com.ibm.icu.impl;
|
||||
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
public class ICULocaleService extends ICUService {
|
||||
Locale fallbackLocale;
|
||||
String fallbackLocaleName;
|
||||
private Locale fallbackLocale;
|
||||
private String fallbackLocaleName;
|
||||
|
||||
/**
|
||||
* Construct an ICULocaleService with a fallback locale string based on the current
|
||||
* default locale at the time of construction.
|
||||
* Construct an ICULocaleService. This uses the current default locale as a fallback.
|
||||
*/
|
||||
public ICULocaleService() {
|
||||
fallbackLocale = Locale.getDefault();
|
||||
fallbackLocaleName = LocaleUtility.canonicalLocaleString(fallbackLocale.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an ICULocaleService with a name (useful for debugging).
|
||||
*/
|
||||
public ICULocaleService(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -45,13 +51,15 @@ public class ICULocaleService extends ICUService {
|
||||
/**
|
||||
* Convenience override for callers using locales.
|
||||
*/
|
||||
public Object get(Locale locale, Locale[] actualLocaleReturn) {
|
||||
if (actualLocaleReturn == null) {
|
||||
public Object get(Locale locale, Locale[] actualReturn) {
|
||||
if (actualReturn == null) {
|
||||
return get(locale.toString());
|
||||
}
|
||||
String[] temp = new String[1];
|
||||
Object result = get(locale.toString(), temp);
|
||||
actualLocaleReturn[0] = LocaleUtility.getLocaleFromName(temp[0]);
|
||||
if (result != null) {
|
||||
actualReturn[0] = LocaleUtility.getLocaleFromName(temp[0]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -70,14 +78,13 @@ public class ICULocaleService extends ICUService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method for callers using locales. This is the typical
|
||||
* current API for this operation.
|
||||
* Convenience method for callers using locales. This is the
|
||||
* current typical API for this operation, though perhaps it should change.
|
||||
*/
|
||||
public Locale[] getAvailableLocales() {
|
||||
TreeSet sort = new TreeSet(String.CASE_INSENSITIVE_ORDER);
|
||||
sort.addAll(getVisibleIDs());
|
||||
Iterator iter = sort.iterator();
|
||||
Locale[] locales = new Locale[sort.size()];
|
||||
Set visIDs = getVisibleIDs();
|
||||
Iterator iter = visIDs.iterator();
|
||||
Locale[] locales = new Locale[visIDs.size()];
|
||||
int n = 0;
|
||||
while (iter.hasNext()) {
|
||||
Locale loc = LocaleUtility.getLocaleFromName((String)iter.next());
|
||||
@ -89,42 +96,34 @@ public class ICULocaleService extends ICUService {
|
||||
/**
|
||||
* A subclass of Key that implements a locale fallback mechanism.
|
||||
* The first locale to search for is the locale provided by the
|
||||
* client, and the fallback locale to search for is the current default
|
||||
* locale. This is instantiated by ICULocaleService.</p>
|
||||
* client, and the fallback locale to search for is the current
|
||||
* default locale. If a prefix is present, the currentDescriptor
|
||||
* includes it before the locale proper, separated by "/". This
|
||||
* is the default key instantiated by ICULocaleService.</p>
|
||||
*
|
||||
* <p>Canonicalization adjusts the locale string so that the
|
||||
* section before the first understore is in lower case, and the rest
|
||||
* is in upper case, with no trailing underscores.</p>
|
||||
* is in upper case, with no trailing underscores.</p>
|
||||
*/
|
||||
public static class LocaleKey extends ICUService.Key {
|
||||
private String prefix;
|
||||
private String primaryID;
|
||||
private String fallbackID;
|
||||
private String currentID;
|
||||
|
||||
/**
|
||||
* Convenience method for createWithCanonical that canonicalizes both the
|
||||
* primary and fallback IDs first.
|
||||
*/
|
||||
public static LocaleKey create(String primaryID, String fallbackID) {
|
||||
String canonicalPrimaryID = LocaleUtility.canonicalLocaleString(primaryID);
|
||||
String canonicalFallbackID = LocaleUtility.canonicalLocaleString(fallbackID);
|
||||
return new LocaleKey(primaryID, canonicalPrimaryID, canonicalFallbackID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method for createWithCanonical that canonicalizes the
|
||||
* primary ID first, the fallback is assumed to already be canonical.
|
||||
* Create a LocaleKey with canonical primary and fallback IDs.
|
||||
*/
|
||||
public static LocaleKey createWithCanonicalFallback(String primaryID, String canonicalFallbackID) {
|
||||
String canonicalPrimaryID = LocaleUtility.canonicalLocaleString(primaryID);
|
||||
return new LocaleKey(primaryID, canonicalPrimaryID, canonicalFallbackID);
|
||||
return createWithCanonicalFallback(primaryID, canonicalFallbackID, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a LocaleKey with canonical primary and fallback IDs.
|
||||
*/
|
||||
public static LocaleKey createWithCanonical(String canonicalPrimaryID, String canonicalFallbackID) {
|
||||
return new LocaleKey(canonicalPrimaryID, canonicalPrimaryID, canonicalFallbackID);
|
||||
public static LocaleKey createWithCanonicalFallback(String primaryID, String canonicalFallbackID, String prefix) {
|
||||
String canonicalPrimaryID = LocaleUtility.canonicalLocaleString(primaryID);
|
||||
return new LocaleKey(primaryID, canonicalPrimaryID, canonicalFallbackID, prefix);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -133,8 +132,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) {
|
||||
protected LocaleKey(String primaryID, String canonicalPrimaryID, String canonicalFallbackID, String prefix) {
|
||||
super(primaryID);
|
||||
|
||||
this.prefix = prefix;
|
||||
|
||||
if (canonicalPrimaryID == null) {
|
||||
this.primaryID = "";
|
||||
@ -154,6 +155,13 @@ public class ICULocaleService extends ICUService {
|
||||
this.currentID = this.primaryID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the prefix, or null if none was defined.
|
||||
*/
|
||||
public String prefix() {
|
||||
return prefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the (canonical) original ID.
|
||||
*/
|
||||
@ -162,12 +170,37 @@ public class ICULocaleService extends ICUService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the (canonical) current ID.
|
||||
* Return the (canonical) current ID, or null if no current id.
|
||||
*/
|
||||
public String currentID() {
|
||||
return currentID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the (canonical) current descriptor, or null if no current id.
|
||||
*/
|
||||
public String currentDescriptor() {
|
||||
String result = currentID();
|
||||
if (result != null && prefix != null) {
|
||||
result = prefix + "/" + result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to return the locale corresponding to the (canonical) original ID.
|
||||
*/
|
||||
public Locale canonicalLocale() {
|
||||
return LocaleUtility.getLocaleFromName(primaryID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to return the locale corresponding to the (canonical) current ID.
|
||||
*/
|
||||
public Locale currentLocale() {
|
||||
return LocaleUtility.getLocaleFromName(currentID);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the key has a fallback, modify the key and return true,
|
||||
* otherwise return false.</p>
|
||||
@ -178,10 +211,9 @@ public class ICULocaleService extends ICUService {
|
||||
* there is no fallback.
|
||||
*/
|
||||
public boolean fallback() {
|
||||
String current = currentID();
|
||||
int x = current.lastIndexOf('_');
|
||||
int x = currentID.lastIndexOf('_');
|
||||
if (x != -1) {
|
||||
currentID = current.substring(0, x);
|
||||
currentID = currentID.substring(0, x);
|
||||
return true;
|
||||
}
|
||||
if (fallbackID != null) {
|
||||
@ -207,7 +239,41 @@ public class ICULocaleService extends ICUService {
|
||||
public static abstract class MultipleKeyFactory implements ICUService.Factory {
|
||||
protected final boolean visible;
|
||||
private SoftReference cacheref;
|
||||
private boolean included;
|
||||
|
||||
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
|
||||
@ -227,62 +293,58 @@ public class ICULocaleService extends ICUService {
|
||||
/**
|
||||
* 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. Note that if
|
||||
* the cache has been freed by gc, we reset the included flag, so
|
||||
* it must not be tested before this method is called.
|
||||
* we do know we understand, if included is true. If the cache has
|
||||
* been flushed, included is false.
|
||||
*/
|
||||
private HashSet getCache() {
|
||||
HashSet cache = null;
|
||||
private CacheInfo getCache() {
|
||||
CacheInfo result = null;
|
||||
if (cacheref != null) {
|
||||
cache = (HashSet)cacheref.get();
|
||||
result = (CacheInfo)cacheref.get();
|
||||
}
|
||||
if (cache == null) {
|
||||
cache = new HashSet();
|
||||
cacheref = new SoftReference(cache);
|
||||
included = false;
|
||||
if (result == null) {
|
||||
result = new CacheInfo();
|
||||
cacheref = new SoftReference(result);
|
||||
}
|
||||
return cache;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the cache of IDs we understand.
|
||||
*/
|
||||
private HashSet getIncludedCache() {
|
||||
HashSet cache = getCache();
|
||||
if (!included) {
|
||||
cache.clear();
|
||||
handleUpdateVisibleIDs(cache);
|
||||
included = true;
|
||||
}
|
||||
return cache;
|
||||
protected Set getSupportedIDs() {
|
||||
CacheInfo ci = getCache();
|
||||
Set result = ci.cache;
|
||||
if (!ci.included) {
|
||||
result = handleGetSupportedIDs();
|
||||
cacheref = new SoftReference(new CacheInfo(result));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public final Object create(Key key) {
|
||||
public Object create(Key key) {
|
||||
Object result = null;
|
||||
String id = key.currentID();
|
||||
HashSet cache = getCache();
|
||||
if (cache.contains(id) == included) {
|
||||
CacheInfo ci = getCache();
|
||||
if (ci.tryCreate(id)) {
|
||||
result = handleCreate(key);
|
||||
if (!included && result == null) {
|
||||
cache.add(id);
|
||||
}
|
||||
ci.addCreate(id, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public final void updateVisibleIDs(Map result) {
|
||||
public void updateVisibleIDs(Map result) {
|
||||
if (visible) {
|
||||
Set cache = getIncludedCache();
|
||||
Iterator iter = cache.iterator();
|
||||
while (iter.hasNext()) {
|
||||
result.put((String)iter.next(), this);
|
||||
}
|
||||
Iterator iter = getSupportedIDs().iterator();
|
||||
while (iter.hasNext()) {
|
||||
result.put(iter.next(), this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final String getDisplayName(String id, Locale locale) {
|
||||
public String getDisplayName(String id, Locale locale) {
|
||||
if (visible) {
|
||||
Set cache = getIncludedCache();
|
||||
Set cache = getSupportedIDs();
|
||||
if (cache.contains(id)) {
|
||||
return handleGetDisplayName(id, locale);
|
||||
}
|
||||
@ -296,11 +358,11 @@ public class ICULocaleService extends ICUService {
|
||||
protected abstract Object handleCreate(Key key);
|
||||
|
||||
/**
|
||||
* Subclasses implement this instead of updateVisibleIDs. Any
|
||||
* id known to and handled by this class should be added to
|
||||
* result.
|
||||
* Subclasses implement this instead of getSupportedIDs. Any
|
||||
* id known to and handled by this class should be included in
|
||||
* the returned Set.
|
||||
*/
|
||||
protected abstract void handleUpdateVisibleIDs(Set result);
|
||||
protected abstract Set handleGetSupportedIDs();
|
||||
|
||||
/**
|
||||
* Subclasses implement this instead of getDisplayName.
|
||||
@ -313,6 +375,64 @@ public class ICULocaleService extends ICUService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Create a LocaleKeyFactory.
|
||||
*/
|
||||
public LocaleKeyFactory(boolean visible, boolean hides) {
|
||||
super(visible);
|
||||
|
||||
this.hides = hides;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
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
|
||||
@ -325,7 +445,11 @@ public class ICULocaleService extends ICUService {
|
||||
*/
|
||||
public static class ICUResourceBundleFactory extends MultipleKeyFactory {
|
||||
protected final String name;
|
||||
protected final String[] requiredContents;
|
||||
protected final String[][] requiredContents;
|
||||
|
||||
public ICUResourceBundleFactory(boolean visible) {
|
||||
this((String)null, visible);
|
||||
}
|
||||
|
||||
/**
|
||||
* A service factory based on ICU resource data in the LocaleElements resources.
|
||||
@ -340,29 +464,89 @@ public class ICULocaleService extends ICUService {
|
||||
* listed resources must come directly from the same bundle.
|
||||
*/
|
||||
public ICUResourceBundleFactory(String name, String requiredContents, boolean visible) {
|
||||
super(visible);
|
||||
this(name, buildRcAndOr(requiredContents), true, visible);
|
||||
}
|
||||
|
||||
this.name = name;
|
||||
if (requiredContents != null) {
|
||||
private static class Node {
|
||||
public boolean test(ResourceBundle rb) {
|
||||
return rb != null;
|
||||
}
|
||||
}
|
||||
|
||||
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 = requiredContents.length();;) {
|
||||
while (i < len && requiredContents.charAt(i) == ';') {
|
||||
for (int i = 0, len = str.length();;) {
|
||||
while (i < len && str.charAt(i) == ';') {
|
||||
++i;
|
||||
}
|
||||
if (i == len) {
|
||||
break;
|
||||
}
|
||||
int j = requiredContents.indexOf(';', i);
|
||||
int j = str.indexOf(';', i);
|
||||
if (j == -1) {
|
||||
j = len;
|
||||
}
|
||||
list.add(requiredContents.substring(i, j));
|
||||
list.add(str.substring(i, j));
|
||||
i = j;
|
||||
}
|
||||
this.requiredContents = (String[])list.toArray(new String[list.size()]);
|
||||
} else {
|
||||
this.requiredContents = null;
|
||||
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;
|
||||
|
||||
if (!adopt && rcOrAnd != null) {
|
||||
rcOrAnd = (String[][])rcOrAnd.clone();
|
||||
for (int i = 0; i < rcOrAnd.length; ++i) {
|
||||
rcOrAnd[i] = (String[])(rcOrAnd[i].clone());
|
||||
}
|
||||
}
|
||||
this.requiredContents = rcOrAnd;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -384,21 +568,23 @@ public class ICULocaleService extends ICUService {
|
||||
* 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 void handleUpdateVisibleIDs(Set result) {
|
||||
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)) {
|
||||
result.add(LocaleUtility.canonicalLocaleString(locale.toString()));
|
||||
String str = LocaleUtility.canonicalLocaleString(locale.toString());
|
||||
result.add(str);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
@ -408,18 +594,41 @@ public class ICULocaleService extends ICUService {
|
||||
* inherited bundle);
|
||||
*/
|
||||
protected boolean acceptsLocale(Locale loc) {
|
||||
try {
|
||||
ResourceBundle bundle = ICULocaleData.loadResourceBundle(name, loc); // single resource bundle lookup
|
||||
if (requiredContents != null) {
|
||||
for (int i = 0; i < requiredContents.length; ++i) {
|
||||
if (bundle.getObject(requiredContents[i]) == null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
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;
|
||||
}
|
||||
|
||||
loop:
|
||||
for (int i = 0; i < requiredContents.length; ++i) {
|
||||
String[] andRC = requiredContents[i];
|
||||
|
||||
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;
|
||||
}
|
||||
@ -433,7 +642,11 @@ public class ICULocaleService extends ICUService {
|
||||
}
|
||||
}
|
||||
|
||||
protected Key createKey(String id) {
|
||||
/**
|
||||
* Return the name of the current fallback locale. If it has changed since this was
|
||||
* last accessed, the service cache is cleared.
|
||||
*/
|
||||
public String validateFallbackLocale() {
|
||||
Locale loc = Locale.getDefault();
|
||||
if (loc != fallbackLocale) {
|
||||
synchronized (this) {
|
||||
@ -444,7 +657,10 @@ public class ICULocaleService extends ICUService {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return LocaleKey.createWithCanonicalFallback(id, fallbackLocaleName);
|
||||
return fallbackLocaleName;
|
||||
}
|
||||
|
||||
protected Key createKey(String id) {
|
||||
return LocaleKey.createWithCanonicalFallback(id, validateFallbackLocale());
|
||||
}
|
||||
}
|
||||
|
@ -5,8 +5,8 @@
|
||||
*******************************************************************************
|
||||
*
|
||||
* $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/impl/ICUService.java,v $
|
||||
* $Date: 2002/08/13 23:40:52 $
|
||||
* $Revision: 1.7 $
|
||||
* $Date: 2002/09/14 21:36:29 $
|
||||
* $Revision: 1.8 $
|
||||
*
|
||||
*******************************************************************************
|
||||
*/
|
||||
@ -38,11 +38,11 @@ import java.util.TreeMap;
|
||||
* generally it should not be mutable, or the caller should clone the
|
||||
* object before modifying it.</p>
|
||||
*
|
||||
* <p>Services 'canonicalize' the query id and use the canonical id
|
||||
* to query for the service. The service also defines a mechanism
|
||||
* to 'fallback' the id multiple times. Clients can optionally
|
||||
* request the actual id that was matched by a query when they
|
||||
* use an id to retrieve a service object.</p>
|
||||
* <p>Services 'canonicalize' the query id and use the canonical id to
|
||||
* query for the service. The service also defines a mechanism to
|
||||
* 'fallback' the id multiple times. Clients can optionally request
|
||||
* the actual id that was matched by a query when they use an id to
|
||||
* retrieve a service object.</p>
|
||||
*
|
||||
* <p>Service objects are instantiated by Factory objects registered with
|
||||
* the service. The service queries each Factory in turn, from most recently
|
||||
@ -81,9 +81,25 @@ import java.util.TreeMap;
|
||||
* ICUService by overriding it, for example, to customize the Key and
|
||||
* fallback strategy. ICULocaleService is a customized service that
|
||||
* uses Locale names as ids and uses Keys that implement the standard
|
||||
* resource bundle fallback strategy.<p>
|
||||
* resource bundle fallback strategy.<p>
|
||||
*/
|
||||
public class ICUService extends ICUNotifier {
|
||||
protected final String name;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public ICUService() {
|
||||
name = "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct with a name (useful for debugging).
|
||||
*/
|
||||
public ICUService(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Access to factories is protected by a read-write lock. This is
|
||||
* to allow multiple threads to read concurrently, but keep
|
||||
@ -97,10 +113,12 @@ public class ICUService extends ICUNotifier {
|
||||
private final List factories = new ArrayList();
|
||||
|
||||
/**
|
||||
* Keys define how ids are canonicalized, and determine the
|
||||
* fallback strategy used when querying the factories. The default
|
||||
* key just takes as its canonicalID the id assigned to it when it
|
||||
* is constructed, and has no fallbacks.
|
||||
* Keys are used to communicate with factories to generate an
|
||||
* instance of the service. They 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.
|
||||
*/
|
||||
public static class Key {
|
||||
private final String id;
|
||||
@ -113,7 +131,7 @@ public class ICUService extends ICUNotifier {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the original ID.
|
||||
* Return the original ID used to construct this key.
|
||||
*/
|
||||
public final String id() {
|
||||
return id;
|
||||
@ -128,13 +146,26 @@ public class ICUService extends ICUNotifier {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the (canonical) current ID. This implementation returns the
|
||||
* canonical ID.
|
||||
* Return the (canonical) current ID. This implementation
|
||||
* returns the canonical ID.
|
||||
*/
|
||||
public String currentID() {
|
||||
return canonicalID();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public String currentDescriptor() {
|
||||
return currentID();
|
||||
}
|
||||
|
||||
/**
|
||||
* If the key has a fallback, modify the key and return true,
|
||||
* otherwise return false. The current ID will change if there
|
||||
@ -161,17 +192,18 @@ public class ICUService extends ICUNotifier {
|
||||
public Object create(Key key);
|
||||
|
||||
/**
|
||||
* Add IDs understood by this factory to the result map, with
|
||||
* this factory as the value. If this factory hides IDs
|
||||
* 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.
|
||||
*/
|
||||
* for those IDs. Result should contain only ids, not
|
||||
* descriptors.
|
||||
*/
|
||||
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.
|
||||
* return null. This is an id, not a descriptor.
|
||||
*/
|
||||
public String getDisplayName(String id, Locale locale);
|
||||
}
|
||||
@ -182,7 +214,8 @@ public class ICUService extends ICUNotifier {
|
||||
* 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.
|
||||
* mapping from id to itself. This ignores the key descriptor
|
||||
* and only examines the id.
|
||||
*/
|
||||
public static class SimpleFactory implements Factory {
|
||||
protected Object instance;
|
||||
@ -238,33 +271,55 @@ public class ICUService extends ICUNotifier {
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience override for get(String, String[]).
|
||||
* Convenience override for get(String, String[]). This uses
|
||||
* createKey to create a key for the provided descriptor.
|
||||
*/
|
||||
public Object get(String id) {
|
||||
return get(id, null);
|
||||
public Object get(String descriptor) {
|
||||
return getKey(createKey(descriptor), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Given an id, return a service object, and, if actualIDReturn
|
||||
* is not null, the actual id under which it was found in the
|
||||
* first element of actualIDReturn. If no service object matches
|
||||
* this id, return null, and leave actualIDReturn unchanged.</p>
|
||||
*
|
||||
* <p>This tries each registered factory in order, and if none can
|
||||
* generate a service object for the key, repeats the process with
|
||||
* each fallback of the key until one returns a service object, or
|
||||
* the key has no fallback.</p>
|
||||
* Convenience override for get(Key, String[]). This uses
|
||||
* createKey to create a key from the provided descriptor.
|
||||
*/
|
||||
public Object get(String id, String[] actualIDReturn) {
|
||||
if (id == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
public Object get(String descriptor, String[] actualReturn) {
|
||||
if (descriptor == null) {
|
||||
throw new NullPointerException("descriptor must not be null");
|
||||
}
|
||||
return getKey(createKey(descriptor), actualReturn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience override for get(Key, String[]).
|
||||
*/
|
||||
public Object getKey(Key key) {
|
||||
return getKey(key, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Given a key, return a service object, and, if actualReturn
|
||||
* is not null, the descriptor with which it was found in the
|
||||
* first element of actualReturn. If no service object matches
|
||||
* this key, return null, and leave actualReturn unchanged.</p>
|
||||
*
|
||||
* <p>This queries the cache using the key's descriptor, and if no
|
||||
* object in the cache matches it, tries the key on each
|
||||
* registered factory, in order. If none generates a service
|
||||
* object for the key, repeats the process with each fallback of
|
||||
* the key, until either one returns a service object, or the key
|
||||
* has no fallback.</p>
|
||||
*
|
||||
* <p>If key is null, just returns null.</p>
|
||||
*/
|
||||
public Object getKey(Key key, String[] actualReturn) {
|
||||
if (factories.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
boolean debug = false;
|
||||
if (debug) System.out.println("Service: " + name + " key: " + key);
|
||||
|
||||
CacheEntry result = null;
|
||||
Key key = createKey(id);
|
||||
if (key != null) {
|
||||
try {
|
||||
// The factory list can't be modified until we're done,
|
||||
@ -284,15 +339,19 @@ public class ICUService extends ICUNotifier {
|
||||
cref = new SoftReference(cache);
|
||||
}
|
||||
|
||||
String currentID = null;
|
||||
ArrayList cacheIDList = null;
|
||||
String currentDescriptor = null;
|
||||
ArrayList cacheDescriptorList = null;
|
||||
boolean putInCache = false;
|
||||
|
||||
int NDebug = 0;
|
||||
|
||||
outer:
|
||||
do {
|
||||
currentID = key.currentID();
|
||||
|
||||
result = (CacheEntry)cache.get(currentID);
|
||||
currentDescriptor = key.currentDescriptor();
|
||||
if (debug) System.out.println(name + "[" + NDebug++ + "] looking for: " + currentDescriptor);
|
||||
result = (CacheEntry)cache.get(currentDescriptor);
|
||||
if (result != null) {
|
||||
if (debug) System.out.println(name + " found with descriptor: " + currentDescriptor);
|
||||
break outer;
|
||||
}
|
||||
|
||||
@ -300,11 +359,13 @@ public class ICUService extends ICUNotifier {
|
||||
// the cache if we eventually succeed.
|
||||
putInCache = true;
|
||||
|
||||
int n = 0;
|
||||
Iterator fi = factories.iterator();
|
||||
while (fi.hasNext()) {
|
||||
Object service = ((Factory)fi.next()).create(key);
|
||||
if (service != null) {
|
||||
result = new CacheEntry(currentID, service);
|
||||
result = new CacheEntry(currentDescriptor, service);
|
||||
if (debug) System.out.println(name + " factory cache with descriptor: " + currentDescriptor);
|
||||
break outer;
|
||||
}
|
||||
}
|
||||
@ -314,20 +375,23 @@ public class ICUService extends ICUNotifier {
|
||||
// don't want to keep querying on an id that's going to
|
||||
// fallback to the one that succeeded, we want to hit the
|
||||
// cache the first time next goaround.
|
||||
if (cacheIDList == null) {
|
||||
cacheIDList = new ArrayList(5);
|
||||
if (cacheDescriptorList == null) {
|
||||
cacheDescriptorList = new ArrayList(5);
|
||||
}
|
||||
cacheIDList.add(currentID);
|
||||
cacheDescriptorList.add(currentDescriptor);
|
||||
|
||||
} while (key.fallback());
|
||||
|
||||
if (result != null) {
|
||||
if (putInCache) {
|
||||
cache.put(result.actualID, result);
|
||||
if (cacheIDList != null) {
|
||||
Iterator iter = cacheIDList.iterator();
|
||||
cache.put(result.actualDescriptor, result);
|
||||
if (cacheDescriptorList != null) {
|
||||
Iterator iter = cacheDescriptorList.iterator();
|
||||
while (iter.hasNext()) {
|
||||
cache.put((String)iter.next(), result);
|
||||
String desc = (String)iter.next();
|
||||
if (debug) System.out.println(name + " adding descriptor: '" + desc + "' for actual: '" + result.actualDescriptor + "'");
|
||||
|
||||
cache.put(desc, result);
|
||||
}
|
||||
}
|
||||
// Atomic update. We held the read lock all this time
|
||||
@ -337,10 +401,12 @@ public class ICUService extends ICUNotifier {
|
||||
cacheref = cref;
|
||||
}
|
||||
|
||||
if (actualIDReturn != null) {
|
||||
actualIDReturn[0] = result.actualID;
|
||||
if (actualReturn != null) {
|
||||
actualReturn[0] = result.actualDescriptor;
|
||||
}
|
||||
|
||||
if (debug) System.out.println("found in service: " + name);
|
||||
|
||||
return result.service;
|
||||
}
|
||||
}
|
||||
@ -349,6 +415,8 @@ public class ICUService extends ICUNotifier {
|
||||
}
|
||||
}
|
||||
|
||||
if (debug) System.out.println("not found in service: " + name);
|
||||
|
||||
return null;
|
||||
}
|
||||
private SoftReference cacheref;
|
||||
@ -356,10 +424,10 @@ public class ICUService extends ICUNotifier {
|
||||
// Record the actual id for this service in the cache, so we can return it
|
||||
// even if we succeed later with a different id.
|
||||
private static final class CacheEntry {
|
||||
String actualID;
|
||||
Object service;
|
||||
CacheEntry(String actualID, Object service) {
|
||||
this.actualID = actualID;
|
||||
final String actualDescriptor;
|
||||
final Object service;
|
||||
CacheEntry(String actualDescriptor, Object service) {
|
||||
this.actualDescriptor = actualDescriptor;
|
||||
this.service = service;
|
||||
}
|
||||
}
|
||||
@ -391,9 +459,7 @@ public class ICUService extends ICUNotifier {
|
||||
// grab the factory list and update it ourselves
|
||||
try {
|
||||
factoryLock.acquireRead();
|
||||
|
||||
idcache = new TreeMap(String.CASE_INSENSITIVE_ORDER);
|
||||
|
||||
ListIterator lIter = factories.listIterator(factories.size());
|
||||
while (lIter.hasPrevious()) {
|
||||
Factory f = (Factory)lIter.previous();
|
||||
@ -490,8 +556,8 @@ public class ICUService extends ICUNotifier {
|
||||
// we define a class so we get atomic simultaneous access to both the
|
||||
// locale and corresponding map
|
||||
private static class LocaleRef {
|
||||
Locale locale;
|
||||
SoftReference ref;
|
||||
final Locale locale;
|
||||
final SoftReference ref;
|
||||
|
||||
LocaleRef(Map dnCache, Locale locale) {
|
||||
this.locale = locale;
|
||||
@ -690,5 +756,19 @@ public class ICUService extends ICUNotifier {
|
||||
}
|
||||
return "no stats";
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of this service. This will be the empty string if none was assigned.
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the result of super.toString, appending the name in curly braces.
|
||||
*/
|
||||
public String toString() {
|
||||
return super.toString() + "{" + name + "}";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,8 +5,8 @@
|
||||
*******************************************************************************
|
||||
*
|
||||
* $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/impl/LocaleUtility.java,v $
|
||||
* $Date: 2002/06/19 21:03:12 $
|
||||
* $Revision: 1.4 $
|
||||
* $Date: 2002/09/14 21:36:29 $
|
||||
* $Revision: 1.5 $
|
||||
* *****************************************************************************************
|
||||
*/
|
||||
|
||||
@ -97,27 +97,4 @@ public class LocaleUtility {
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
/*
|
||||
public static String getDisplayLanguage(String languageID, Locale l) {
|
||||
}
|
||||
|
||||
public static String getDisplayRegion(String regionID, Locale l) {
|
||||
}
|
||||
|
||||
public static String getDisplayVariant(String variantID, Locale l) {
|
||||
}
|
||||
|
||||
public static String getDisplayName(String localeName) {
|
||||
return getDisplayName(getLocaleFromString(localeName));
|
||||
}
|
||||
|
||||
public static String getDisplayName(Locale locale) {
|
||||
String lang = locale.getLanguage();
|
||||
String region = locale.getCountry();
|
||||
String var = locale.getVariant();
|
||||
|
||||
StringBuffer buf = new StringBuffer(lang);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
@ -5,15 +5,13 @@
|
||||
*******************************************************************************
|
||||
*
|
||||
* $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/text/NumberFormat.java,v $
|
||||
* $Date: 2002/03/20 05:11:15 $
|
||||
* $Revision: 1.13 $
|
||||
* $Date: 2002/09/14 21:36:28 $
|
||||
* $Revision: 1.14 $
|
||||
*
|
||||
*****************************************************************************************
|
||||
*/
|
||||
package com.ibm.icu.text;
|
||||
|
||||
import com.ibm.icu.impl.ICULocaleData;
|
||||
|
||||
import java.io.InvalidObjectException; //Bug 4185761 [Richard/GCL]
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
@ -23,9 +21,22 @@ import java.text.FieldPosition;
|
||||
import java.text.Format;
|
||||
import java.text.ParseException;
|
||||
import java.text.ParsePosition;
|
||||
import java.util.HashSet;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.Set;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* <code>NumberFormat</code> is the abstract base class for all number
|
||||
@ -151,13 +162,20 @@ import java.util.ResourceBundle;
|
||||
*
|
||||
* see DecimalFormat
|
||||
* see java.text.ChoiceFormat
|
||||
* @version $Revision: 1.13 $
|
||||
* @version $Revision: 1.14 $
|
||||
* @author Mark Davis
|
||||
* @author Helena Shih
|
||||
* @author Alan Liu
|
||||
*/
|
||||
public abstract class NumberFormat extends Format{
|
||||
|
||||
// Constants used by factory methods to specify a style of format.
|
||||
private static final int NUMBERSTYLE = 0;
|
||||
private static final int CURRENCYSTYLE = 1;
|
||||
private static final int PERCENTSTYLE = 2;
|
||||
private static final int SCIENTIFICSTYLE = 3;
|
||||
private static final int INTEGERSTYLE = 4;
|
||||
|
||||
/**
|
||||
* Field constant used to construct a FieldPosition object. Signifies that
|
||||
* the position of the integer part of a formatted number should be returned.
|
||||
@ -455,13 +473,168 @@ public abstract class NumberFormat extends Format{
|
||||
return getInstance(inLocale, SCIENTIFICSTYLE);
|
||||
}
|
||||
|
||||
// ===== Factory stuff =====
|
||||
|
||||
public static abstract class NumberFormatFactory {
|
||||
public static final int FORMAT_NUMBER = NUMBERSTYLE;
|
||||
public static final int FORMAT_CURRENCY = CURRENCYSTYLE;
|
||||
public static final int FORMAT_PERCENT = PERCENTSTYLE;
|
||||
public static final int FORMAT_SCIENTIFIC = SCIENTIFICSTYLE;
|
||||
public static final int FORMAT_INTEGER = INTEGERSTYLE;
|
||||
|
||||
/**
|
||||
* Return true if this factory will 'hide' other locales that
|
||||
* are more specific than the ones in this factory. E.g., if
|
||||
* this 'hides' 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();
|
||||
|
||||
/**
|
||||
* Return an array of the locales directly supported by this factory.
|
||||
*/
|
||||
public abstract Locale[] getSupportedLocales();
|
||||
|
||||
/**
|
||||
* Return a number format of the appropriate type. If the locale
|
||||
* is not supported, return null. All the defined types must be
|
||||
* supported.
|
||||
*/
|
||||
public abstract NumberFormat createFormat(Locale loc, int formatType);
|
||||
}
|
||||
|
||||
public static abstract class SimpleNumberFormatFactory extends NumberFormatFactory {
|
||||
final Locale locale;
|
||||
final boolean isGeneric;
|
||||
|
||||
public SimpleNumberFormatFactory(Locale locale, boolean isGeneric) {
|
||||
this.locale = locale;
|
||||
this.isGeneric = isGeneric;
|
||||
}
|
||||
|
||||
public final boolean hasGenericLocales() {
|
||||
return isGeneric;
|
||||
}
|
||||
|
||||
public final Locale[] getSupportedLocales() {
|
||||
return new Locale[] { locale };
|
||||
}
|
||||
}
|
||||
|
||||
private static final class NFFactory extends LocaleKeyFactory {
|
||||
private NumberFormatFactory delegate;
|
||||
|
||||
NFFactory(NumberFormatFactory delegate) {
|
||||
super(true, delegate.hasGenericLocales());
|
||||
|
||||
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 Set handleGetSupportedIDs() {
|
||||
Locale[] locales = delegate.getSupportedLocales();
|
||||
Set result = new HashSet();
|
||||
for (int i = 0; i < locales.length; ++i) {
|
||||
result.add(locales.toString());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the set of Locales for which NumberFormats are installed
|
||||
* @return available locales
|
||||
*/
|
||||
public static Locale[] getAvailableLocales() {
|
||||
return ICULocaleData.getAvailableLocales("NumberPatterns");
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a new NumberFormat for the provided locale of the defined
|
||||
* type. The returned object is a key that can be used to unregister this
|
||||
* NumberFormat object.
|
||||
*/
|
||||
public static Object register(NumberFormatFactory factory) {
|
||||
if (factory == null) {
|
||||
throw new IllegalArgumentException("factory must not be null");
|
||||
}
|
||||
return getService().registerFactory(new NFFactory(factory));
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister the currency associated with this key (obtained from
|
||||
* registerInstance).
|
||||
*/
|
||||
public static boolean unregister(Object registryKey) {
|
||||
return getService().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;
|
||||
}
|
||||
}
|
||||
|
||||
ICULocaleService newService = new ICULocaleService("NumberFormat");
|
||||
|
||||
newService.registerFactory(new RBNumberFormatFactory());
|
||||
|
||||
service = newService; // atomic
|
||||
}
|
||||
return service;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -624,11 +797,28 @@ public abstract class NumberFormat extends Format{
|
||||
|
||||
// =======================privates===============================
|
||||
|
||||
// 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);
|
||||
|
||||
//System.out.println("desired locale: " + desiredLocale + " service result:" + result);
|
||||
|
||||
//NumberFormat result2 = createInstance(desiredLocale, choice);
|
||||
//System.out.println("defaultResult: " + result2);
|
||||
|
||||
return (NumberFormat)result.clone();
|
||||
}
|
||||
|
||||
// [NEW]
|
||||
private static NumberFormat getInstance(Locale desiredLocale,
|
||||
private static NumberFormat createInstance(Locale desiredLocale,
|
||||
int choice) {
|
||||
DecimalFormat format = new DecimalFormat(getPattern(desiredLocale, choice),
|
||||
new DecimalFormatSymbols(desiredLocale));
|
||||
String pattern = getPattern(desiredLocale, choice);
|
||||
DecimalFormatSymbols symbols = new DecimalFormatSymbols(desiredLocale);
|
||||
DecimalFormat format = new DecimalFormat(pattern, symbols);
|
||||
// System.out.println("loc: " + desiredLocale + " choice: " + choice + " pat: " + pattern + " sym: " + symbols + " result: " + format);
|
||||
|
||||
/*Bug 4408066
|
||||
Add codes for the new method getIntegerInstance() [Richard/GCL]
|
||||
*/
|
||||
@ -763,15 +953,9 @@ public abstract class NumberFormat extends Format{
|
||||
*/
|
||||
private static final Hashtable cachedLocaleData = new Hashtable(3);
|
||||
|
||||
// Constants used by factory methods to specify a style of format.
|
||||
private static final int NUMBERSTYLE = 0;
|
||||
private static final int CURRENCYSTYLE = 1;
|
||||
private static final int PERCENTSTYLE = 2;
|
||||
private static final int SCIENTIFICSTYLE = 3;
|
||||
/*Bug 4408066
|
||||
Add Field for the new method getIntegerInstance() [Richard/GCL]
|
||||
*/
|
||||
private static final int INTEGERSTYLE = 4;
|
||||
|
||||
/**
|
||||
* True if the the grouping (i.e. thousands) separator is used when
|
||||
|
@ -5,8 +5,8 @@
|
||||
*******************************************************************************
|
||||
*
|
||||
* $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/util/Currency.java,v $
|
||||
* $Date: 2002/09/07 00:15:35 $
|
||||
* $Revision: 1.5 $
|
||||
* $Date: 2002/09/14 21:36:30 $
|
||||
* $Revision: 1.6 $
|
||||
*
|
||||
*******************************************************************************
|
||||
*/
|
||||
@ -56,11 +56,11 @@ public class Currency implements Serializable {
|
||||
|
||||
private static ICULocaleService getService() {
|
||||
if (service == null) {
|
||||
service = new ICULocaleService();
|
||||
service = new ICULocaleService("Currency");
|
||||
|
||||
class CurrencyFactory extends ICUResourceBundleFactory {
|
||||
CurrencyFactory() {
|
||||
super ("LocaleElements", "CurrencyElements", true);
|
||||
super("CurrencyElements", true);
|
||||
}
|
||||
|
||||
protected Object createFromBundle(ResourceBundle bundle, Key key) {
|
||||
|
Loading…
Reference in New Issue
Block a user