ICU-20230 Implementing COMPACT field.

Adds some plumbing to allow MutablePatternModifier to set fields, and otherwise builds upon the infrastructure from the previous commit to add the MEASURE_UNIT field.
This commit is contained in:
Shane Carr 2018-11-15 20:58:24 -08:00 committed by Shane F. Carr
parent ee9c0b944c
commit c0799c141b
19 changed files with 303 additions and 37 deletions

View file

@ -158,7 +158,7 @@ Field AffixUtils::getFieldForType(AffixPatternType type) {
int32_t
AffixUtils::unescape(const UnicodeString &affixPattern, NumberStringBuilder &output, int32_t position,
const SymbolProvider &provider, UErrorCode &status) {
const SymbolProvider &provider, Field field, UErrorCode &status) {
int32_t length = 0;
AffixTag tag;
while (hasNext(tag, affixPattern)) {
@ -171,7 +171,7 @@ AffixUtils::unescape(const UnicodeString &affixPattern, NumberStringBuilder &out
length += output.insert(
position + length, provider.getSymbol(tag.type), getFieldForType(tag.type), status);
} else {
length += output.insertCodePoint(position + length, tag.codePoint, UNUM_FIELD_COUNT, status);
length += output.insertCodePoint(position + length, tag.codePoint, field, status);
}
}
return length;

View file

@ -144,7 +144,8 @@ class U_I18N_API AffixUtils {
* @param provider An object to generate locale symbols.
*/
static int32_t unescape(const UnicodeString& affixPattern, NumberStringBuilder& output,
int32_t position, const SymbolProvider& provider, UErrorCode& status);
int32_t position, const SymbolProvider& provider, Field field,
UErrorCode& status);
/**
* Sames as {@link #unescape}, but only calculates the code point count. More efficient than {@link #unescape}

View file

@ -260,7 +260,7 @@ void CompactHandler::precomputeAllModifiers(MutablePatternModifier &buildReferen
ParsedPatternInfo patternInfo;
PatternParser::parseToPatternInfo(UnicodeString(patternString), patternInfo, status);
if (U_FAILURE(status)) { return; }
buildReference.setPatternInfo(&patternInfo);
buildReference.setPatternInfo(&patternInfo, UNUM_COMPACT_FIELD);
info.mod = buildReference.createImmutable(status);
if (U_FAILURE(status)) { return; }
info.patternString = patternString;
@ -310,7 +310,7 @@ void CompactHandler::processQuantity(DecimalQuantity &quantity, MicroProps &micr
ParsedPatternInfo &patternInfo = const_cast<CompactHandler *>(this)->unsafePatternInfo;
PatternParser::parseToPatternInfo(UnicodeString(patternString), patternInfo, status);
static_cast<MutablePatternModifier*>(const_cast<Modifier*>(micros.modMiddle))
->setPatternInfo(&patternInfo);
->setPatternInfo(&patternInfo, UNUM_COMPACT_FIELD);
}
// We already performed rounding. Do not perform it again.

View file

@ -344,7 +344,8 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps& macros, bool safe,
fPatternModifier.adoptInstead(patternModifier);
patternModifier->setPatternInfo(
macros.affixProvider != nullptr ? macros.affixProvider
: static_cast<const AffixPatternProvider*>(fPatternInfo.getAlias()));
: static_cast<const AffixPatternProvider*>(fPatternInfo.getAlias()),
UNUM_FIELD_COUNT);
patternModifier->setPatternAttributes(fMicros.sign, isPermille);
if (patternModifier->needsPlurals()) {
patternModifier->setSymbols(

View file

@ -23,13 +23,14 @@ AffixPatternProvider::~AffixPatternProvider() = default;
MutablePatternModifier::MutablePatternModifier(bool isStrong)
: fStrong(isStrong) {}
void MutablePatternModifier::setPatternInfo(const AffixPatternProvider* patternInfo) {
void MutablePatternModifier::setPatternInfo(const AffixPatternProvider* patternInfo, Field field) {
fPatternInfo = patternInfo;
fField = field;
}
void MutablePatternModifier::setPatternAttributes(UNumberSignDisplay signDisplay, bool perMille) {
fSignDisplay = signDisplay;
this->perMilleReplacesPercent = perMille;
fPerMilleReplacesPercent = perMille;
}
void MutablePatternModifier::setSymbols(const DecimalFormatSymbols* symbols,
@ -255,20 +256,20 @@ bool MutablePatternModifier::semanticallyEquivalent(const Modifier& other) const
int32_t MutablePatternModifier::insertPrefix(NumberStringBuilder& sb, int position, UErrorCode& status) {
prepareAffix(true);
int length = AffixUtils::unescape(currentAffix, sb, position, *this, status);
int32_t length = AffixUtils::unescape(currentAffix, sb, position, *this, fField, status);
return length;
}
int32_t MutablePatternModifier::insertSuffix(NumberStringBuilder& sb, int position, UErrorCode& status) {
prepareAffix(false);
int length = AffixUtils::unescape(currentAffix, sb, position, *this, status);
int32_t length = AffixUtils::unescape(currentAffix, sb, position, *this, fField, status);
return length;
}
/** This method contains the heart of the logic for rendering LDML affix strings. */
void MutablePatternModifier::prepareAffix(bool isPrefix) {
PatternStringUtils::patternInfoToStringBuilder(
*fPatternInfo, isPrefix, fSignum, fSignDisplay, fPlural, perMilleReplacesPercent, currentAffix);
*fPatternInfo, isPrefix, fSignum, fSignDisplay, fPlural, fPerMilleReplacesPercent, currentAffix);
}
UnicodeString MutablePatternModifier::getSymbol(AffixPatternType type) const {

View file

@ -95,8 +95,11 @@ class U_I18N_API MutablePatternModifier
* Sets a reference to the parsed decimal format pattern, usually obtained from
* {@link PatternStringParser#parseToPatternInfo(String)}, but any implementation of {@link AffixPatternProvider} is
* accepted.
*
* @param field
* Which field to use for literal characters in the pattern.
*/
void setPatternInfo(const AffixPatternProvider *patternInfo);
void setPatternInfo(const AffixPatternProvider *patternInfo, Field field);
/**
* Sets attributes that imply changes to the literal interpretation of the pattern string affixes.
@ -203,8 +206,9 @@ class U_I18N_API MutablePatternModifier
// Pattern details (initialized in setPatternInfo and setPatternAttributes)
const AffixPatternProvider *fPatternInfo;
Field fField;
UNumberSignDisplay fSignDisplay;
bool perMilleReplacesPercent;
bool fPerMilleReplacesPercent;
// Symbol details (initialized in setSymbols)
const DecimalFormatSymbols *fSymbols;

View file

@ -239,6 +239,8 @@ public:
kSignField = UNUM_SIGN_FIELD,
/** @draft ICU 64 */
kMeasureUnitField = UNUM_MEASURE_UNIT_FIELD,
/** @draft ICU 64 */
kCompactField = UNUM_COMPACT_FIELD,
/**
* These constants are provided for backwards compatibility only.

View file

@ -377,6 +377,9 @@ typedef enum UNumberFormatFields {
UNUM_SIGN_FIELD,
/** @draft ICU 64 */
UNUM_MEASURE_UNIT_FIELD,
/** @draft ICU 64 */
UNUM_COMPACT_FIELD,
#ifndef U_HIDE_DEPRECATED_API
/**
* One more than the highest normal UNumberFormatFields value.

View file

@ -223,7 +223,7 @@ void AffixUtilsTest::testUnescapeWithSymbolProvider() {
UnicodeString input(cas[0]);
UnicodeString expected(cas[1]);
sb.clear();
AffixUtils::unescape(input, sb, 0, provider, status);
AffixUtils::unescape(input, sb, 0, provider, UNUM_FIELD_COUNT, status);
assertSuccess("Spot 1", status);
assertEquals(input, expected, sb.toUnicodeString());
assertEquals(input, expected, sb.toTempUnicodeString());
@ -233,7 +233,7 @@ void AffixUtilsTest::testUnescapeWithSymbolProvider() {
sb.clear();
sb.append(u"abcdefg", UNUM_FIELD_COUNT, status);
assertSuccess("Spot 2", status);
AffixUtils::unescape(u"-+%", sb, 4, provider, status);
AffixUtils::unescape(u"-+%", sb, 4, provider, UNUM_FIELD_COUNT, status);
assertSuccess("Spot 3", status);
assertEquals(u"Symbol provider into middle", u"abcd123efg", sb.toUnicodeString());
}
@ -241,7 +241,7 @@ void AffixUtilsTest::testUnescapeWithSymbolProvider() {
UnicodeString AffixUtilsTest::unescapeWithDefaults(const SymbolProvider &defaultProvider,
UnicodeString input, UErrorCode &status) {
NumberStringBuilder nsb;
int32_t length = AffixUtils::unescape(input, nsb, 0, defaultProvider, status);
int32_t length = AffixUtils::unescape(input, nsb, 0, defaultProvider, UNUM_FIELD_COUNT, status);
assertEquals("Return value of unescape", nsb.length(), length);
return nsb.toUnicodeString();
}

View file

@ -2349,6 +2349,130 @@ void NumberFormatterApiTest::fieldPositionCoverage() {
expectedFieldPositions,
sizeof(expectedFieldPositions)/sizeof(*expectedFieldPositions));
}
{
const char16_t* message = u"Compact field basic";
FormattedNumber result = assertFormatSingle(
message,
u"compact-short",
NumberFormatter::with().notation(Notation::compactShort()),
Locale::getUS(),
65000,
u"65K");
static const UFieldPosition expectedFieldPositions[] = {
// field, begin index, end index
{UNUM_INTEGER_FIELD, 0, 2},
{UNUM_COMPACT_FIELD, 2, 3}};
assertFieldPositions(
message,
result,
expectedFieldPositions,
sizeof(expectedFieldPositions)/sizeof(*expectedFieldPositions));
}
{
const char16_t* message = u"Compact field with spaces";
FormattedNumber result = assertFormatSingle(
message,
u"compact-long",
NumberFormatter::with().notation(Notation::compactLong()),
Locale::getUS(),
65000,
u"65 thousand");
static const UFieldPosition expectedFieldPositions[] = {
// field, begin index, end index
{UNUM_INTEGER_FIELD, 0, 2},
{UNUM_COMPACT_FIELD, 3, 11}};
assertFieldPositions(
message,
result,
expectedFieldPositions,
sizeof(expectedFieldPositions)/sizeof(*expectedFieldPositions));
}
{
const char16_t* message = u"Compact field with inner space";
FormattedNumber result = assertFormatSingle(
message,
u"compact-long",
NumberFormatter::with().notation(Notation::compactLong()),
"fil", // locale with interesting data
6000,
u"6 na libo");
static const UFieldPosition expectedFieldPositions[] = {
// field, begin index, end index
{UNUM_INTEGER_FIELD, 0, 1},
{UNUM_COMPACT_FIELD, 2, 9}};
assertFieldPositions(
message,
result,
expectedFieldPositions,
sizeof(expectedFieldPositions)/sizeof(*expectedFieldPositions));
}
{
const char16_t* message = u"Compact field with bidi mark";
FormattedNumber result = assertFormatSingle(
message,
u"compact-long",
NumberFormatter::with().notation(Notation::compactLong()),
"he", // locale with interesting data
6000,
u"\u200F6 אלף");
static const UFieldPosition expectedFieldPositions[] = {
// field, begin index, end index
{UNUM_INTEGER_FIELD, 1, 2},
{UNUM_COMPACT_FIELD, 3, 6}};
assertFieldPositions(
message,
result,
expectedFieldPositions,
sizeof(expectedFieldPositions)/sizeof(*expectedFieldPositions));
}
{
const char16_t* message = u"Compact with currency fields";
FormattedNumber result = assertFormatSingle(
message,
u"compact-short currency/USD",
NumberFormatter::with().notation(Notation::compactShort()).unit(USD),
"sr_Latn", // locale with interesting data
65000,
u"65 hilj. US$");
static const UFieldPosition expectedFieldPositions[] = {
// field, begin index, end index
{UNUM_INTEGER_FIELD, 0, 2},
{UNUM_COMPACT_FIELD, 3, 8},
{UNUM_CURRENCY_FIELD, 9, 12}};
assertFieldPositions(
message,
result,
expectedFieldPositions,
sizeof(expectedFieldPositions)/sizeof(*expectedFieldPositions));
}
{
const char16_t* message = u"Compact with measure unit fields";
FormattedNumber result = assertFormatSingle(
message,
u"compact-long measure-unit/length-meter unit-width-full-name",
NumberFormatter::with().notation(Notation::compactLong())
.unit(METER)
.unitWidth(UNUM_UNIT_WIDTH_FULL_NAME),
Locale::getUS(),
65000,
u"65 thousand meters");
static const UFieldPosition expectedFieldPositions[] = {
// field, begin index, end index
{UNUM_INTEGER_FIELD, 0, 2},
{UNUM_COMPACT_FIELD, 3, 11},
{UNUM_MEASURE_UNIT_FIELD, 12, 18}};
assertFieldPositions(
message,
result,
expectedFieldPositions,
sizeof(expectedFieldPositions)/sizeof(*expectedFieldPositions));
}
}
void NumberFormatterApiTest::toFormat() {

View file

@ -26,7 +26,7 @@ void PatternModifierTest::testBasic() {
ParsedPatternInfo patternInfo;
PatternParser::parseToPatternInfo(u"a0b", patternInfo, status);
assertSuccess("Spot 1", status);
mod.setPatternInfo(&patternInfo);
mod.setPatternInfo(&patternInfo, UNUM_FIELD_COUNT);
mod.setPatternAttributes(UNUM_SIGN_AUTO, false);
DecimalFormatSymbols symbols(Locale::getEnglish(), status);
CurrencySymbols currencySymbols({u"USD", status}, "en", status);
@ -58,7 +58,7 @@ void PatternModifierTest::testBasic() {
ParsedPatternInfo patternInfo2;
PatternParser::parseToPatternInfo(u"a0b;c-0d", patternInfo2, status);
assertSuccess("Spot 4", status);
mod.setPatternInfo(&patternInfo2);
mod.setPatternInfo(&patternInfo2, UNUM_FIELD_COUNT);
mod.setPatternAttributes(UNUM_SIGN_AUTO, false);
mod.setNumberProperties(1, StandardPlural::Form::COUNT);
assertEquals("Pattern a0b;c-0d", u"a", getPrefix(mod, status));
@ -88,7 +88,7 @@ void PatternModifierTest::testPatternWithNoPlaceholder() {
ParsedPatternInfo patternInfo;
PatternParser::parseToPatternInfo(u"abc", patternInfo, status);
assertSuccess("Spot 1", status);
mod.setPatternInfo(&patternInfo);
mod.setPatternInfo(&patternInfo, UNUM_FIELD_COUNT);
mod.setPatternAttributes(UNUM_SIGN_AUTO, false);
DecimalFormatSymbols symbols(Locale::getEnglish(), status);
CurrencySymbols currencySymbols({u"USD", status}, "en", status);
@ -131,7 +131,7 @@ void PatternModifierTest::testMutableEqualsImmutable() {
ParsedPatternInfo patternInfo;
PatternParser::parseToPatternInfo("a0b;c-0d", patternInfo, status);
assertSuccess("Spot 1", status);
mod.setPatternInfo(&patternInfo);
mod.setPatternInfo(&patternInfo, UNUM_FIELD_COUNT);
mod.setPatternAttributes(UNUM_SIGN_AUTO, false);
DecimalFormatSymbols symbols(Locale::getEnglish(), status);
CurrencySymbols currencySymbols({u"USD", status}, "en", status);

View file

@ -309,7 +309,8 @@ public class AffixUtils {
CharSequence affixPattern,
NumberStringBuilder output,
int position,
SymbolProvider provider) {
SymbolProvider provider,
NumberFormat.Field field) {
assert affixPattern != null;
int length = 0;
long tag = 0L;
@ -324,7 +325,7 @@ public class AffixUtils {
provider.getSymbol(typeOrCp),
getFieldForType(typeOrCp));
} else {
length += output.insertCodePoint(position + length, typeOrCp, null);
length += output.insertCodePoint(position + length, typeOrCp, field);
}
}
return length;

View file

@ -38,6 +38,7 @@ public class MutablePatternModifier implements Modifier, SymbolProvider, MicroPr
// Pattern details
AffixPatternProvider patternInfo;
Field field;
SignDisplay signDisplay;
boolean perMilleReplacesPercent;
@ -71,9 +72,13 @@ public class MutablePatternModifier implements Modifier, SymbolProvider, MicroPr
* Sets a reference to the parsed decimal format pattern, usually obtained from
* {@link PatternStringParser#parseToPatternInfo(String)}, but any implementation of
* {@link AffixPatternProvider} is accepted.
*
* @param field
* Which field to use for literal characters in the pattern.
*/
public void setPatternInfo(AffixPatternProvider patternInfo) {
public void setPatternInfo(AffixPatternProvider patternInfo, Field field) {
this.patternInfo = patternInfo;
this.field = field;
}
/**
@ -343,13 +348,13 @@ public class MutablePatternModifier implements Modifier, SymbolProvider, MicroPr
private int insertPrefix(NumberStringBuilder sb, int position) {
prepareAffix(true);
int length = AffixUtils.unescape(currentAffix, sb, position, this);
int length = AffixUtils.unescape(currentAffix, sb, position, this, field);
return length;
}
private int insertSuffix(NumberStringBuilder sb, int position) {
prepareAffix(false);
int length = AffixUtils.unescape(currentAffix, sb, position, this);
int length = AffixUtils.unescape(currentAffix, sb, position, this, field);
return length;
}

View file

@ -19,6 +19,7 @@ import com.ibm.icu.impl.number.MutablePatternModifier.ImmutablePatternModifier;
import com.ibm.icu.impl.number.PatternStringParser;
import com.ibm.icu.impl.number.PatternStringParser.ParsedPatternInfo;
import com.ibm.icu.text.CompactDecimalFormat.CompactStyle;
import com.ibm.icu.text.NumberFormat;
import com.ibm.icu.text.PluralRules;
import com.ibm.icu.util.ULocale;
@ -96,7 +97,7 @@ public class CompactNotation extends Notation {
}
if (buildReference != null) {
// Safe code path
precomputedMods = new HashMap<String, ImmutablePatternModifier>();
precomputedMods = new HashMap<>();
precomputeAllModifiers(buildReference);
} else {
// Unsafe code path
@ -106,12 +107,12 @@ public class CompactNotation extends Notation {
/** Used by the safe code path */
private void precomputeAllModifiers(MutablePatternModifier buildReference) {
Set<String> allPatterns = new HashSet<String>();
Set<String> allPatterns = new HashSet<>();
data.getUniquePatterns(allPatterns);
for (String patternString : allPatterns) {
ParsedPatternInfo patternInfo = PatternStringParser.parseToPatternInfo(patternString);
buildReference.setPatternInfo(patternInfo);
buildReference.setPatternInfo(patternInfo, NumberFormat.Field.COMPACT);
precomputedMods.put(patternString, buildReference.createImmutable());
}
}
@ -148,7 +149,7 @@ public class CompactNotation extends Notation {
// Overwrite the PatternInfo in the existing modMiddle.
assert micros.modMiddle instanceof MutablePatternModifier;
ParsedPatternInfo patternInfo = PatternStringParser.parseToPatternInfo(patternString);
((MutablePatternModifier) micros.modMiddle).setPatternInfo(patternInfo);
((MutablePatternModifier) micros.modMiddle).setPatternInfo(patternInfo, NumberFormat.Field.COMPACT);
}
// We already performed rounding. Do not perform it again.

View file

@ -322,7 +322,7 @@ class NumberFormatterImpl {
// Middle modifier (patterns, positive/negative, currency symbols, percent)
// The default middle modifier is weak (thus the false argument).
MutablePatternModifier patternMod = new MutablePatternModifier(false);
patternMod.setPatternInfo((macros.affixProvider != null) ? macros.affixProvider : patternInfo);
patternMod.setPatternInfo((macros.affixProvider != null) ? macros.affixProvider : patternInfo, null);
patternMod.setPatternAttributes(micros.sign, isPermille);
if (patternMod.needsPlurals()) {
if (rules == null) {

View file

@ -1966,6 +1966,11 @@ public abstract class NumberFormat extends UFormat {
*/
public static final Field MEASURE_UNIT = new Field("measure unit");
/**
* @draft ICU 64
*/
public static final Field COMPACT = new Field("compact");
/**
* Constructs a new instance of NumberFormat.Field with the given field
* name.

View file

@ -204,14 +204,14 @@ public class AffixUtilsTest {
String input = cas[0];
String expected = cas[1];
sb.clear();
AffixUtils.unescape(input, sb, 0, provider);
AffixUtils.unescape(input, sb, 0, provider, null);
assertEquals("With symbol provider on <" + input + ">", expected, sb.toString());
}
// Test insertion position
sb.clear();
sb.append("abcdefg", null);
AffixUtils.unescape("-+%", sb, 4, provider);
AffixUtils.unescape("-+%", sb, 4, provider, null);
assertEquals("Symbol provider into middle", "abcd123efg", sb.toString());
}
@ -237,7 +237,7 @@ public class AffixUtilsTest {
private static String unescapeWithDefaults(String input) {
NumberStringBuilder nsb = new NumberStringBuilder();
int length = AffixUtils.unescape(input, nsb, 0, DEFAULT_SYMBOL_PROVIDER);
int length = AffixUtils.unescape(input, nsb, 0, DEFAULT_SYMBOL_PROVIDER, null);
assertEquals("Return value of unescape", nsb.length(), length);
return nsb.toString();
}

View file

@ -25,7 +25,7 @@ public class MutablePatternModifierTest {
@Test
public void basic() {
MutablePatternModifier mod = new MutablePatternModifier(false);
mod.setPatternInfo(PatternStringParser.parseToPatternInfo("a0b"));
mod.setPatternInfo(PatternStringParser.parseToPatternInfo("a0b"), null);
mod.setPatternAttributes(SignDisplay.AUTO, false);
mod.setSymbols(DecimalFormatSymbols.getInstance(ULocale.ENGLISH),
Currency.getInstance("USD"),
@ -51,7 +51,7 @@ public class MutablePatternModifierTest {
assertEquals("a", getPrefix(mod));
assertEquals("b", getSuffix(mod));
mod.setPatternInfo(PatternStringParser.parseToPatternInfo("a0b;c-0d"));
mod.setPatternInfo(PatternStringParser.parseToPatternInfo("a0b;c-0d"), null);
mod.setPatternAttributes(SignDisplay.AUTO, false);
mod.setNumberProperties(1, null);
assertEquals("a", getPrefix(mod));
@ -76,7 +76,7 @@ public class MutablePatternModifierTest {
@Test
public void mutableEqualsImmutable() {
MutablePatternModifier mod = new MutablePatternModifier(false);
mod.setPatternInfo(PatternStringParser.parseToPatternInfo("a0b;c-0d"));
mod.setPatternInfo(PatternStringParser.parseToPatternInfo("a0b;c-0d"), null);
mod.setPatternAttributes(SignDisplay.AUTO, false);
mod.setSymbols(DecimalFormatSymbols.getInstance(ULocale.ENGLISH), null, UnitWidth.SHORT, null);
DecimalQuantity fq = new DecimalQuantity_DualStorageBCD(1);
@ -106,7 +106,7 @@ public class MutablePatternModifierTest {
@Test
public void patternWithNoPlaceholder() {
MutablePatternModifier mod = new MutablePatternModifier(false);
mod.setPatternInfo(PatternStringParser.parseToPatternInfo("abc"));
mod.setPatternInfo(PatternStringParser.parseToPatternInfo("abc"), null);
mod.setPatternAttributes(SignDisplay.AUTO, false);
mod.setSymbols(DecimalFormatSymbols.getInstance(ULocale.ENGLISH),
Currency.getInstance("USD"),

View file

@ -2317,6 +2317,124 @@ public class NumberFormatterApiTest {
result,
expectedFieldPositions);
}
{
String message = "Compact field basic";
FormattedNumber result = assertFormatSingle(
message,
"compact-short",
NumberFormatter.with().notation(Notation.compactShort()),
ULocale.US,
65000,
"65K");
Object[][] expectedFieldPositions = new Object[][] {
// field, begin index, end index
{NumberFormat.Field.INTEGER, 0, 2},
{NumberFormat.Field.COMPACT, 2, 3}};
assertFieldPositions(
message,
result,
expectedFieldPositions);
}
{
String message = "Compact field with spaces";
FormattedNumber result = assertFormatSingle(
message,
"compact-long",
NumberFormatter.with().notation(Notation.compactLong()),
ULocale.US,
65000,
"65 thousand");
Object[][] expectedFieldPositions = new Object[][] {
// field, begin index, end index
{NumberFormat.Field.INTEGER, 0, 2},
{NumberFormat.Field.COMPACT, 3, 11}};
assertFieldPositions(
message,
result,
expectedFieldPositions);
}
{
String message = "Compact field with inner space";
FormattedNumber result = assertFormatSingle(
message,
"compact-long",
NumberFormatter.with().notation(Notation.compactLong()),
new ULocale("fil"), // locale with interesting data
6000,
"6 na libo");
Object[][] expectedFieldPositions = new Object[][] {
// field, begin index, end index
{NumberFormat.Field.INTEGER, 0, 1},
{NumberFormat.Field.COMPACT, 2, 9}};
assertFieldPositions(
message,
result,
expectedFieldPositions);
}
{
String message = "Compact field with bidi mark";
FormattedNumber result = assertFormatSingle(
message,
"compact-long",
NumberFormatter.with().notation(Notation.compactLong()),
new ULocale("he"), // locale with interesting data
6000,
"\u200F6 אלף");
Object[][] expectedFieldPositions = new Object[][] {
// field, begin index, end index
{NumberFormat.Field.INTEGER, 1, 2},
{NumberFormat.Field.COMPACT, 3, 6}};
assertFieldPositions(
message,
result,
expectedFieldPositions);
}
{
String message = "Compact with currency fields";
FormattedNumber result = assertFormatSingle(
message,
"compact-short currency/USD",
NumberFormatter.with().notation(Notation.compactShort()).unit(USD),
new ULocale("sr_Latn"), // locale with interesting data
65000,
"65 hilj. US$");
Object[][] expectedFieldPositions = new Object[][] {
// field, begin index, end index
{NumberFormat.Field.INTEGER, 0, 2},
{NumberFormat.Field.COMPACT, 3, 8},
{NumberFormat.Field.CURRENCY, 9, 12}};
assertFieldPositions(
message,
result,
expectedFieldPositions);
}
{
String message = "Compact with measure unit fields";
FormattedNumber result = assertFormatSingle(
message,
"compact-long measure-unit/length-meter unit-width-full-name",
NumberFormatter.with().notation(Notation.compactLong())
.unit(MeasureUnit.METER)
.unitWidth(UnitWidth.FULL_NAME),
ULocale.US,
65000,
"65 thousand meters");
Object[][] expectedFieldPositions = new Object[][] {
// field, begin index, end index
{NumberFormat.Field.INTEGER, 0, 2},
{NumberFormat.Field.COMPACT, 3, 11},
{NumberFormat.Field.MEASURE_UNIT, 12, 18}};
assertFieldPositions(
message,
result,
expectedFieldPositions);
}
}
/** Handler for serialization compatibility test suite. */