ICU-11276 Adding placeholder implementation and more API functions.

This commit is contained in:
Shane Carr 2018-08-28 20:34:41 -07:00
parent 553f22585d
commit 37a40b31ed
No known key found for this signature in database
GPG Key ID: FCED3B24AAB18B5C
5 changed files with 250 additions and 14 deletions

View File

@ -4,9 +4,9 @@ package com.ibm.icu.impl.number.range;
import java.util.Objects;
import com.ibm.icu.number.NumberFormatterSettings;
import com.ibm.icu.number.NumberRangeFormatter.RangeCollapse;
import com.ibm.icu.number.NumberRangeFormatter.RangeIdentityFallback;
import com.ibm.icu.number.UnlocalizedNumberFormatter;
import com.ibm.icu.util.ULocale;
/**
@ -14,8 +14,8 @@ import com.ibm.icu.util.ULocale;
*
*/
public class RangeMacroProps {
public NumberFormatterSettings<?> formatter1;
public NumberFormatterSettings<?> formatter2;
public UnlocalizedNumberFormatter formatter1;
public UnlocalizedNumberFormatter formatter2;
public RangeCollapse collapse;
public RangeIdentityFallback identityFallback;
public ULocale loc;

View File

@ -5,8 +5,8 @@ package com.ibm.icu.number;
import com.ibm.icu.impl.number.DecimalQuantity;
import com.ibm.icu.impl.number.DecimalQuantity_DualStorageBCD;
import com.ibm.icu.impl.number.NumberStringBuilder;
import com.ibm.icu.impl.number.range.RangeMacroProps;
import com.ibm.icu.number.FormattedNumberRange.RangeIdentityType;
import com.ibm.icu.text.NumberFormat;
/**
* A NumberRangeFormatter that has a locale associated with it; this means .formatRange() methods are available.
@ -36,16 +36,72 @@ public class LocalizedNumberRangeFormatter extends NumberRangeFormatterSettings<
* @see NumberRangeFormatter
*/
public FormattedNumberRange formatRange(int first, int second) {
// TODO: This is a placeholder implementation.
DecimalQuantity dq1 = new DecimalQuantity_DualStorageBCD(first);
DecimalQuantity dq2 = new DecimalQuantity_DualStorageBCD(second);
return formatImpl(dq1, dq2);
}
/**
* Format the given doubles to a string using the settings specified in the NumberRangeFormatter fluent setting
* chain.
*
* @param first
* The first number in the range, usually to the left in LTR locales.
* @param second
* The second number in the range, usually to the right in LTR locales.
* @return A FormattedNumber object; call .toString() to get the string.
* @draft ICU 63
* @provisional This API might change or be removed in a future release.
* @see NumberRangeFormatter
*/
public FormattedNumberRange formatRange(double first, double second) {
DecimalQuantity dq1 = new DecimalQuantity_DualStorageBCD(first);
DecimalQuantity dq2 = new DecimalQuantity_DualStorageBCD(second);
return formatImpl(dq1, dq2);
}
/**
* Format the given Numbers to a string using the settings specified in the NumberRangeFormatter fluent setting
* chain.
*
* @param first
* The first number in the range, usually to the left in LTR locales.
* @param second
* The second number in the range, usually to the right in LTR locales.
* @return A FormattedNumber object; call .toString() to get the string.
* @draft ICU 63
* @provisional This API might change or be removed in a future release.
* @see NumberRangeFormatter
*/
public FormattedNumberRange formatRange(Number first, Number second) {
DecimalQuantity dq1 = new DecimalQuantity_DualStorageBCD(first);
DecimalQuantity dq2 = new DecimalQuantity_DualStorageBCD(second);
return formatImpl(dq1, dq2);
}
FormattedNumberRange formatImpl(DecimalQuantity first, DecimalQuantity second) {
// TODO: This is a placeholder implementation.
RangeMacroProps macros = resolve();
LocalizedNumberFormatter f1 , f2;
if (macros.formatter1 != null) {
f1 = macros.formatter1.locale(macros.loc);
} else {
f1 = NumberFormatter.withLocale(macros.loc);
}
if (macros.formatter2 != null) {
f2 = macros.formatter2.locale(macros.loc);
} else {
f2 = NumberFormatter.withLocale(macros.loc);
}
FormattedNumber r1 = f1.format(first);
FormattedNumber r2 = f2.format(second);
NumberStringBuilder nsb = new NumberStringBuilder();
nsb.append(dq1.toPlainString(), NumberFormat.Field.INTEGER);
nsb.append(r1.nsb);
nsb.append(" --- ", null);
nsb.append(dq2.toPlainString(), NumberFormat.Field.INTEGER);
nsb.append(r2.nsb);
RangeIdentityType identityType = (first == second) ? RangeIdentityType.EQUAL_BEFORE_ROUNDING
: RangeIdentityType.NOT_EQUAL;
return new FormattedNumberRange(nsb, dq1, dq2, identityType);
return new FormattedNumberRange(nsb, first, second, identityType);
}
@Override

View File

@ -2,6 +2,10 @@
// License & terms of use: http://www.unicode.org/copyright.html#License
package com.ibm.icu.number;
import java.util.Locale;
import com.ibm.icu.util.ULocale;
/**
* The main entrypoint to the formatting of ranges of numbers, including currencies and other units of measurement.
*
@ -16,4 +20,18 @@ public abstract class NumberRangeFormatter {
public static enum RangeIdentityFallback {}
private static final UnlocalizedNumberRangeFormatter BASE = new UnlocalizedNumberRangeFormatter();
public static UnlocalizedNumberRangeFormatter with() {
return BASE;
}
public static LocalizedNumberRangeFormatter withLocale(Locale locale) {
return BASE.locale(locale);
}
public static LocalizedNumberRangeFormatter withLocale(ULocale locale) {
return BASE.locale(locale);
}
}

View File

@ -38,11 +38,11 @@ public abstract class NumberRangeFormatterSettings<T extends NumberRangeFormatte
this.value = value;
}
public T numberFormatter(NumberFormatterSettings<?> formatter) {
public T numberFormatter(UnlocalizedNumberFormatter formatter) {
return numberFormatters(formatter, formatter);
}
public T numberFormatters(NumberFormatterSettings<?> formatterFirst, NumberFormatterSettings<?> formatterSecond) {
public T numberFormatters(UnlocalizedNumberFormatter formatterFirst, UnlocalizedNumberFormatter formatterSecond) {
T intermediate = create(KEY_FORMATTER_1, formatterFirst);
return (T) intermediate.create(KEY_FORMATTER_2, formatterSecond);
}
@ -79,12 +79,12 @@ public abstract class NumberRangeFormatterSettings<T extends NumberRangeFormatte
break;
case KEY_FORMATTER_1:
if (macros.formatter1 == null) {
macros.formatter1 = (NumberFormatterSettings<?>) current.value;
macros.formatter1 = (UnlocalizedNumberFormatter) current.value;
}
break;
case KEY_FORMATTER_2:
if (macros.formatter2 == null) {
macros.formatter2 = (NumberFormatterSettings<?>) current.value;
macros.formatter2 = (UnlocalizedNumberFormatter) current.value;
}
break;
case KEY_COLLAPSE:
@ -131,9 +131,9 @@ public abstract class NumberRangeFormatterSettings<T extends NumberRangeFormatte
if (other == null) {
return false;
}
if (!(other instanceof NumberFormatterSettings)) {
if (!(other instanceof NumberRangeFormatterSettings)) {
return false;
}
return resolve().equals(((NumberFormatterSettings<?>) other).resolve());
return resolve().equals(((NumberRangeFormatterSettings<?>) other).resolve());
}
}

View File

@ -0,0 +1,162 @@
// © 2018 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html#License
package com.ibm.icu.dev.test.number;
import static org.junit.Assert.assertEquals;
import java.util.Locale;
import org.junit.Test;
import com.ibm.icu.number.LocalizedNumberRangeFormatter;
import com.ibm.icu.number.NumberFormatter;
import com.ibm.icu.number.NumberFormatter.GroupingStrategy;
import com.ibm.icu.number.NumberRangeFormatter;
import com.ibm.icu.number.UnlocalizedNumberRangeFormatter;
import com.ibm.icu.util.Currency;
import com.ibm.icu.util.ULocale;
/**
* @author sffc
*
*/
public class NumberRangeFormatterTest {
private static final Currency USD = Currency.getInstance("USD");
private static final Currency GBP = Currency.getInstance("GBP");
@Test
public void testSanity() {
LocalizedNumberRangeFormatter lnrf1 = NumberRangeFormatter.withLocale(ULocale.US);
LocalizedNumberRangeFormatter lnrf2 = NumberRangeFormatter.with().locale(ULocale.US);
LocalizedNumberRangeFormatter lnrf3 = NumberRangeFormatter.withLocale(Locale.US);
LocalizedNumberRangeFormatter lnrf4 = NumberRangeFormatter.with().locale(Locale.US);
assertEquals("Formatters should be equal 1", lnrf1, lnrf2);
assertEquals("Formatters should be equal 2", lnrf2, lnrf3);
assertEquals("Formatters should be equal 3", lnrf3, lnrf4);
assertEquals("Formatters should have same behavior 1", lnrf1.formatRange(4, 6), lnrf2.formatRange(4, 6));
assertEquals("Formatters should have same behavior 2", lnrf2.formatRange(4, 6), lnrf3.formatRange(4, 6));
assertEquals("Formatters should have same behavior 3", lnrf3.formatRange(4, 6), lnrf4.formatRange(4, 6));
}
@Test
public void testBasic() {
assertFormatRange(
"Basic",
NumberRangeFormatter.with(),
ULocale.US,
"1 --- 5",
"5 --- 5",
"5 --- 5",
"0 --- 3",
"0 --- 0",
"3 --- 3,000",
"3,000 --- 5,000",
"4,999 --- 5,001",
"5,000 --- 5,000",
"5,000 --- 5,000,000");
}
@Test
public void testNullBehavior() {
assertFormatRange(
"Basic",
NumberRangeFormatter.with().numberFormatter(null),
ULocale.US,
"1 --- 5",
"5 --- 5",
"5 --- 5",
"0 --- 3",
"0 --- 0",
"3 --- 3,000",
"3,000 --- 5,000",
"4,999 --- 5,001",
"5,000 --- 5,000",
"5,000 --- 5,000,000");
assertFormatRange(
"Basic",
NumberRangeFormatter.with().numberFormatters(null, null),
ULocale.US,
"1 --- 5",
"5 --- 5",
"5 --- 5",
"0 --- 3",
"0 --- 0",
"3 --- 3,000",
"3,000 --- 5,000",
"4,999 --- 5,001",
"5,000 --- 5,000",
"5,000 --- 5,000,000");
assertFormatRange(
"Basic",
NumberRangeFormatter.with().numberFormatters(
NumberFormatter.with().grouping(GroupingStrategy.OFF),
null
),
ULocale.US,
"1 --- 5",
"5 --- 5",
"5 --- 5",
"0 --- 3",
"0 --- 0",
"3 --- 3,000",
"3000 --- 5,000",
"4999 --- 5,001",
"5000 --- 5,000",
"5000 --- 5,000,000");
assertFormatRange(
"Basic",
NumberRangeFormatter.with().numberFormatters(
null,
NumberFormatter.with().grouping(GroupingStrategy.OFF)
),
ULocale.US,
"1 --- 5",
"5 --- 5",
"5 --- 5",
"0 --- 3",
"0 --- 0",
"3 --- 3000",
"3,000 --- 5000",
"4,999 --- 5001",
"5,000 --- 5000",
"5,000 --- 5000000");
}
static void assertFormatRange(
String message,
UnlocalizedNumberRangeFormatter f,
ULocale locale,
String expected_10_50,
String expected_49_51,
String expected_50_50,
String expected_00_30,
String expected_00_00,
String expected_30_3K,
String expected_30K_50K,
String expected_49K_51K,
String expected_50K_50K,
String expected_50K_50M) {
LocalizedNumberRangeFormatter l = f.locale(locale);
assertFormattedRangeEquals(message, l, 1, 5, expected_10_50);
assertFormattedRangeEquals(message, l, 4.9999999, 5.0000001, expected_49_51);
assertFormattedRangeEquals(message, l, 5, 5, expected_50_50);
assertFormattedRangeEquals(message, l, 0, 3, expected_00_30);
assertFormattedRangeEquals(message, l, 0, 0, expected_00_00);
assertFormattedRangeEquals(message, l, 3, 3000, expected_30_3K);
assertFormattedRangeEquals(message, l, 3000, 5000, expected_30K_50K);
assertFormattedRangeEquals(message, l, 4999, 5001, expected_49K_51K);
assertFormattedRangeEquals(message, l, 5000, 5000, expected_50K_50K);
assertFormattedRangeEquals(message, l, 5e3, 5e6, expected_50K_50M);
}
private static void assertFormattedRangeEquals(String message, LocalizedNumberRangeFormatter l, Number first,
Number second, String expected) {
String actual1 = l.formatRange(first, second).toString();
assertEquals(message + ": " + first + ", " + second, expected, actual1);
}
}