mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-08 06:53:45 +00:00
ICU-12605 convert data enumeration to resource sink for TimeUnitFormat, Java
X-SVN-Rev: 38879
This commit is contained in:
parent
b9250c1a6e
commit
e489a8b318
1 changed files with 80 additions and 43 deletions
|
@ -22,6 +22,7 @@ import java.util.TreeMap;
|
|||
|
||||
import com.ibm.icu.impl.ICUData;
|
||||
import com.ibm.icu.impl.ICUResourceBundle;
|
||||
import com.ibm.icu.impl.UResource;
|
||||
import com.ibm.icu.util.Measure;
|
||||
import com.ibm.icu.util.TimeUnit;
|
||||
import com.ibm.icu.util.TimeUnitAmount;
|
||||
|
@ -34,7 +35,7 @@ import com.ibm.icu.util.UResourceBundle;
|
|||
* Format or parse a TimeUnitAmount, using plural rules for the units where available.
|
||||
*
|
||||
* <P>
|
||||
* Code Sample:
|
||||
* Code Sample:
|
||||
* <pre>
|
||||
* // create a time unit instance.
|
||||
* // only SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, and YEAR are supported
|
||||
|
@ -51,7 +52,7 @@ import com.ibm.icu.util.UResourceBundle;
|
|||
* try {
|
||||
* // parse a string into time unit amount
|
||||
* TimeUnitAmount result = (TimeUnitAmount) format.parseObject(formatted);
|
||||
* // result should equal to source
|
||||
* // result should equal to source
|
||||
* } catch (ParseException e) {
|
||||
* }
|
||||
* </pre>
|
||||
|
@ -66,41 +67,41 @@ import com.ibm.icu.util.UResourceBundle;
|
|||
public class TimeUnitFormat extends MeasureFormat {
|
||||
|
||||
/**
|
||||
* Constant for full name style format.
|
||||
* Constant for full name style format.
|
||||
* For example, the full name for "hour" in English is "hour" or "hours".
|
||||
* @deprecated ICU 53 see {@link MeasureFormat.FormatWidth}
|
||||
*/
|
||||
@Deprecated
|
||||
public static final int FULL_NAME = 0;
|
||||
/**
|
||||
* Constant for abbreviated name style format.
|
||||
* Constant for abbreviated name style format.
|
||||
* For example, the abbreviated name for "hour" in English is "hr" or "hrs".
|
||||
* @deprecated ICU 53 see {@link MeasureFormat.FormatWidth}
|
||||
*/
|
||||
@Deprecated
|
||||
public static final int ABBREVIATED_NAME = 1;
|
||||
|
||||
|
||||
private static final int TOTAL_STYLES = 2;
|
||||
|
||||
private static final long serialVersionUID = -3707773153184971529L;
|
||||
|
||||
|
||||
// These fields are supposed to be the same as the fields in mf. They
|
||||
// are here for serialization backward compatibility and to support parsing.
|
||||
private NumberFormat format;
|
||||
private ULocale locale;
|
||||
private int style;
|
||||
|
||||
|
||||
// We use this field in lieu of the super class because the super class
|
||||
// is immutable while this class is mutable. The contents of the super class
|
||||
// is an empty shell. Every public method of the super class is overridden to
|
||||
// delegate to this field. Each time this object mutates, it replaces this field with
|
||||
// a new immutable instance.
|
||||
private transient MeasureFormat mf;
|
||||
|
||||
|
||||
private transient Map<TimeUnit, Map<String, Object[]>> timeUnitToCountToPatterns;
|
||||
private transient PluralRules pluralRules;
|
||||
private transient boolean isReady;
|
||||
|
||||
|
||||
private static final String DEFAULT_PATTERN_FOR_SECOND = "{0} s";
|
||||
private static final String DEFAULT_PATTERN_FOR_MINUTE = "{0} min";
|
||||
private static final String DEFAULT_PATTERN_FOR_HOUR = "{0} h";
|
||||
|
@ -110,7 +111,7 @@ public class TimeUnitFormat extends MeasureFormat {
|
|||
private static final String DEFAULT_PATTERN_FOR_YEAR = "{0} y";
|
||||
|
||||
/**
|
||||
* Create empty format using full name style, for example, "hours".
|
||||
* Create empty format using full name style, for example, "hours".
|
||||
* Use setLocale and/or setFormat to modify.
|
||||
* @deprecated ICU 53 use {@link MeasureFormat} instead.
|
||||
*/
|
||||
|
@ -157,13 +158,13 @@ public class TimeUnitFormat extends MeasureFormat {
|
|||
mf = MeasureFormat.getInstance(
|
||||
locale, style == FULL_NAME ? FormatWidth.WIDE : FormatWidth.SHORT);
|
||||
this.style = style;
|
||||
|
||||
|
||||
// Needed for getLocale(ULocale.VALID_LOCALE)
|
||||
setLocale(locale, locale);
|
||||
this.locale = locale;
|
||||
isReady = false;
|
||||
}
|
||||
|
||||
|
||||
private TimeUnitFormat(ULocale locale, int style, NumberFormat numberFormat) {
|
||||
this(locale, style);
|
||||
if (numberFormat != null) {
|
||||
|
@ -190,7 +191,7 @@ public class TimeUnitFormat extends MeasureFormat {
|
|||
public TimeUnitFormat setLocale(ULocale locale) {
|
||||
if (locale != this.locale){
|
||||
mf = mf.withLocale(locale);
|
||||
|
||||
|
||||
// Needed for getLocale(ULocale.VALID_LOCALE)
|
||||
setLocale(locale, locale);
|
||||
this.locale = locale;
|
||||
|
@ -198,7 +199,7 @@ public class TimeUnitFormat extends MeasureFormat {
|
|||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the locale used for formatting or parsing.
|
||||
* @param locale locale of this time unit formatter.
|
||||
|
@ -209,7 +210,7 @@ public class TimeUnitFormat extends MeasureFormat {
|
|||
public TimeUnitFormat setLocale(Locale locale) {
|
||||
return setLocale(ULocale.forLocale(locale));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the format used for formatting or parsing. Passing null is equivalent to passing
|
||||
* {@link NumberFormat#getNumberInstance(ULocale)}.
|
||||
|
@ -248,7 +249,7 @@ public class TimeUnitFormat extends MeasureFormat {
|
|||
FieldPosition pos) {
|
||||
return mf.format(obj, toAppendTo, pos);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parse a TimeUnitAmount.
|
||||
* @see java.text.Format#parseObject(java.lang.String, java.text.ParsePosition)
|
||||
|
@ -341,7 +342,7 @@ public class TimeUnitFormat extends MeasureFormat {
|
|||
return new TimeUnitAmount(resultNumber, resultTimeUnit);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void setup() {
|
||||
if (locale == null) {
|
||||
if (format != null) {
|
||||
|
@ -362,18 +363,37 @@ public class TimeUnitFormat extends MeasureFormat {
|
|||
setup("unitsShort/duration", timeUnitToCountToPatterns, ABBREVIATED_NAME, pluralKeywords);
|
||||
isReady = true;
|
||||
}
|
||||
|
||||
private void setup(String resourceKey, Map<TimeUnit, Map<String, Object[]>> timeUnitToCountToPatterns, int style,
|
||||
Set<String> pluralKeywords) {
|
||||
// fill timeUnitToCountToPatterns from resource file
|
||||
try {
|
||||
ICUResourceBundle resource = (ICUResourceBundle) UResourceBundle.getBundleInstance(
|
||||
ICUData.ICU_UNIT_BASE_NAME, locale);
|
||||
ICUResourceBundle unitsRes = resource.getWithFallback(resourceKey);
|
||||
int size = unitsRes.getSize();
|
||||
for (int index = 0; index < size; ++index) {
|
||||
String timeUnitName = unitsRes.get(index).getKey();
|
||||
|
||||
private static final class TimeUnitFormatSetupSink extends UResource.Sink {
|
||||
Map<TimeUnit, Map<String, Object[]>> timeUnitToCountToPatterns;
|
||||
int style;
|
||||
Set<String> pluralKeywords;
|
||||
ULocale locale;
|
||||
boolean beenHere;
|
||||
|
||||
TimeUnitFormatSetupSink(Map<TimeUnit, Map<String, Object[]>> timeUnitToCountToPatterns,
|
||||
int style, Set<String> pluralKeywords, ULocale locale) {
|
||||
this.timeUnitToCountToPatterns = timeUnitToCountToPatterns;
|
||||
this.style = style;
|
||||
this.pluralKeywords = pluralKeywords;
|
||||
this.locale = locale;
|
||||
this.beenHere = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(UResource.Key key, UResource.Value value, boolean noFallback) {
|
||||
// Skip all put() calls except the first one -- discard all fallback data.
|
||||
if (beenHere) {
|
||||
return;
|
||||
} else {
|
||||
beenHere = true;
|
||||
}
|
||||
|
||||
UResource.Table units = value.getTable();
|
||||
for (int i = 0; units.getKeyAndValue(i, key, value); ++i) {
|
||||
String timeUnitName = key.toString();
|
||||
TimeUnit timeUnit = null;
|
||||
|
||||
if (timeUnitName.equals("year")) {
|
||||
timeUnit = TimeUnit.YEAR;
|
||||
} else if (timeUnitName.equals("month")) {
|
||||
|
@ -391,19 +411,18 @@ public class TimeUnitFormat extends MeasureFormat {
|
|||
} else {
|
||||
continue;
|
||||
}
|
||||
ICUResourceBundle oneUnitRes = unitsRes.getWithFallback(timeUnitName);
|
||||
int count = oneUnitRes.getSize();
|
||||
|
||||
Map<String, Object[]> countToPatterns = timeUnitToCountToPatterns.get(timeUnit);
|
||||
if (countToPatterns == null) {
|
||||
countToPatterns = new TreeMap<String, Object[]>();
|
||||
timeUnitToCountToPatterns.put(timeUnit, countToPatterns);
|
||||
}
|
||||
for (int pluralIndex = 0; pluralIndex < count; ++pluralIndex) {
|
||||
String pluralCount = oneUnitRes.get(pluralIndex).getKey();
|
||||
|
||||
UResource.Table countsToPatternTable = value.getTable();
|
||||
for (int j = 0; countsToPatternTable.getKeyAndValue(j, key, value); ++j) {
|
||||
String pluralCount = key.toString();
|
||||
if (!pluralKeywords.contains(pluralCount))
|
||||
continue;
|
||||
String pattern = oneUnitRes.get(pluralIndex).getString();
|
||||
final MessageFormat messageFormat = new MessageFormat(pattern, locale);
|
||||
// save both full name and abbreviated name in one table
|
||||
// is good space-wise, but it degrades performance,
|
||||
// since it needs to check whether the needed space
|
||||
|
@ -413,9 +432,27 @@ public class TimeUnitFormat extends MeasureFormat {
|
|||
pair = new Object[2];
|
||||
countToPatterns.put(pluralCount, pair);
|
||||
}
|
||||
pair[style] = messageFormat;
|
||||
if (pair[style] == null) {
|
||||
String pattern = value.getString();
|
||||
final MessageFormat messageFormat = new MessageFormat(pattern, locale);
|
||||
pair[style] = messageFormat;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setup(String resourceKey, Map<TimeUnit, Map<String, Object[]>> timeUnitToCountToPatterns, int style,
|
||||
Set<String> pluralKeywords) {
|
||||
// fill timeUnitToCountToPatterns from resource file
|
||||
try {
|
||||
|
||||
ICUResourceBundle resource = (ICUResourceBundle) UResourceBundle.getBundleInstance(
|
||||
ICUData.ICU_UNIT_BASE_NAME, locale);
|
||||
|
||||
TimeUnitFormatSetupSink sink = new TimeUnitFormatSetupSink(
|
||||
timeUnitToCountToPatterns, style, pluralKeywords, locale);
|
||||
resource.getAllItemsWithFallback(resourceKey, sink);
|
||||
} catch (MissingResourceException e) {
|
||||
}
|
||||
// there should be patterns for each plural rule in each time unit.
|
||||
|
@ -528,11 +565,11 @@ public class TimeUnitFormat extends MeasureFormat {
|
|||
searchInTree(resourceKey, styl, timeUnit, srcPluralCount, "other", countToPatterns);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// boilerplate code to make TimeUnitFormat otherwise follow the contract of
|
||||
// MeasureFormat
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @deprecated This API is ICU internal only.
|
||||
|
@ -543,7 +580,7 @@ public class TimeUnitFormat extends MeasureFormat {
|
|||
StringBuilder appendTo, FieldPosition fieldPosition, Measure... measures) {
|
||||
return mf.formatMeasures(appendTo, fieldPosition, measures);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @deprecated This API is ICU internal only.
|
||||
|
@ -553,7 +590,7 @@ public class TimeUnitFormat extends MeasureFormat {
|
|||
public MeasureFormat.FormatWidth getWidth() {
|
||||
return mf.getWidth();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @deprecated This API is ICU internal only.
|
||||
|
@ -563,7 +600,7 @@ public class TimeUnitFormat extends MeasureFormat {
|
|||
public NumberFormat getNumberFormat() {
|
||||
return mf.getNumberFormat();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @deprecated This API is ICU internal only.
|
||||
|
@ -576,13 +613,13 @@ public class TimeUnitFormat extends MeasureFormat {
|
|||
return result;
|
||||
}
|
||||
// End boilerplate.
|
||||
|
||||
|
||||
// Serialization
|
||||
|
||||
|
||||
private Object writeReplace() throws ObjectStreamException {
|
||||
return mf.toTimeUnitProxy();
|
||||
}
|
||||
|
||||
|
||||
// Preserve backward serialize backward compatibility.
|
||||
private Object readResolve() throws ObjectStreamException {
|
||||
return new TimeUnitFormat(locale, style, format);
|
||||
|
|
Loading…
Add table
Reference in a new issue