ICU-7618 replace MessageFormat with SimpleFormatterImpl where easy; remove obsolete ChoiceFormat handling of currency names

X-SVN-Rev: 38199
This commit is contained in:
Markus Scherer 2016-01-26 22:52:45 +00:00
parent 4382bcac9f
commit dcb76aab72
10 changed files with 94 additions and 105 deletions

View File

@ -1,7 +1,7 @@
/*
*******************************************************************************
* Copyright (C) 2009-2015, International Business Machines Corporation and *
* others. All Rights Reserved. *
* Copyright (C) 2009-2016, International Business Machines Corporation and
* others. All Rights Reserved.
*******************************************************************************
*/
package com.ibm.icu.impl;
@ -27,7 +27,6 @@ import com.ibm.icu.text.BreakIterator;
import com.ibm.icu.text.DisplayContext;
import com.ibm.icu.text.DisplayContext.Type;
import com.ibm.icu.text.LocaleDisplayNames;
import com.ibm.icu.text.MessageFormat;
import com.ibm.icu.util.ULocale;
import com.ibm.icu.util.UResourceBundle;
import com.ibm.icu.util.UResourceBundleIterator;
@ -39,9 +38,10 @@ public class LocaleDisplayNamesImpl extends LocaleDisplayNames {
private final DisplayContext nameLength;
private final DataTable langData;
private final DataTable regionData;
private final MessageFormat separatorFormat;
private final MessageFormat format;
private final MessageFormat keyTypeFormat;
// Compiled SimpleFormatter patterns.
private final String separatorFormat;
private final String format;
private final String keyTypeFormat;
private final char formatOpenParen;
private final char formatReplaceOpenParen;
private final char formatCloseParen;
@ -139,13 +139,14 @@ public class LocaleDisplayNamesImpl extends LocaleDisplayNames {
if ("separator".equals(sep)) {
sep = "{0}, {1}";
}
this.separatorFormat = new MessageFormat(sep);
StringBuilder sb = new StringBuilder();
this.separatorFormat = SimpleFormatterImpl.compileToStringMinMaxArguments(sep, sb, 2, 2);
String pattern = langData.get("localeDisplayPattern", "pattern");
if ("pattern".equals(pattern)) {
pattern = "{0} ({1})";
}
this.format = new MessageFormat(pattern);
this.format = SimpleFormatterImpl.compileToStringMinMaxArguments(pattern, sb, 2, 2);
if (pattern.contains("")) {
formatOpenParen = '';
formatCloseParen = '';
@ -162,7 +163,8 @@ public class LocaleDisplayNamesImpl extends LocaleDisplayNames {
if ("keyTypePattern".equals(keyTypePattern)) {
keyTypePattern = "{0}={1}";
}
this.keyTypeFormat = new MessageFormat(keyTypePattern);
this.keyTypeFormat = SimpleFormatterImpl.compileToStringMinMaxArguments(
keyTypePattern, sb, 2, 2);
// Get values from the contextTransforms data if we need them
// Also check whether we will need a break iterator (depends on the data)
@ -365,8 +367,8 @@ public class LocaleDisplayNamesImpl extends LocaleDisplayNames {
if (!valueDisplayName.equals(value)) {
appendWithSep(valueDisplayName, buf);
} else if (!key.equals(keyDisplayName)) {
String keyValue = keyTypeFormat.format(
new String[] { keyDisplayName, valueDisplayName });
String keyValue = SimpleFormatterImpl.formatCompiledPattern(
keyTypeFormat, keyDisplayName, valueDisplayName);
appendWithSep(keyValue, buf);
} else {
appendWithSep(keyDisplayName, buf)
@ -382,7 +384,8 @@ public class LocaleDisplayNamesImpl extends LocaleDisplayNames {
}
if (resultRemainder != null) {
resultName = format.format(new Object[] {resultName, resultRemainder});
resultName = SimpleFormatterImpl.formatCompiledPattern(
format, resultName, resultRemainder);
}
return adjustForUsageAndContext(CapitalizationContextUsage.LANGUAGE, resultName);
@ -639,8 +642,7 @@ public class LocaleDisplayNamesImpl extends LocaleDisplayNames {
if (b.length() == 0) {
b.append(s);
} else {
String combined = separatorFormat.format(new String[] { b.toString(), s });
b.replace(0, b.length(), combined);
SimpleFormatterImpl.formatAndReplace(separatorFormat, b, null, b, s);
}
return b;
}

View File

@ -186,6 +186,25 @@ public final class SimpleFormatterImpl {
return formatAndAppend(compiledPattern, new StringBuilder(), null, values).toString();
}
/**
* Formats the not-compiled pattern with the given values.
* Equivalent to compileToStringMinMaxArguments() followed by formatCompiledPattern().
* The number of arguments checked against the given limits is the
* highest argument number plus one, not the number of occurrences of arguments.
*
* @param pattern Not-compiled form of a pattern string.
* @param min The pattern must have at least this many arguments.
* @param max The pattern must have at most this many arguments.
* @return The compiled-pattern string.
* @throws IllegalArgumentException for bad argument syntax and too few or too many arguments.
*/
public static String formatRawPattern(String pattern, int min, int max, CharSequence... values) {
StringBuilder sb = new StringBuilder();
String compiledPattern = compileToStringMinMaxArguments(pattern, sb, min, max);
sb.setLength(0);
return formatAndAppend(compiledPattern, sb, null, values).toString();
}
/**
* Formats the given values, appending to the appendTo builder.
*

View File

@ -17,6 +17,7 @@ import java.util.Map;
import com.ibm.icu.impl.CalendarData;
import com.ibm.icu.impl.ICUCache;
import com.ibm.icu.impl.SimpleCache;
import com.ibm.icu.impl.SimpleFormatterImpl;
import com.ibm.icu.text.DateIntervalInfo.PatternInfo;
import com.ibm.icu.util.Calendar;
import com.ibm.icu.util.DateInterval;
@ -858,8 +859,8 @@ public class DateIntervalFormat extends UFormat {
laterDate = fDateFormat.format(toCalendar, laterDate, otherPos);
String fallbackPattern = fInfo.getFallbackIntervalPattern();
adjustPosition(fallbackPattern, earlierDate.toString(), pos, laterDate.toString(), otherPos, pos);
String fallbackRange = MessageFormat.format(fallbackPattern, new Object[]
{earlierDate.toString(), laterDate.toString()});
String fallbackRange = SimpleFormatterImpl.formatRawPattern(
fallbackPattern, 2, 2, earlierDate, laterDate);
if (formatDatePlusTimeRange) {
// fallbackRange has just the time range, need to format the date part and combine that
fDateFormat.applyPattern(fDatePattern);
@ -868,8 +869,8 @@ public class DateIntervalFormat extends UFormat {
otherPos.setEndIndex(0);
datePortion = fDateFormat.format(fromCalendar, datePortion, otherPos);
adjustPosition(fDateTimeFormat, fallbackRange, pos, datePortion.toString(), otherPos, pos);
fallbackRange = MessageFormat.format(fDateTimeFormat, new Object[]
{fallbackRange, datePortion.toString()});
fallbackRange = SimpleFormatterImpl.formatRawPattern(
fDateTimeFormat, 2, 2, fallbackRange, datePortion);
}
appendTo.append(fallbackRange);
if (formatDatePlusTimeRange) {
@ -1813,8 +1814,8 @@ public class DateIntervalFormat extends UFormat {
if ( timeItvPtnInfo != null ) {
String timeIntervalPattern = timeItvPtnInfo.getFirstPart() +
timeItvPtnInfo.getSecondPart();
String pattern = MessageFormat.format(dtfmt, new Object[]
{timeIntervalPattern, datePattern});
String pattern = SimpleFormatterImpl.formatRawPattern(
dtfmt, 2, 2, timeIntervalPattern, datePattern);
timeItvPtnInfo = DateIntervalInfo.genPatternInfo(pattern,
timeItvPtnInfo.firstDateInPtnIsLaterDate());
intervalPatterns.put(

View File

@ -1,7 +1,7 @@
/*
********************************************************************************
* Copyright (C) 2006-2015, Google, International Business Machines Corporation *
* and others. All Rights Reserved. *
* Copyright (C) 2006-2016, Google, International Business Machines Corporation
* and others. All Rights Reserved.
********************************************************************************
*/
package com.ibm.icu.text;
@ -27,6 +27,7 @@ import com.ibm.icu.impl.ICUCache;
import com.ibm.icu.impl.ICUResourceBundle;
import com.ibm.icu.impl.PatternTokenizer;
import com.ibm.icu.impl.SimpleCache;
import com.ibm.icu.impl.SimpleFormatterImpl;
import com.ibm.icu.impl.Utility;
import com.ibm.icu.util.Calendar;
import com.ibm.icu.util.Freezable;
@ -434,7 +435,8 @@ public class DateTimePatternGenerator implements Freezable<DateTimePatternGenera
if (datePattern == null) return timePattern == null ? "" : timePattern;
if (timePattern == null) return datePattern;
return MessageFormat.format(getDateTimeFormat(), new Object[]{timePattern, datePattern});
return SimpleFormatterImpl.formatRawPattern(
getDateTimeFormat(), 2, 2, timePattern, datePattern);
}
/**
@ -1646,7 +1648,8 @@ public class DateTimePatternGenerator implements Freezable<DateTimePatternGenera
String temp = adjustFieldTypes(tempWithMatcher, source, flags, options);
int foundMask = startingMask & ~distInfo.missingFieldMask;
int topField = getTopBitNumber(foundMask);
resultPattern = MessageFormat.format(getAppendFormat(topField), new Object[]{resultPattern, temp, getAppendName(topField)});
resultPattern = SimpleFormatterImpl.formatRawPattern(
getAppendFormat(topField), 2, 3, resultPattern, temp, getAppendName(topField));
}
}
return resultPattern;

View File

@ -1,7 +1,7 @@
/*
*******************************************************************************
* Copyright (C) 1996-2015, International Business Machines Corporation and *
* others. All Rights Reserved. *
* Copyright (C) 1996-2016, International Business Machines Corporation and
* others. All Rights Reserved.
*******************************************************************************
*/
package com.ibm.icu.text;
@ -4040,19 +4040,19 @@ public class DecimalFormat extends NumberFormat {
// Reuse one StringBuffer for better performance
StringBuffer buffer = new StringBuffer();
if (posPrefixPattern != null) {
expandAffix(posPrefixPattern, pluralCount, buffer, false);
expandAffix(posPrefixPattern, pluralCount, buffer);
positivePrefix = buffer.toString();
}
if (posSuffixPattern != null) {
expandAffix(posSuffixPattern, pluralCount, buffer, false);
expandAffix(posSuffixPattern, pluralCount, buffer);
positiveSuffix = buffer.toString();
}
if (negPrefixPattern != null) {
expandAffix(negPrefixPattern, pluralCount, buffer, false);
expandAffix(negPrefixPattern, pluralCount, buffer);
negativePrefix = buffer.toString();
}
if (negSuffixPattern != null) {
expandAffix(negSuffixPattern, pluralCount, buffer, false);
expandAffix(negSuffixPattern, pluralCount, buffer);
negativeSuffix = buffer.toString();
}
}
@ -4071,6 +4071,7 @@ public class DecimalFormat extends NumberFormat {
* it is used to expand the stored affix patterns given a specific number (doFormat ==
* true), for those rare cases in which a currency format references a ChoiceFormat
* (e.g., en_IN display name for INR). The number itself is taken from digitList.
* TODO: There are no currency ChoiceFormat patterns, figure out what is still relevant here.
*
* When used in the first way, this method has a side effect: It sets currencyChoice
* to a ChoiceFormat object, if the currency's display name in this locale is a
@ -4083,15 +4084,9 @@ public class DecimalFormat extends NumberFormat {
* it is the singular "one", or the plural "other". For all other cases, it is null,
* and is not being used.
* @param buffer a scratch StringBuffer; its contents will be lost
* @param doFormat if false, then the pattern will be expanded, and if a currency
* symbol is encountered that expands to a ChoiceFormat, the currencyChoice member
* variable will be initialized if it is null. If doFormat is true, then it is assumed
* that the currencyChoice has been created, and it will be used to format the value
* in digitList.
*/
// Bug 4212072 [Richard/GCL]
private void expandAffix(String pattern, String pluralCount, StringBuffer buffer,
boolean doFormat) {
private void expandAffix(String pattern, String pluralCount, StringBuffer buffer) {
buffer.setLength(0);
for (int i = 0; i < pattern.length();) {
char c = pattern.charAt(i++);
@ -4143,37 +4138,10 @@ public class DecimalFormat extends NumberFormat {
// when formatting currency plural names. For other cases,
// pluralCount == null, and plural names are not needed.
if (plural && pluralCount != null) {
boolean isChoiceFormat[] = new boolean[1];
s = currency.getName(symbols.getULocale(), Currency.PLURAL_LONG_NAME,
pluralCount, isChoiceFormat);
pluralCount, null);
} else if (!intl) {
boolean isChoiceFormat[] = new boolean[1];
s = currency.getName(symbols.getULocale(), Currency.SYMBOL_NAME,
isChoiceFormat);
if (isChoiceFormat[0]) {
// Two modes here: If doFormat is false, we set up
// currencyChoice. If doFormat is true, we use the previously
// created currencyChoice to format the value in digitList.
if (!doFormat) {
// If the currency is handled by a ChoiceFormat, then
// we're not going to use the expanded
// patterns. Instantiate the ChoiceFormat and return.
if (currencyChoice == null) {
currencyChoice = new ChoiceFormat(s);
}
// We could almost return null or "" here, since the
// expanded affixes are almost not used at all in this
// situation. However, one method -- toPattern() -- still
// does use the expanded affixes, in order to set up a
// padding pattern. We use the CURRENCY_SIGN as a
// placeholder.
s = String.valueOf(CURRENCY_SIGN);
} else {
FieldPosition pos = new FieldPosition(0); // ignored
currencyChoice.format(digitList.getDouble(), buffer, pos);
continue;
}
}
s = currency.getName(symbols.getULocale(), Currency.SYMBOL_NAME, null);
} else {
s = currency.getCurrencyCode();
}
@ -4220,7 +4188,7 @@ public class DecimalFormat extends NumberFormat {
affixPat = isNegative ? negSuffixPattern : posSuffixPattern;
}
StringBuffer affixBuf = new StringBuffer();
expandAffix(affixPat, null, affixBuf, true);
expandAffix(affixPat, null, affixBuf);
buf.append(affixBuf);
return affixBuf.length();
}
@ -5287,9 +5255,7 @@ public class DecimalFormat extends NumberFormat {
super.setCurrency(theCurrency);
if (theCurrency != null) {
boolean[] isChoiceFormat = new boolean[1];
String s = theCurrency.getName(symbols.getULocale(),
Currency.SYMBOL_NAME, isChoiceFormat);
String s = theCurrency.getName(symbols.getULocale(), Currency.SYMBOL_NAME, null);
symbols.setCurrency(theCurrency);
symbols.setCurrencySymbol(s);
}
@ -5602,6 +5568,7 @@ public class DecimalFormat extends NumberFormat {
/**
* Formatter for ChoiceFormat-based currency names. If this field is not null, then
* delegate to it to format currency symbols.
* TODO: This is obsolete: Remove, and design extensible serialization. ICU ticket #12090.
*
* @since ICU 2.6
*/

View File

@ -1,7 +1,7 @@
/*
*******************************************************************************
* Copyright (C) 1996-2015, International Business Machines Corporation and *
* others. All Rights Reserved. *
* Copyright (C) 1996-2016, International Business Machines Corporation and
* others. All Rights Reserved.
*******************************************************************************
*/
package com.ibm.icu.text;
@ -9,7 +9,6 @@ package com.ibm.icu.text;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.text.ChoiceFormat;
import java.util.Arrays;
import java.util.Locale;
import java.util.MissingResourceException;
@ -966,17 +965,10 @@ public class DecimalFormatSymbols implements Cloneable, Serializable {
// Obtain currency data from the currency API. This is strictly
// for backward compatibility; we don't use DecimalFormatSymbols
// for currency data anymore.
String currname = null;
currency = Currency.getInstance(locale);
if (currency != null) {
intlCurrencySymbol = currency.getCurrencyCode();
boolean[] isChoiceFormat = new boolean[1];
currname = currency.getName(locale, Currency.SYMBOL_NAME, isChoiceFormat);
// If this is a ChoiceFormat currency, then format an
// arbitrary value; pick something != 1; more common.
currencySymbol = isChoiceFormat[0]
? new ChoiceFormat(currname).format(2.0)
: currname;
currencySymbol = currency.getName(locale, Currency.SYMBOL_NAME, null);
CurrencyFormatInfo fmtInfo = info.getFormatInfo(intlCurrencySymbol);
if (fmtInfo != null) {
currencyPattern = fmtInfo.currencyPattern;

View File

@ -356,7 +356,8 @@ public final class RelativeDateTimeFormatter {
return new RelativeDateTimeFormatter(
data.qualitativeUnitMap,
data.relUnitPatternMap,
new MessageFormat(data.dateTimePattern),
SimpleFormatterImpl.compileToStringMinMaxArguments(
data.dateTimePattern, new StringBuilder(), 2, 2),
PluralRules.forLocale(locale),
nf,
style,
@ -492,8 +493,8 @@ public final class RelativeDateTimeFormatter {
* @stable ICU 53
*/
public String combineDateAndTime(String relativeDateString, String timeString) {
return this.combinedDateAndTime.format(
new Object[]{timeString, relativeDateString}, new StringBuffer(), null).toString();
return SimpleFormatterImpl.formatCompiledPattern(
combinedDateAndTime, timeString, relativeDateString);
}
/**
@ -544,7 +545,7 @@ public final class RelativeDateTimeFormatter {
private RelativeDateTimeFormatter(
EnumMap<Style, EnumMap<AbsoluteUnit, EnumMap<Direction, String>>> qualitativeUnitMap,
EnumMap<Style, EnumMap<RelativeUnit, String[][]>> patternMap,
MessageFormat combinedDateAndTime,
String combinedDateAndTime,
PluralRules pluralRules,
NumberFormat numberFormat,
Style style,
@ -601,7 +602,7 @@ public final class RelativeDateTimeFormatter {
private final EnumMap<Style, EnumMap<AbsoluteUnit, EnumMap<Direction, String>>> qualitativeUnitMap;
private final EnumMap<Style, EnumMap<RelativeUnit, String[][]>> patternMap;
private final MessageFormat combinedDateAndTime;
private final String combinedDateAndTime; // compiled SimpleFormatter pattern
private final PluralRules pluralRules;
private final NumberFormat numberFormat;

View File

@ -1,6 +1,6 @@
/*
*******************************************************************************
* Copyright (C) 1996-2015, International Business Machines Corporation and
* Copyright (C) 1996-2016, International Business Machines Corporation and
* others. All Rights Reserved.
*******************************************************************************
*/
@ -28,6 +28,7 @@ import com.ibm.icu.impl.DateNumberFormat;
import com.ibm.icu.impl.ICUCache;
import com.ibm.icu.impl.PatternProps;
import com.ibm.icu.impl.SimpleCache;
import com.ibm.icu.impl.SimpleFormatterImpl;
import com.ibm.icu.lang.UCharacter;
import com.ibm.icu.text.TimeZoneFormat.Style;
import com.ibm.icu.text.TimeZoneFormat.TimeType;
@ -1181,8 +1182,9 @@ public class SimpleDateFormat extends DateFormat {
{
glueIndex += (SHORT + 1);
}
cachedDefaultPattern = MessageFormat.format(dateTimePatterns[glueIndex],
new Object[] {dateTimePatterns[SHORT], dateTimePatterns[SHORT + 4]});
cachedDefaultPattern = SimpleFormatterImpl.formatRawPattern(
dateTimePatterns[glueIndex], 2, 2,
dateTimePatterns[SHORT], dateTimePatterns[SHORT + 4]);
} catch (MissingResourceException e) {
cachedDefaultPattern = FALLBACKPATTERN;
}
@ -1919,7 +1921,8 @@ public class SimpleDateFormat extends DateFormat {
if (monthPattern == null) {
appendTo.append(array[value]);
} else {
appendTo.append(MessageFormat.format(monthPattern, array[value]));
String s = SimpleFormatterImpl.formatRawPattern(monthPattern, 1, 1, array[value]);
appendTo.append(s);
}
}
}
@ -2684,7 +2687,8 @@ public class SimpleDateFormat extends DateFormat {
isLeapMonth = 0;
}
if (monthPattern != null) {
String leapMonthName = MessageFormat.format(monthPattern, data[i]);
String leapMonthName = SimpleFormatterImpl.formatRawPattern(
monthPattern, 1, 1, data[i]);
length = leapMonthName.length();
if (length > bestMatchLength &&
(matchLength = regionMatchesWithOptionalDot(text, start, leapMonthName, length)) >= 0)

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 1996-2015, International Business Machines
* Copyright (C) 1996-2016, International Business Machines
* Corporation and others. All Rights Reserved.
*/
@ -20,10 +20,10 @@ import com.ibm.icu.impl.CalendarUtil;
import com.ibm.icu.impl.ICUCache;
import com.ibm.icu.impl.ICUResourceBundle;
import com.ibm.icu.impl.SimpleCache;
import com.ibm.icu.impl.SimpleFormatterImpl;
import com.ibm.icu.impl.SoftCache;
import com.ibm.icu.text.DateFormat;
import com.ibm.icu.text.DateFormatSymbols;
import com.ibm.icu.text.MessageFormat;
import com.ibm.icu.text.SimpleDateFormat;
import com.ibm.icu.util.ULocale.Category;
@ -3555,9 +3555,10 @@ public abstract class Calendar implements Serializable, Cloneable, Comparable<Ca
// Resolve a pattern for the date/time style
String pattern = null;
if ((timeStyle >= 0) && (dateStyle >= 0)) {
pattern = MessageFormat.format(patternData.getDateTimePattern(dateStyle),
new Object[] {patternData.patterns[timeStyle],
patternData.patterns[dateStyle + 4]});
pattern = SimpleFormatterImpl.formatRawPattern(
patternData.getDateTimePattern(dateStyle), 2, 2,
patternData.patterns[timeStyle],
patternData.patterns[dateStyle + 4]);
// Might need to merge the overrides from the date and time into a single
// override string TODO: Right now we are forcing the date's override into the
// time style.

View File

@ -1,7 +1,7 @@
/*
*******************************************************************************
* Copyright (C) 2006-2015, Google, International Business Machines Corporation *
* and others. All Rights Reserved. *
* Copyright (C) 2006-2016, Google, International Business Machines Corporation
* and others. All Rights Reserved.
*******************************************************************************
*/
@ -866,24 +866,23 @@ public class DateTimeGeneratorTest extends TestFmwk {
*/
public void TestGetRedundants(){
DateTimePatternGenerator dtpg = DateTimePatternGenerator.getInstance();
// Tests when "if (output == null)" is true
try{
dtpg.getRedundants(null);
} catch(Exception e){
errln("DateTimeGenerator.getRedundants was not suppose to return " +
"an exception when passing a null parameter.");
errln("DateTimeGenerator.getRedundants was not supposed to return " +
"an exception when passing a null parameter: " + e);
}
// Tests when "if (output == null)" is false
try{
Collection<String> out = new LinkedHashSet<String>();
dtpg.getRedundants(out);
} catch(Exception e){
errln("DateTimeGenerator.getRedundants was not suppose to return " +
"an exception when passing a new LinkedHashSet<String>() parameter.");
errln("DateTimeGenerator.getRedundants was not supposed to return " +
"an exception when passing a new LinkedHashSet<String>() parameter: " + e);
}
}
/* Tests the method