ICU-13073 Adding API for setting custom compact data, for CLDR Survey Tool.

X-SVN-Rev: 40117
This commit is contained in:
Shane Carr 2017-05-12 21:50:31 +00:00
parent b9f7feaf26
commit 36c6e6c6a2
4 changed files with 129 additions and 3 deletions

View File

@ -12,6 +12,7 @@ import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Map;
import com.ibm.icu.impl.number.Parse.GroupingMode;
import com.ibm.icu.impl.number.Parse.ParseMode;
@ -73,6 +74,7 @@ public class Properties
/| or #equals(), but it will NOT catch if you forget to add it to #hashCode(). |/
/+--------------------------------------------------------------------------------------------*/
private transient Map<String, Map<String, String>> compactCustomData;
private transient CompactStyle compactStyle;
private transient Currency currency;
private transient CurrencyPluralInfo currencyPluralInfo;
@ -132,6 +134,7 @@ public class Properties
}
private Properties _clear() {
compactCustomData = DEFAULT_COMPACT_CUSTOM_DATA;
compactStyle = DEFAULT_COMPACT_STYLE;
currency = DEFAULT_CURRENCY;
currencyPluralInfo = DEFAULT_CURRENCY_PLURAL_INFO;
@ -180,6 +183,7 @@ public class Properties
}
private Properties _copyFrom(Properties other) {
compactCustomData = other.compactCustomData;
compactStyle = other.compactStyle;
currency = other.currency;
currencyPluralInfo = other.currencyPluralInfo;
@ -229,6 +233,7 @@ public class Properties
private boolean _equals(Properties other) {
boolean eq = true;
eq = eq && _equalsHelper(compactCustomData, other.compactCustomData);
eq = eq && _equalsHelper(compactStyle, other.compactStyle);
eq = eq && _equalsHelper(currency, other.currency);
eq = eq && _equalsHelper(currencyPluralInfo, other.currencyPluralInfo);
@ -292,6 +297,7 @@ public class Properties
private int _hashCode() {
int hashCode = 0;
hashCode ^= _hashCodeHelper(compactCustomData);
hashCode ^= _hashCodeHelper(compactStyle);
hashCode ^= _hashCodeHelper(currency);
hashCode ^= _hashCodeHelper(currencyPluralInfo);
@ -386,6 +392,13 @@ public class Properties
return _equals((Properties) other);
}
/// BEGIN GETTERS/SETTERS ///
@Override
public Map<String, Map<String, String>> getCompactCustomData() {
return compactCustomData;
}
@Override
public CompactStyle getCompactStyle() {
return compactStyle;
@ -396,8 +409,6 @@ public class Properties
return currency;
}
/// BEGIN GETTERS/SETTERS ///
@Override
@Deprecated
public CurrencyPluralInfo getCurrencyPluralInfo() {
@ -660,6 +671,12 @@ public class Properties
}
}
@Override
public Properties setCompactCustomData(Map<String, Map<String, String>> compactCustomData) {
this.compactCustomData = compactCustomData;
return this;
}
@Override
public Properties setCompactStyle(CompactStyle compactStyle) {
this.compactStyle = compactStyle;

View File

@ -49,6 +49,39 @@ public class CompactDecimalFormat extends Format.BeforeFormat {
* @return The property bag, for chaining.
*/
public IProperties setCompactStyle(CompactStyle compactStyle);
static Map<String, Map<String, String>> DEFAULT_COMPACT_CUSTOM_DATA = null;
/** @see #setCompactCustomData */
public Map<String, Map<String, String>> getCompactCustomData();
/**
* Specifies custom data to be used instead of CLDR data when constructing a
* CompactDecimalFormat. The argument should be a map with the following structure:
*
* <pre>
* {
* "1000": {
* "one": "0 thousand",
* "other": "0 thousand"
* },
* "10000": {
* "one": "00 thousand",
* "other": "00 thousand"
* },
* // ...
* }
* </pre>
*
* This API endpoint is used by the CLDR Survey Tool.
*
* @param compactCustomData A map with the above structure.
* @return The property bag, for chaining.
* @internal
* @deprecated This API is ICU internal only.
*/
@Deprecated
public IProperties setCompactCustomData(Map<String, Map<String, String>> compactCustomData);
}
public static boolean useCompactDecimalFormat(IProperties properties) {
@ -179,7 +212,12 @@ public class CompactDecimalFormat extends Format.BeforeFormat {
private CompactDecimalFormat(DecimalFormatSymbols symbols, IProperties properties) {
CompactDecimalFingerprint fingerprint = new CompactDecimalFingerprint(symbols, properties);
this.rounder = getRounder(properties);
this.data = getData(symbols, fingerprint);
// Short-circuit and use custom data if provided
if (properties.getCompactCustomData() != null) {
this.data = createDataFromCustom(symbols, fingerprint, properties.getCompactCustomData());
} else {
this.data = getData(symbols, fingerprint);
}
this.defaultMod = getDefaultMod(symbols, fingerprint);
this.style = properties.getCompactStyle(); // for exporting only
}
@ -492,4 +530,34 @@ public class CompactDecimalFormat extends Format.BeforeFormat {
}
}
}
/**
* Uses data from the custom powersToPluralsToPatterns map instead of an ICUResourceBundle to
* populate an instance of CompactDecimalData.
*/
static CompactDecimalData createDataFromCustom(
DecimalFormatSymbols symbols,
CompactDecimalFingerprint fingerprint,
Map<String, Map<String, String>> powersToPluralsToPatterns) {
CompactDecimalData data = new CompactDecimalData();
PNAffixGenerator pnag = PNAffixGenerator.getThreadLocalInstance();
for (Map.Entry<String, Map<String, String>> magnitudeEntry :
powersToPluralsToPatterns.entrySet()) {
byte magnitude = (byte) (magnitudeEntry.getKey().length() - 1);
for (Map.Entry<String, String> pluralEntry : magnitudeEntry.getValue().entrySet()) {
StandardPlural plural = StandardPlural.fromString(pluralEntry.getKey().toString());
String patternString = pluralEntry.getValue().toString();
Properties properties = PatternString.parseToProperties(patternString);
byte _multiplier = (byte) -(magnitude - properties.getMinimumIntegerDigits() + 1);
if (_multiplier != data.setOrGetMultiplier(magnitude, _multiplier)) {
throw new IllegalArgumentException(
"Different number of zeros for same power of ten in custom compact decimal format data");
}
PNAffixGenerator.Result result =
pnag.getModifiers(symbols, fingerprint.currencySymbol, properties);
data.setModifiers(result.positive, result.negative, magnitude, plural);
}
}
return data;
}
}

View File

@ -20,14 +20,18 @@ import java.text.AttributedCharacterIterator;
import java.text.CharacterIterator;
import java.text.FieldPosition;
import java.text.ParsePosition;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import org.junit.Test;
import com.ibm.icu.dev.test.TestFmwk;
import com.ibm.icu.impl.number.Properties;
import com.ibm.icu.text.CompactDecimalFormat;
import com.ibm.icu.text.CompactDecimalFormat.CompactStyle;
import com.ibm.icu.text.DecimalFormat;
import com.ibm.icu.text.DecimalFormat.PropertySetter;
import com.ibm.icu.text.NumberFormat;
import com.ibm.icu.util.Currency;
import com.ibm.icu.util.CurrencyAmount;
@ -649,6 +653,27 @@ public class CompactDecimalFormatTest extends TestFmwk {
}
}
@Test
public void TestCustomData() {
final Map<String,Map<String,String>> customData = new HashMap<String,Map<String,String>>();
Map<String,String> inner = new HashMap<String,String>();
inner.put("one", "0 qwerty");
inner.put("other", "0 dvorak");
customData.put("1000", inner);
CompactDecimalFormat cdf = CompactDecimalFormat.getInstance(ULocale.ENGLISH, CompactStyle.SHORT);
cdf.setProperties(new PropertySetter() {
@Override
public void set(Properties props) {
props.setCompactCustomData(customData);
}
});
assertEquals("Below custom range", "120", cdf.format(123));
assertEquals("Plural form one", "1 qwerty", cdf.format(1000));
assertEquals("Plural form other", "1.2 dvorak", cdf.format(1234));
assertEquals("Above custom range", "12 dvorak", cdf.format(12345));
assertEquals("Negative number", "-1 qwerty", cdf.format(-1000));
}
@Test
public void TestBug12422() {
CompactDecimalFormat cdf;

View File

@ -21,7 +21,9 @@ import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.junit.Test;
@ -259,6 +261,20 @@ public class PropertiesTest {
FormatWidth[] values = FormatWidth.values();
return values[seed % values.length];
} else if (type == Map.class) {
// Map<String,Map<String,String>> for compactCustomData property
if (seed == 0) return null;
Map<String, Map<String, String>> outer = new HashMap<String, Map<String, String>>();
Map<String, String> inner = new HashMap<String, String>();
inner.put("one", "0 thousand");
StringBuilder magnitudeKey = new StringBuilder();
magnitudeKey.append("1000");
for (int i = 0; i < seed % 9; i++) {
magnitudeKey.append("0");
}
outer.put(magnitudeKey.toString(), inner);
return outer;
} else if (type == MathContext.class) {
if (seed == 0) return null;
RoundingMode[] modes = RoundingMode.values();