mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-08 15:05:53 +00:00
ICU-5402 Improve DateFormat performance
X-SVN-Rev: 20983
This commit is contained in:
parent
0baac6e262
commit
1eb0713f37
16 changed files with 1164 additions and 765 deletions
4
.gitattributes
vendored
4
.gitattributes
vendored
|
@ -136,8 +136,12 @@ icu4j/src/com/ibm/icu/dev/tool/docs/icu4j34.api.gz -text
|
|||
icu4j/src/com/ibm/icu/dev/tool/docs/icu4j341.api.gz -text
|
||||
icu4j/src/com/ibm/icu/dev/tool/docs/icu4j342.api.gz -text
|
||||
icu4j/src/com/ibm/icu/dev/tool/docs/icu4j343.api.gz -text
|
||||
icu4j/src/com/ibm/icu/impl/DateNumberFormat.java -text
|
||||
icu4j/src/com/ibm/icu/impl/ICUCache.java -text
|
||||
icu4j/src/com/ibm/icu/impl/SimpleCache.java -text
|
||||
icu4j/src/com/ibm/icu/impl/data/icudata.jar -text
|
||||
icu4j/src/com/ibm/icu/impl/data/th.brk -text
|
||||
icu4j/src/com/ibm/icu/util/CalendarServiceShim.java -text
|
||||
icu4j/src/com/ibm/icu/util/UResourceBundleIterator.java -text
|
||||
icu4j/src/com/ibm/richtext/textapps/resources/unicode.arabic.red -text
|
||||
icu4j/src/com/ibm/richtext/textapps/resources/unicode.hebrew.red -text
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//##header
|
||||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 1996-2006, International Business Machines Corporation and *
|
||||
* Copyright (C) 1996-2007, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*
|
||||
|
@ -10,9 +10,10 @@
|
|||
package com.ibm.icu.dev.test.serializable;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
|
||||
import com.ibm.icu.impl.DateNumberFormat;
|
||||
import com.ibm.icu.text.ChineseDateFormat;
|
||||
import com.ibm.icu.text.ChineseDateFormatSymbols;
|
||||
import com.ibm.icu.text.DateFormat;
|
||||
|
@ -1391,6 +1392,24 @@ public class FormatTests
|
|||
}
|
||||
//#endif
|
||||
|
||||
public static class DateNumberFormatHandler implements SerializableTest.Handler
|
||||
{
|
||||
public Object[] getTestObjects()
|
||||
{
|
||||
Locale locales[] = SerializableTest.getLocales();
|
||||
DateNumberFormat[] dnfmts = new DateNumberFormat[locales.length];
|
||||
for (int i = 0; i < locales.length; i++) {
|
||||
ULocale uloc = ULocale.forLocale(locales[i]);
|
||||
dnfmts[i] = new DateNumberFormat(uloc);
|
||||
}
|
||||
return dnfmts;
|
||||
}
|
||||
|
||||
public boolean hasSameBehavior(Object a, Object b) {
|
||||
return a.equals(b);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
// nothing needed...
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//##header
|
||||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 1996-2006, International Business Machines Corporation and *
|
||||
* Copyright (C) 1996-2007, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*
|
||||
|
@ -436,6 +436,7 @@ public class SerializableTest extends TestFmwk.TestGroup
|
|||
map.put("com.ibm.icu.text.SimpleDateFormat", new FormatTests.SimpleDateFormatHandler());
|
||||
map.put("com.ibm.icu.text.ChineseDateFormat", new FormatTests.ChineseDateFormatHandler());
|
||||
map.put("com.ibm.icu.text.ChineseDateFormatSymbols", new FormatTests.ChineseDateFormatSymbolsHandler());
|
||||
map.put("com.ibm.icu.impl.DateNumberFormat", new FormatTests.DateNumberFormatHandler());
|
||||
|
||||
map.put("com.ibm.icu.util.Calendar", new CalendarTests.CalendarHandler());
|
||||
map.put("com.ibm.icu.util.BuddhistCalendar", new CalendarTests.BuddhistCalendarHandler());
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//##header
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2006, International Business Machines Corporation and others.
|
||||
|
|
213
icu4j/src/com/ibm/icu/impl/DateNumberFormat.java
Normal file
213
icu4j/src/com/ibm/icu/impl/DateNumberFormat.java
Normal file
|
@ -0,0 +1,213 @@
|
|||
//##header
|
||||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2007, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*******************************************************************************
|
||||
*/
|
||||
package com.ibm.icu.impl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.math.BigInteger;
|
||||
import java.text.FieldPosition;
|
||||
import java.text.ParsePosition;
|
||||
|
||||
import com.ibm.icu.lang.UCharacter;
|
||||
import com.ibm.icu.math.BigDecimal;
|
||||
import com.ibm.icu.text.NumberFormat;
|
||||
import com.ibm.icu.util.ULocale;
|
||||
import com.ibm.icu.util.UResourceBundle;
|
||||
|
||||
/*
|
||||
* NumberFormat implementation dedicated/optimized for DateFormat,
|
||||
* used by SimpleDateFormat implementation.
|
||||
*/
|
||||
public final class DateNumberFormat extends NumberFormat {
|
||||
|
||||
private static final long serialVersionUID = -6315692826916346953L;
|
||||
|
||||
private char zeroDigit;
|
||||
private char minusSign;
|
||||
private boolean positiveOnly = false;
|
||||
|
||||
private transient char[] decimalBuf = new char[20]; // 20 digits is good enough to store Long.MAX_VALUE
|
||||
|
||||
private static SimpleCache CACHE = new SimpleCache();
|
||||
|
||||
private int maxIntDigits;
|
||||
private int minIntDigits;
|
||||
|
||||
public DateNumberFormat(ULocale loc) {
|
||||
initialize(loc);
|
||||
}
|
||||
|
||||
public DateNumberFormat(char zeroDigit, char minusSign) {
|
||||
this.zeroDigit = zeroDigit;
|
||||
this.minusSign = minusSign;
|
||||
}
|
||||
|
||||
private void initialize(ULocale loc) {
|
||||
char[] elems = (char[])CACHE.get(loc);
|
||||
if (elems == null) {
|
||||
// Missed cache
|
||||
ICUResourceBundle rb = (ICUResourceBundle)UResourceBundle.getBundleInstance(ICUResourceBundle.ICU_BASE_NAME, loc);
|
||||
String[] numberElements = rb.getStringArray("NumberElements");
|
||||
elems = new char[2];
|
||||
elems[0] = numberElements[4].charAt(0);
|
||||
elems[1] = numberElements[6].charAt(0);
|
||||
CACHE.put(loc, elems);
|
||||
}
|
||||
zeroDigit = elems[0];
|
||||
minusSign = elems[1];
|
||||
}
|
||||
|
||||
public void setMaximumIntegerDigits(int newValue) {
|
||||
maxIntDigits = newValue;
|
||||
}
|
||||
|
||||
public int getMaximumIntegerDigits() {
|
||||
return maxIntDigits;
|
||||
}
|
||||
|
||||
public void setMinimumIntegerDigits(int newValue) {
|
||||
minIntDigits = newValue;
|
||||
}
|
||||
|
||||
public int getMinimumIntegerDigits() {
|
||||
return minIntDigits;
|
||||
}
|
||||
|
||||
/* For supporting SimpleDateFormat.parseInt */
|
||||
public void setParsePositiveOnly(boolean isPositiveOnly) {
|
||||
positiveOnly = isPositiveOnly;
|
||||
}
|
||||
|
||||
public char getZeroDigit() {
|
||||
return zeroDigit;
|
||||
}
|
||||
|
||||
public StringBuffer format(double number, StringBuffer toAppendTo,
|
||||
FieldPosition pos) {
|
||||
throw new UnsupportedOperationException("StringBuffer format(double, StringBuffer, FieldPostion) is not implemented");
|
||||
}
|
||||
|
||||
public StringBuffer format(long numberL, StringBuffer toAppendTo,
|
||||
FieldPosition pos) {
|
||||
|
||||
if (numberL < 0) {
|
||||
// negative
|
||||
toAppendTo.append(minusSign);
|
||||
}
|
||||
|
||||
// Note: NumberFormat used by DateFormat only uses int numbers.
|
||||
// Remainder operation on 32bit platform using long is significantly slower
|
||||
// than int. So, this method casts long number into int.
|
||||
int number = (int)numberL;
|
||||
|
||||
int limit = decimalBuf.length < maxIntDigits ? decimalBuf.length : maxIntDigits;
|
||||
int index = limit - 1;
|
||||
while (true) {
|
||||
decimalBuf[index] = (char)((number % 10) + zeroDigit);
|
||||
number /= 10;
|
||||
if (index == 0 || number == 0) {
|
||||
break;
|
||||
}
|
||||
index--;
|
||||
}
|
||||
int padding = minIntDigits - (limit - index);
|
||||
for (; padding > 0; padding--) {
|
||||
decimalBuf[--index] = zeroDigit;
|
||||
}
|
||||
int length = limit - index;
|
||||
toAppendTo.append(decimalBuf, index, length);
|
||||
pos.setBeginIndex(0);
|
||||
if (pos.getField() == NumberFormat.INTEGER_FIELD) {
|
||||
pos.setEndIndex(length);
|
||||
} else {
|
||||
pos.setEndIndex(0);
|
||||
}
|
||||
return toAppendTo;
|
||||
}
|
||||
|
||||
public StringBuffer format(BigInteger number, StringBuffer toAppendTo,
|
||||
FieldPosition pos) {
|
||||
throw new UnsupportedOperationException("StringBuffer format(BigInteger, StringBuffer, FieldPostion) is not implemented");
|
||||
}
|
||||
|
||||
//#ifndef FOUNDATION
|
||||
public StringBuffer format(java.math.BigDecimal number, StringBuffer toAppendTo,
|
||||
FieldPosition pos) {
|
||||
throw new UnsupportedOperationException("StringBuffer format(BigDecimal, StringBuffer, FieldPostion) is not implemented");
|
||||
}
|
||||
//#endif
|
||||
|
||||
public StringBuffer format(BigDecimal number,
|
||||
StringBuffer toAppendTo, FieldPosition pos) {
|
||||
throw new UnsupportedOperationException("StringBuffer format(BigDecimal, StringBuffer, FieldPostion) is not implemented");
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: This method only parse integer numbers which can be represented by long
|
||||
*/
|
||||
public Number parse(String text, ParsePosition parsePosition) {
|
||||
long num = 0;
|
||||
boolean sawNumber = false;
|
||||
boolean negative = false;
|
||||
int base = parsePosition.getIndex();
|
||||
int offset = 0;
|
||||
for (; base + offset < text.length(); offset++) {
|
||||
char ch = text.charAt(base + offset);
|
||||
if (offset == 0 && ch == minusSign) {
|
||||
if (positiveOnly) {
|
||||
break;
|
||||
}
|
||||
negative = true;
|
||||
} else {
|
||||
int digit = ch - zeroDigit;
|
||||
if (digit < 0 || 9 < digit) {
|
||||
digit = UCharacter.digit(ch);
|
||||
}
|
||||
if (0 <= digit && digit <= 9) {
|
||||
sawNumber = true;
|
||||
num = num * 10 + digit;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Number result = null;
|
||||
if (sawNumber) {
|
||||
num = negative ? num * (-1) : num;
|
||||
result = new Long(num);
|
||||
parsePosition.setIndex(base + offset);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (!super.equals(obj)) {
|
||||
return false;
|
||||
}
|
||||
DateNumberFormat other = (DateNumberFormat)obj;
|
||||
if (this.maxIntDigits == other.maxIntDigits
|
||||
&& this.minIntDigits == other.minIntDigits
|
||||
&& this.zeroDigit == other.zeroDigit
|
||||
&& this.minusSign == other.minusSign
|
||||
&& this.positiveOnly == other.positiveOnly) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
|
||||
stream.defaultReadObject();
|
||||
// re-allocate the work buffer
|
||||
decimalBuf = new char[20];
|
||||
}
|
||||
}
|
||||
|
||||
//eof
|
8
icu4j/src/com/ibm/icu/impl/ICUCache.java
Normal file
8
icu4j/src/com/ibm/icu/impl/ICUCache.java
Normal file
|
@ -0,0 +1,8 @@
|
|||
package com.ibm.icu.impl;
|
||||
|
||||
public interface ICUCache {
|
||||
public static final Object NULL = new Object();
|
||||
public void clear();
|
||||
public void put(Object key, Object value);
|
||||
public Object get(Object key);
|
||||
}
|
|
@ -265,13 +265,16 @@ public class ICULocaleService extends ICUService {
|
|||
public String currentDescriptor() {
|
||||
String result = currentID();
|
||||
if (result != null) {
|
||||
result = "/" + result;
|
||||
if (varstart != -1) {
|
||||
result += primaryID.substring(varstart);
|
||||
}
|
||||
StringBuffer buf = new StringBuffer(result.length() + 32);
|
||||
if (kind != KIND_ANY) {
|
||||
result = prefix() + result;
|
||||
buf.append(prefix());
|
||||
}
|
||||
buf.append('/');
|
||||
buf.append(result);
|
||||
if (varstart != -1) {
|
||||
buf.append(primaryID.substring(varstart, primaryID.length()));
|
||||
}
|
||||
result = buf.toString();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
40
icu4j/src/com/ibm/icu/impl/SimpleCache.java
Normal file
40
icu4j/src/com/ibm/icu/impl/SimpleCache.java
Normal file
|
@ -0,0 +1,40 @@
|
|||
package com.ibm.icu.impl;
|
||||
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class SimpleCache implements ICUCache {
|
||||
|
||||
public Object get(Object key) {
|
||||
SoftReference ref = cacheRef;
|
||||
if (ref != null) {
|
||||
Map map = (Map)ref.get();
|
||||
if (map != null) {
|
||||
return map.get(key);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void put(Object key, Object value) {
|
||||
SoftReference ref = cacheRef;
|
||||
Map map = null;
|
||||
if (ref != null) {
|
||||
map = (Map)ref.get();
|
||||
}
|
||||
if (map == null) {
|
||||
map = Collections.synchronizedMap(new HashMap());
|
||||
ref = new SoftReference(map);
|
||||
cacheRef = ref;
|
||||
}
|
||||
map.put(key, value);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
cacheRef = null;
|
||||
}
|
||||
|
||||
private SoftReference cacheRef = null;
|
||||
}
|
|
@ -51,8 +51,7 @@ public class ChineseDateFormat extends SimpleDateFormat {
|
|||
* @stable ICU 2.0
|
||||
*/
|
||||
public ChineseDateFormat(String pattern, Locale locale) {
|
||||
// TODO: convert to use ULocale
|
||||
super(pattern, new ChineseDateFormatSymbols(locale), true);
|
||||
this(pattern, ULocale.forLocale(locale));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -63,9 +62,8 @@ public class ChineseDateFormat extends SimpleDateFormat {
|
|||
* @provisional This API might change or be removed in a future release.
|
||||
*/
|
||||
public ChineseDateFormat(String pattern, ULocale locale) {
|
||||
// TODO: convert CDFS to use ULocale
|
||||
//super(pattern, new ChineseDateFormatSymbols(locale.toLocale()), true);
|
||||
super(pattern, new ChineseDateFormatSymbols(locale), locale);
|
||||
super(pattern, new ChineseDateFormatSymbols(locale),
|
||||
new ChineseCalendar(TimeZone.getDefault(), locale), locale, true);
|
||||
}
|
||||
|
||||
// NOTE: This API still exists; we just inherit it from SimpleDateFormat
|
||||
|
|
|
@ -92,4 +92,11 @@ public class ChineseDateFormatSymbols extends DateFormatSymbols {
|
|||
super.initializeData(loc, calData);
|
||||
isLeapMonth = calData.getStringArray("isLeapMonth");
|
||||
}
|
||||
|
||||
void initializeData(DateFormatSymbols dfs) {
|
||||
super.initializeData(dfs);
|
||||
if (dfs instanceof ChineseDateFormatSymbols) {
|
||||
this.isLeapMonth = ((ChineseDateFormatSymbols)dfs).isLeapMonth;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,18 +7,6 @@
|
|||
|
||||
package com.ibm.icu.text;
|
||||
|
||||
import com.ibm.icu.impl.ICUResourceBundle;
|
||||
import com.ibm.icu.impl.CalendarData;
|
||||
import com.ibm.icu.impl.TextTrieMap;
|
||||
import com.ibm.icu.impl.Utility;
|
||||
import com.ibm.icu.util.Calendar;
|
||||
import com.ibm.icu.util.GregorianCalendar;
|
||||
import com.ibm.icu.util.TimeZone;
|
||||
import com.ibm.icu.util.UResourceBundle;
|
||||
import com.ibm.icu.impl.ZoneMeta;
|
||||
import com.ibm.icu.util.ULocale;
|
||||
import com.ibm.icu.impl.SoftCache;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
@ -27,6 +15,19 @@ import java.util.Locale;
|
|||
import java.util.MissingResourceException;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
import com.ibm.icu.impl.CalendarData;
|
||||
import com.ibm.icu.impl.ICUCache;
|
||||
import com.ibm.icu.impl.ICUResourceBundle;
|
||||
import com.ibm.icu.impl.SimpleCache;
|
||||
import com.ibm.icu.impl.TextTrieMap;
|
||||
import com.ibm.icu.impl.Utility;
|
||||
import com.ibm.icu.impl.ZoneMeta;
|
||||
import com.ibm.icu.util.Calendar;
|
||||
import com.ibm.icu.util.GregorianCalendar;
|
||||
import com.ibm.icu.util.TimeZone;
|
||||
import com.ibm.icu.util.ULocale;
|
||||
import com.ibm.icu.util.UResourceBundle;
|
||||
|
||||
/**
|
||||
* <code>DateFormatSymbols</code> is a public class for encapsulating
|
||||
* localizable date-time formatting data, such as the names of the
|
||||
|
@ -825,7 +826,6 @@ public class DateFormatSymbols implements Serializable, Cloneable {
|
|||
{
|
||||
try {
|
||||
DateFormatSymbols other = (DateFormatSymbols)super.clone();
|
||||
copyMembers(this, other);
|
||||
return other;
|
||||
} catch (CloneNotSupportedException e) {
|
||||
///CLOVER:OFF
|
||||
|
@ -896,6 +896,10 @@ public class DateFormatSymbols implements Serializable, Cloneable {
|
|||
* Useful constant for defining timezone offsets.
|
||||
*/
|
||||
static final int millisPerHour = 60*60*1000;
|
||||
|
||||
// DateFormatSymbols cache
|
||||
private static ICUCache DFSCACHE = new SimpleCache();
|
||||
|
||||
/**
|
||||
*
|
||||
* @param desiredLocale
|
||||
|
@ -904,10 +908,54 @@ public class DateFormatSymbols implements Serializable, Cloneable {
|
|||
*/
|
||||
protected void initializeData(ULocale desiredLocale, String type)
|
||||
{
|
||||
CalendarData calData = new CalendarData(desiredLocale, type);
|
||||
initializeData(desiredLocale, calData);
|
||||
String key = desiredLocale.toString() + "+" + type;
|
||||
DateFormatSymbols dfs = (DateFormatSymbols)DFSCACHE.get(key);
|
||||
if (dfs == null) {
|
||||
// Initialize data from scratch put a clone of this instance into the cache
|
||||
CalendarData calData = new CalendarData(desiredLocale, type);
|
||||
initializeData(desiredLocale, calData);
|
||||
dfs = (DateFormatSymbols)this.clone();
|
||||
DFSCACHE.put(key, dfs);
|
||||
} else {
|
||||
initializeData(dfs);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize format symbols using another instance.
|
||||
*
|
||||
* TODO Clean up initialization methods for subclasses
|
||||
*/
|
||||
void initializeData(DateFormatSymbols dfs) {
|
||||
this.eras = dfs.eras;
|
||||
this.eraNames = dfs.eraNames;
|
||||
this.narrowEras = dfs.narrowEras;
|
||||
this.months = dfs.months;
|
||||
this.shortMonths = dfs.shortMonths;
|
||||
this.narrowMonths = dfs.narrowMonths;
|
||||
this.standaloneMonths = dfs.standaloneMonths;
|
||||
this.standaloneShortMonths = dfs.standaloneShortMonths;
|
||||
this.standaloneNarrowMonths = dfs.standaloneNarrowMonths;
|
||||
this.weekdays = dfs.weekdays;
|
||||
this.shortWeekdays = dfs.shortWeekdays;
|
||||
this.narrowWeekdays = dfs.narrowWeekdays;
|
||||
this.standaloneWeekdays = dfs.standaloneWeekdays;
|
||||
this.standaloneShortWeekdays = dfs.standaloneShortWeekdays;
|
||||
this.standaloneNarrowWeekdays = dfs.standaloneNarrowWeekdays;
|
||||
this.ampms = dfs.ampms;
|
||||
this.shortQuarters = dfs.shortQuarters;
|
||||
this.quarters = dfs.quarters;
|
||||
this.standaloneShortQuarters = dfs.standaloneShortQuarters;
|
||||
this.standaloneQuarters = dfs.standaloneQuarters;
|
||||
|
||||
this.zoneStrings = dfs.zoneStrings; // always null at initialization time for now
|
||||
this.localPatternChars = dfs.localPatternChars;
|
||||
|
||||
this.actualLocale = dfs.actualLocale;
|
||||
this.validLocale = dfs.validLocale;
|
||||
this.requestedLocale = dfs.requestedLocale;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param desiredLocale
|
||||
|
@ -1242,7 +1290,7 @@ public class DateFormatSymbols implements Serializable, Cloneable {
|
|||
/**
|
||||
* A cache for ZoneItemInfo objects, shared by class instances.
|
||||
*/
|
||||
private static SoftCache zoneItemInfoCache = new SoftCache();
|
||||
private static ICUCache zoneItemInfoCache = new SimpleCache();
|
||||
|
||||
/**
|
||||
* A ZoneItemInfo instance which holds custom timezone strings
|
||||
|
@ -1520,36 +1568,6 @@ public class DateFormatSymbols implements Serializable, Cloneable {
|
|||
return aCopy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clones all the data members from the source DateFormatSymbols to
|
||||
* the target DateFormatSymbols. This is only for subclasses.
|
||||
* @param src the source DateFormatSymbols.
|
||||
* @param dst the target DateFormatSymbols.
|
||||
*/
|
||||
private final void copyMembers(DateFormatSymbols src, DateFormatSymbols dst)
|
||||
{
|
||||
dst.eras = duplicate(src.eras);
|
||||
dst.eraNames = duplicate(src.eraNames);
|
||||
dst.months = duplicate(src.months);
|
||||
dst.shortMonths = duplicate(src.shortMonths);
|
||||
dst.narrowMonths = duplicate(src.narrowMonths);
|
||||
dst.standaloneMonths = duplicate(src.standaloneMonths);
|
||||
dst.standaloneShortMonths = duplicate(src.standaloneShortMonths);
|
||||
dst.standaloneNarrowMonths = duplicate(src.standaloneNarrowMonths);
|
||||
dst.weekdays = duplicate(src.weekdays);
|
||||
dst.shortWeekdays = duplicate(src.shortWeekdays);
|
||||
dst.narrowWeekdays = duplicate(src.narrowWeekdays);
|
||||
dst.standaloneWeekdays = duplicate(src.standaloneWeekdays);
|
||||
dst.standaloneShortWeekdays = duplicate(src.standaloneShortWeekdays);
|
||||
dst.standaloneNarrowWeekdays = duplicate(src.standaloneNarrowWeekdays);
|
||||
dst.ampms = duplicate(src.ampms);
|
||||
if (src.zoneStrings != null) {
|
||||
dst.zoneStrings = duplicate(src.zoneStrings);
|
||||
}
|
||||
dst.requestedLocale = new ULocale(src.requestedLocale.toString());
|
||||
dst.localPatternChars = new String (src.localPatternChars);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares the equality of the two arrays of String.
|
||||
* @param current this String array.
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -5,38 +5,25 @@
|
|||
|
||||
package com.ibm.icu.util;
|
||||
|
||||
import com.ibm.icu.impl.ICULocaleService;
|
||||
import com.ibm.icu.impl.ICUResourceBundle;
|
||||
import com.ibm.icu.impl.ICUService.Factory;
|
||||
import com.ibm.icu.impl.CalendarData;
|
||||
import com.ibm.icu.text.DateFormat;
|
||||
import com.ibm.icu.text.DateFormatSymbols;
|
||||
import com.ibm.icu.text.SimpleDateFormat;
|
||||
import com.ibm.icu.util.TimeZone;
|
||||
import com.ibm.icu.util.BuddhistCalendar;
|
||||
import com.ibm.icu.util.ChineseCalendar;
|
||||
import com.ibm.icu.util.CopticCalendar;
|
||||
import com.ibm.icu.util.EthiopicCalendar;
|
||||
import com.ibm.icu.util.GregorianCalendar;
|
||||
import com.ibm.icu.util.HebrewCalendar;
|
||||
import com.ibm.icu.util.IslamicCalendar;
|
||||
import com.ibm.icu.util.JapaneseCalendar;
|
||||
|
||||
import java.io.IOException;
|
||||
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;
|
||||
|
||||
import com.ibm.icu.impl.CalendarData;
|
||||
import com.ibm.icu.impl.ICUCache;
|
||||
import com.ibm.icu.impl.ICUResourceBundle;
|
||||
import com.ibm.icu.impl.SimpleCache;
|
||||
import com.ibm.icu.text.DateFormat;
|
||||
import com.ibm.icu.text.DateFormatSymbols;
|
||||
import com.ibm.icu.text.MessageFormat;
|
||||
import com.ibm.icu.text.SimpleDateFormat;
|
||||
|
||||
/**
|
||||
* <code>Calendar</code> is an abstract base class for converting between
|
||||
* a <code>Date</code> object and a set of integer fields such as
|
||||
|
@ -1575,7 +1562,7 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable {
|
|||
*/
|
||||
public static synchronized Calendar getInstance()
|
||||
{
|
||||
return getInstance(TimeZone.getDefault(), ULocale.getDefault(), null);
|
||||
return getInstanceInternal(null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1586,7 +1573,7 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable {
|
|||
*/
|
||||
public static synchronized Calendar getInstance(TimeZone zone)
|
||||
{
|
||||
return getInstance(zone, ULocale.getDefault(), null);
|
||||
return getInstanceInternal(zone, null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1597,7 +1584,7 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable {
|
|||
*/
|
||||
public static synchronized Calendar getInstance(Locale aLocale)
|
||||
{
|
||||
return getInstance(TimeZone.getDefault(), ULocale.forLocale(aLocale), null);
|
||||
return getInstanceInternal(null, ULocale.forLocale(aLocale));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1609,7 +1596,7 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable {
|
|||
*/
|
||||
public static synchronized Calendar getInstance(ULocale locale)
|
||||
{
|
||||
return getInstance(TimeZone.getDefault(), locale, null);
|
||||
return getInstanceInternal(null, locale);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1621,7 +1608,7 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable {
|
|||
*/
|
||||
public static synchronized Calendar getInstance(TimeZone zone,
|
||||
Locale aLocale) {
|
||||
return getInstance(zone, ULocale.forLocale(aLocale), null);
|
||||
return getInstanceInternal(zone, ULocale.forLocale(aLocale));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1634,69 +1621,26 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable {
|
|||
*/
|
||||
public static synchronized Calendar getInstance(TimeZone zone,
|
||||
ULocale locale) {
|
||||
return getInstance(zone, locale, null);
|
||||
return getInstanceInternal(zone, locale);
|
||||
}
|
||||
|
||||
// ==== Factory Stuff ====
|
||||
///CLOVER:OFF
|
||||
/**
|
||||
* Return a calendar of for the TimeZone and locale. If factoryName 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 the locale.
|
||||
* @prototype
|
||||
*/
|
||||
/* public */ static synchronized Calendar getInstance(TimeZone zone,
|
||||
ULocale locale,
|
||||
String factoryName)
|
||||
{
|
||||
CalendarFactory factory = null;
|
||||
if (factoryName != null) {
|
||||
factory = (CalendarFactory)getFactoryMap().get(factoryName);
|
||||
/*
|
||||
* All getInstance implementations call this private method to create a new
|
||||
* Calendar instance.
|
||||
*/
|
||||
private static Calendar getInstanceInternal(TimeZone tz, ULocale locale) {
|
||||
if (locale == null) {
|
||||
locale = ULocale.getDefault();
|
||||
}
|
||||
|
||||
ULocale[] actualReturn = new ULocale[1];
|
||||
if (factory == null && service != null) {
|
||||
factory = (CalendarFactory)service.get(locale, actualReturn);
|
||||
}
|
||||
|
||||
if (factory == null) {
|
||||
int calType = getCalendarType(locale);
|
||||
switch (calType) {
|
||||
case BUDDHIST:
|
||||
return new BuddhistCalendar(zone, locale);
|
||||
case CHINESE:
|
||||
return new ChineseCalendar(zone, locale);
|
||||
case COPTIC:
|
||||
return new CopticCalendar(zone, locale);
|
||||
case ETHIOPIC:
|
||||
return new EthiopicCalendar(zone, locale);
|
||||
case GREGORIAN:
|
||||
return new GregorianCalendar(zone, locale);
|
||||
case HEBREW:
|
||||
return new HebrewCalendar(zone, locale);
|
||||
case ISLAMIC:
|
||||
case ISLAMIC_CIVIL: {
|
||||
IslamicCalendar result = new IslamicCalendar(zone, locale);
|
||||
result.setCivil(calType == ISLAMIC_CIVIL);
|
||||
return result;
|
||||
}
|
||||
case JAPANESE:
|
||||
return new JapaneseCalendar(zone, locale);
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
} else {
|
||||
Calendar result = factory.create(zone, locale);
|
||||
|
||||
// TODO: get the actual/valid locale properly
|
||||
ULocale uloc = actualReturn[0];
|
||||
result.setLocale(uloc, uloc);
|
||||
|
||||
return result;
|
||||
if (tz == null) {
|
||||
tz = TimeZone.getDefault();
|
||||
}
|
||||
Calendar cal = getShim().createInstance(locale);
|
||||
cal.setTimeZone(tz);
|
||||
cal.setTimeInMillis(System.currentTimeMillis());
|
||||
return cal;
|
||||
}
|
||||
|
||||
|
||||
private static final int BUDDHIST = 0;
|
||||
private static final int CHINESE = 1;
|
||||
private static final int COPTIC = 2;
|
||||
|
@ -1734,7 +1678,6 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable {
|
|||
return GREGORIAN;
|
||||
}
|
||||
|
||||
///CLOVER:ON
|
||||
/**
|
||||
* Gets the list of locales for which Calendars are installed.
|
||||
* @return the list of locales for which Calendars are installed.
|
||||
|
@ -1742,9 +1685,10 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable {
|
|||
*/
|
||||
public static Locale[] getAvailableLocales()
|
||||
{
|
||||
return service == null
|
||||
? ICUResourceBundle.getAvailableLocales(ICUResourceBundle.ICU_BASE_NAME)
|
||||
: service.getAvailableLocales();
|
||||
if (shim == null) {
|
||||
return ICUResourceBundle.getAvailableLocales(ICUResourceBundle.ICU_BASE_NAME);
|
||||
}
|
||||
return getShim().getAvailableLocales();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1755,75 +1699,103 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable {
|
|||
*/
|
||||
public static ULocale[] getAvailableULocales()
|
||||
{
|
||||
return service == null
|
||||
? ICUResourceBundle.getAvailableULocales(ICUResourceBundle.ICU_BASE_NAME)
|
||||
: service.getAvailableULocales();
|
||||
if (shim == null) {
|
||||
return ICUResourceBundle.getAvailableULocales(ICUResourceBundle.ICU_BASE_NAME);
|
||||
}
|
||||
return getShim().getAvailableULocales();
|
||||
}
|
||||
|
||||
// ==== Factory Stuff ====
|
||||
/**
|
||||
* A CalendarFactory is used to register new calendar implementation.
|
||||
* The factory should be able to create a calendar instance for the
|
||||
* specified locale.
|
||||
*
|
||||
* @prototype
|
||||
*/
|
||||
/* public */ static abstract class CalendarFactory {
|
||||
public boolean visible() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public abstract Set getSupportedLocaleNames();
|
||||
|
||||
public Calendar createCalendar(ULocale loc) {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected CalendarFactory() {
|
||||
}
|
||||
}
|
||||
|
||||
// shim so we can build without service code
|
||||
static abstract class CalendarShim {
|
||||
abstract Locale[] getAvailableLocales();
|
||||
abstract ULocale[] getAvailableULocales();
|
||||
abstract Object registerFactory(CalendarFactory factory);
|
||||
abstract boolean unregister(Object k);
|
||||
abstract Calendar createInstance(ULocale l);
|
||||
}
|
||||
|
||||
private static CalendarShim shim;
|
||||
private static CalendarShim getShim() {
|
||||
if (shim == null) {
|
||||
try {
|
||||
Class cls = Class.forName("com.ibm.icu.util.CalendarServiceShim");
|
||||
shim = (CalendarShim)cls.newInstance();
|
||||
}
|
||||
catch (MissingResourceException e) {
|
||||
throw e;
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException(e.getMessage());
|
||||
}
|
||||
}
|
||||
return shim;
|
||||
}
|
||||
|
||||
static Calendar createInstance(ULocale locale) {
|
||||
int calType = getCalendarType(locale);
|
||||
TimeZone zone = TimeZone.getDefault();
|
||||
|
||||
switch (calType) {
|
||||
case BUDDHIST:
|
||||
return new BuddhistCalendar(zone, locale);
|
||||
case CHINESE:
|
||||
return new ChineseCalendar(zone, locale);
|
||||
case COPTIC:
|
||||
return new CopticCalendar(zone, locale);
|
||||
case ETHIOPIC:
|
||||
return new EthiopicCalendar(zone, locale);
|
||||
case GREGORIAN:
|
||||
return new GregorianCalendar(zone, locale);
|
||||
case HEBREW:
|
||||
return new HebrewCalendar(zone, locale);
|
||||
case ISLAMIC:
|
||||
case ISLAMIC_CIVIL: {
|
||||
IslamicCalendar result = new IslamicCalendar(zone, locale);
|
||||
result.setCivil(calType == ISLAMIC_CIVIL);
|
||||
return result;
|
||||
}
|
||||
case JAPANESE:
|
||||
return new JapaneseCalendar(zone, locale);
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
///CLOVER:OFF
|
||||
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;
|
||||
}
|
||||
|
||||
// Never used -- why is this here? Alan 2003-05
|
||||
// private static void addFactory(Map m, CalendarFactory f) {
|
||||
// m.put(f.factoryName(), f);
|
||||
// }
|
||||
|
||||
/**
|
||||
* Return a set of all the registered calendar factory names.
|
||||
* @prototype
|
||||
*/
|
||||
/* public */ static Set getCalendarFactoryNames() {
|
||||
return Collections.unmodifiableSet(getFactoryMap().keySet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a new CalendarFactory. getInstance(TimeZone, ULocale, String) will
|
||||
* try to locate a registered factories matching the factoryName. Only registered
|
||||
* factories will be found.
|
||||
* @prototype
|
||||
*/
|
||||
private static void registerFactory(CalendarFactory factory) {
|
||||
/* public */ static Object registerFactory(CalendarFactory factory) {
|
||||
if (factory == null) {
|
||||
throw new IllegalArgumentException("Factory must not be null");
|
||||
throw new IllegalArgumentException("factory must not be null");
|
||||
}
|
||||
getFactoryMap().put(factory.factoryName(), factory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience override of register(CalendarFactory, ULocale, boolean);
|
||||
* @prototype
|
||||
*/
|
||||
/* public */ static Object register(CalendarFactory factory, ULocale locale) {
|
||||
return register(factory, locale, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a default CalendarFactory for the provided locale.
|
||||
* If the factory has not already been registered with
|
||||
* registerFactory, it will be.
|
||||
* @prototype
|
||||
*/
|
||||
/* public */ static Object register(CalendarFactory factory, ULocale locale, boolean visible) {
|
||||
if (factory == null) {
|
||||
throw new IllegalArgumentException("calendar must not be null");
|
||||
}
|
||||
registerFactory(factory);
|
||||
return getService().registerObject(factory, locale, visible);
|
||||
return getShim().registerFactory(factory);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1832,20 +1804,17 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable {
|
|||
* @prototype
|
||||
*/
|
||||
/* public */ static boolean unregister(Object registryKey) {
|
||||
return service == null
|
||||
? false
|
||||
: service.unregisterFactory((Factory)registryKey);
|
||||
if (registryKey == null) {
|
||||
throw new IllegalArgumentException("registryKey must not be null");
|
||||
}
|
||||
|
||||
if (shim == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return shim.unregister(registryKey);
|
||||
}
|
||||
|
||||
private static ICULocaleService service = null;
|
||||
private static ICULocaleService getService() {
|
||||
synchronized (Calendar.class) {
|
||||
if (service == null) {
|
||||
service = new ICULocaleService("Calendar");
|
||||
}
|
||||
}
|
||||
return service;
|
||||
}
|
||||
///CLOVER:ON
|
||||
// ==== End of factory Stuff ====
|
||||
|
||||
|
@ -3047,51 +3016,96 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable {
|
|||
* @provisional This API might change or be removed in a future release.
|
||||
*/
|
||||
protected DateFormat handleGetDateFormat(String pattern, ULocale locale) {
|
||||
DateFormatSymbols symbols = new DateFormatSymbols(this, locale);
|
||||
return new SimpleDateFormat(pattern, symbols, locale);
|
||||
FormatConfiguration fmtConfig = new FormatConfiguration();
|
||||
fmtConfig.pattern = pattern;
|
||||
fmtConfig.formatData = new DateFormatSymbols(this, locale);
|
||||
fmtConfig.loc = locale;
|
||||
fmtConfig.cal = this;
|
||||
|
||||
return SimpleDateFormat.getInstance(fmtConfig);
|
||||
}
|
||||
|
||||
static private DateFormat formatHelper(Calendar cal, ULocale loc,
|
||||
int dateStyle, int timeStyle)
|
||||
{
|
||||
// See if there are any custom resources for this calendar
|
||||
// If not, just use the default DateFormat
|
||||
DateFormat result = null;
|
||||
|
||||
// date format pattern cache
|
||||
private static final ICUCache PATTERN_CACHE = new SimpleCache();
|
||||
// final fallback patterns
|
||||
private static final String[] DEFAULT_PATTERNS = {
|
||||
"HH:mm:ss z",
|
||||
"HH:mm:ss z",
|
||||
"HH:mm:ss",
|
||||
"HH:mm",
|
||||
"EEEE, yyyy MMMM dd",
|
||||
"yyyy MMMM d",
|
||||
"yyyy MMM d",
|
||||
"yy/MM/dd",
|
||||
"{1} {0}"
|
||||
};
|
||||
|
||||
static private DateFormat formatHelper(Calendar cal, ULocale loc, int dateStyle, int timeStyle) {
|
||||
// First, try to get a pattern from PATTERN_CACHE
|
||||
String key = loc.toString() + cal.getType();
|
||||
String[] patterns = (String[])PATTERN_CACHE.get(key);
|
||||
if (patterns == null) {
|
||||
// Cache missed. Get one from bundle
|
||||
try {
|
||||
CalendarData calData = new CalendarData(loc, cal.getType());
|
||||
String[] patterns = calData.get("DateTimePatterns").getStringArray();
|
||||
|
||||
String pattern = null;
|
||||
if ((timeStyle >= 0) && (dateStyle >= 0)) {
|
||||
Object[] dateTimeArgs = { patterns[timeStyle],
|
||||
patterns[dateStyle + 4] };
|
||||
pattern = MessageFormat.format(patterns[8], dateTimeArgs);
|
||||
}
|
||||
else if (timeStyle >= 0) {
|
||||
pattern = patterns[timeStyle];
|
||||
}
|
||||
else if (dateStyle >= 0) {
|
||||
pattern = patterns[dateStyle + 4];
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("No date or time style specified");
|
||||
}
|
||||
result = cal.handleGetDateFormat(pattern, loc);
|
||||
patterns = calData.get("DateTimePatterns").getStringArray();
|
||||
} catch (MissingResourceException e) {
|
||||
// !!! need dateformat subclass appropriate to calendar type here!
|
||||
// No custom patterns
|
||||
// !!! note: possible circularity here, if getDateTimeInstance calls us because of
|
||||
// loc specifying a calendar.
|
||||
result = DateFormat.getDateTimeInstance(dateStyle, timeStyle, loc);
|
||||
|
||||
DateFormatSymbols symbols = new DateFormatSymbols(cal, loc);
|
||||
((SimpleDateFormat) result).setDateFormatSymbols(symbols); // aliu
|
||||
patterns = DEFAULT_PATTERNS;
|
||||
}
|
||||
PATTERN_CACHE.put(key, patterns);
|
||||
}
|
||||
// Resolve a pattern for the date/time style
|
||||
String pattern = null;
|
||||
if ((timeStyle >= 0) && (dateStyle >= 0)) {
|
||||
pattern = MessageFormat.format(patterns[8],
|
||||
new Object[] {patterns[timeStyle], patterns[dateStyle + 4]});
|
||||
} else if (timeStyle >= 0) {
|
||||
pattern = patterns[timeStyle];
|
||||
} else if (dateStyle >= 0) {
|
||||
pattern = patterns[dateStyle + 4];
|
||||
} else {
|
||||
throw new IllegalArgumentException("No date or time style specified");
|
||||
}
|
||||
DateFormat result = cal.handleGetDateFormat(pattern, loc);
|
||||
result.setCalendar(cal);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* An instance of FormatConfiguration represents calendar specific
|
||||
* date format configuration and used for calling the ICU private
|
||||
* SimpleDateFormat factory method.
|
||||
*
|
||||
* @internal
|
||||
* @deprecated This API is ICU internal only.
|
||||
*/
|
||||
public static class FormatConfiguration {
|
||||
private String pattern;
|
||||
private DateFormatSymbols formatData;
|
||||
private Calendar cal;
|
||||
private ULocale loc;
|
||||
|
||||
// Only Calendar can instantiate
|
||||
private FormatConfiguration() {
|
||||
}
|
||||
|
||||
public String getPatternString() {
|
||||
return pattern;
|
||||
}
|
||||
|
||||
public Calendar getCalendar() {
|
||||
return cal;
|
||||
}
|
||||
|
||||
public ULocale getLocale() {
|
||||
return loc;
|
||||
}
|
||||
|
||||
public DateFormatSymbols getDateFormatSymbols() {
|
||||
return formatData;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Protected utility methods for use by subclasses. These are very handy
|
||||
// for implementing add, roll, and computeFields.
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
/**
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2002-2004, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
package com.ibm.icu.util;
|
||||
|
||||
import com.ibm.icu.util.TimeZone;
|
||||
import java.util.Locale;
|
||||
/**
|
||||
* @prototype
|
||||
*/
|
||||
interface CalendarFactory {
|
||||
public Calendar create(TimeZone tz, ULocale loc);
|
||||
public String factoryName();
|
||||
}
|
||||
|
107
icu4j/src/com/ibm/icu/util/CalendarServiceShim.java
Normal file
107
icu4j/src/com/ibm/icu/util/CalendarServiceShim.java
Normal file
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* Copyright (C) 2007, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package com.ibm.icu.util;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.Set;
|
||||
|
||||
import com.ibm.icu.impl.ICULocaleService;
|
||||
import com.ibm.icu.impl.ICUResourceBundle;
|
||||
import com.ibm.icu.impl.ICUService;
|
||||
import com.ibm.icu.impl.ICULocaleService.LocaleKey;
|
||||
import com.ibm.icu.impl.ICULocaleService.LocaleKeyFactory;
|
||||
import com.ibm.icu.impl.ICUService.Factory;
|
||||
import com.ibm.icu.impl.ICUService.Key;
|
||||
import com.ibm.icu.util.Calendar.CalendarFactory;
|
||||
|
||||
class CalendarServiceShim extends Calendar.CalendarShim {
|
||||
|
||||
Locale[] getAvailableLocales() {
|
||||
if (service.isDefault()) {
|
||||
return ICUResourceBundle.getAvailableLocales(ICUResourceBundle.ICU_BASE_NAME);
|
||||
}
|
||||
return service.getAvailableLocales();
|
||||
}
|
||||
|
||||
ULocale[] getAvailableULocales() {
|
||||
if (service.isDefault()) {
|
||||
return ICUResourceBundle.getAvailableULocales(ICUResourceBundle.ICU_BASE_NAME);
|
||||
}
|
||||
return service.getAvailableULocales();
|
||||
}
|
||||
|
||||
private static final class CalFactory extends LocaleKeyFactory {
|
||||
private CalendarFactory delegate;
|
||||
CalFactory(CalendarFactory delegate) {
|
||||
super(delegate.visible() ? VISIBLE : INVISIBLE);
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
public Object create(Key key, ICUService service) {
|
||||
if (handlesKey(key)) {
|
||||
LocaleKey lkey = (LocaleKey)key;
|
||||
ULocale loc = lkey.canonicalLocale();
|
||||
Object result = delegate.createCalendar(loc);
|
||||
if (result == null) {
|
||||
result = service.getKey(key, null, this);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected Set getSupportedIDs() {
|
||||
return delegate.getSupportedLocaleNames();
|
||||
}
|
||||
}
|
||||
|
||||
Calendar createInstance(ULocale desiredLocale) {
|
||||
ULocale[] actualLoc = new ULocale[1];
|
||||
if (desiredLocale.equals(ULocale.ROOT)) {
|
||||
desiredLocale = ULocale.ROOT;
|
||||
}
|
||||
Calendar cal = (Calendar)service.get(desiredLocale, actualLoc);
|
||||
if (cal == null) {
|
||||
throw new MissingResourceException("Unable to construct Calendar", "", "");
|
||||
}
|
||||
cal = (Calendar)cal.clone();
|
||||
|
||||
/* !!! TODO !!! actualLoc returned by service is not properly set.
|
||||
* When this Calendar object is being created, cal.setLocale is called
|
||||
* and proper actual locale is set at that time. Revisit this later.
|
||||
* -yoshito
|
||||
*/
|
||||
/*
|
||||
ULocale uloc = actualLoc[0];
|
||||
cal.setLocale(uloc, uloc); // service make no distinction between actual and valid
|
||||
*/
|
||||
return cal;
|
||||
}
|
||||
|
||||
Object registerFactory(CalendarFactory factory) {
|
||||
return service.registerFactory(new CalFactory(factory));
|
||||
}
|
||||
|
||||
boolean unregister(Object k) {
|
||||
return service.unregisterFactory((Factory)k);
|
||||
}
|
||||
|
||||
private static class CalService extends ICULocaleService {
|
||||
CalService() {
|
||||
super("Calendar");
|
||||
class RBCalendarFactory extends ICUResourceBundleFactory {
|
||||
protected Object handleCreate(ULocale loc, int kind, ICUService sercice) {
|
||||
return Calendar.createInstance(loc);
|
||||
}
|
||||
}
|
||||
this.registerFactory(new RBCalendarFactory());
|
||||
markDefault();
|
||||
}
|
||||
}
|
||||
|
||||
private static ICULocaleService service = new CalService();
|
||||
}
|
|
@ -8,6 +8,7 @@
|
|||
package com.ibm.icu.util;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
|
@ -16,12 +17,11 @@ import java.util.Locale;
|
|||
import java.util.Map;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.TreeMap;
|
||||
import java.lang.ref.SoftReference;
|
||||
|
||||
import com.ibm.icu.impl.LocaleUtility;
|
||||
import com.ibm.icu.impl.SimpleCache;
|
||||
import com.ibm.icu.impl.ICUResourceBundle;
|
||||
import com.ibm.icu.impl.LocaleUtility;
|
||||
import com.ibm.icu.lang.UCharacter;
|
||||
|
||||
/**
|
||||
* A class analogous to {@link java.util.Locale} that provides additional
|
||||
* support for ICU protocol. In ICU 3.0 this class is enhanced to support
|
||||
|
@ -232,30 +232,7 @@ public final class ULocale implements Serializable {
|
|||
*/
|
||||
public static final ULocale ROOT = new ULocale("root", EMPTY_LOCALE);
|
||||
|
||||
private static final HashMap CACHE = new HashMap(20);
|
||||
static {
|
||||
CACHE.put(EMPTY_LOCALE, ROOT);
|
||||
CACHE.put(Locale.ENGLISH, ENGLISH);
|
||||
CACHE.put(Locale.FRENCH, FRENCH);
|
||||
CACHE.put(Locale.GERMAN, GERMAN);
|
||||
CACHE.put(Locale.ITALIAN, ITALIAN);
|
||||
CACHE.put(Locale.JAPANESE, JAPANESE);
|
||||
CACHE.put(Locale.KOREAN, KOREAN);
|
||||
CACHE.put(Locale.CHINESE, CHINESE);
|
||||
CACHE.put(Locale.SIMPLIFIED_CHINESE, SIMPLIFIED_CHINESE);
|
||||
CACHE.put(Locale.TRADITIONAL_CHINESE, TRADITIONAL_CHINESE);
|
||||
CACHE.put(Locale.FRANCE, FRANCE);
|
||||
CACHE.put(Locale.GERMANY, GERMANY);
|
||||
CACHE.put(Locale.ITALY, ITALY);
|
||||
CACHE.put(Locale.JAPAN, JAPAN);
|
||||
CACHE.put(Locale.KOREA, KOREA);
|
||||
CACHE.put(Locale.CHINA, CHINA);
|
||||
CACHE.put(Locale.TAIWAN, TAIWAN);
|
||||
CACHE.put(Locale.UK, UK);
|
||||
CACHE.put(Locale.US, US);
|
||||
CACHE.put(Locale.CANADA, CANADA);
|
||||
CACHE.put(Locale.CANADA_FRENCH, CANADA_FRENCH);
|
||||
}
|
||||
private static final SimpleCache CACHE = new SimpleCache();
|
||||
|
||||
/**
|
||||
* Cache the locale.
|
||||
|
@ -749,14 +726,19 @@ public final class ULocale implements Serializable {
|
|||
if (loc == null) {
|
||||
return null;
|
||||
}
|
||||
if (loc.toString().length() == 0) {
|
||||
return ROOT;
|
||||
}
|
||||
ULocale result = (ULocale)CACHE.get(loc);
|
||||
if (result == null && defaultULocale != null && loc == defaultULocale.locale) {
|
||||
if (result == null) {
|
||||
if (defaultULocale != null && loc == defaultULocale.locale) {
|
||||
result = defaultULocale;
|
||||
} else {
|
||||
result = new ULocale(loc.toString(), loc);
|
||||
String locStr = loc.toString();
|
||||
if (locStr.length() == 0) {
|
||||
result = ROOT;
|
||||
} else {
|
||||
result = new ULocale(locStr, loc);
|
||||
}
|
||||
}
|
||||
CACHE.put(loc, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -863,10 +845,12 @@ public final class ULocale implements Serializable {
|
|||
return locale;
|
||||
}
|
||||
|
||||
private static SoftReference nameCacheRef = new SoftReference(Collections.synchronizedMap(new HashMap()));
|
||||
/**
|
||||
* Keep our own default ULocale.
|
||||
*/
|
||||
private static ULocale defaultULocale;
|
||||
private static Locale defaultLocale = Locale.getDefault();
|
||||
private static ULocale defaultULocale = new ULocale(defaultLocale);
|
||||
|
||||
/**
|
||||
* Returns the current default ULocale.
|
||||
|
@ -874,8 +858,9 @@ public final class ULocale implements Serializable {
|
|||
*/
|
||||
public static ULocale getDefault() {
|
||||
synchronized (ULocale.class) {
|
||||
Locale defaultLocale = Locale.getDefault();
|
||||
if (defaultULocale == null || defaultULocale.toLocale() != defaultLocale) {
|
||||
Locale currentDefault = Locale.getDefault();
|
||||
if (defaultLocale != currentDefault) {
|
||||
defaultLocale = currentDefault;
|
||||
defaultULocale = new ULocale(defaultLocale);
|
||||
}
|
||||
return defaultULocale;
|
||||
|
@ -1143,7 +1128,6 @@ public final class ULocale implements Serializable {
|
|||
}
|
||||
return name;
|
||||
}
|
||||
private static SoftReference nameCacheRef = new SoftReference(Collections.synchronizedMap(new HashMap()));
|
||||
|
||||
/**
|
||||
* Returns a string representation of this object.
|
||||
|
|
Loading…
Add table
Reference in a new issue