blob: f10cc180a3cdb8b000b66f84b566da3ea63e8864 [file] [log] [blame]
/* GENERATED SOURCE. DO NOT MODIFY. */
// © 2022 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
package android.icu.message2;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import android.icu.math.BigDecimal;
import android.icu.number.LocalizedNumberFormatter;
import android.icu.number.NumberFormatter;
import android.icu.number.Precision;
import android.icu.number.UnlocalizedNumberFormatter;
import android.icu.text.FormattedValue;
import android.icu.util.CurrencyAmount;
/**
* Creates a {@link Formatter} doing numeric formatting, similar to <code>{exp, number}</code>
* in {@link android.icu.text.MessageFormat}.
*/
class NumberFormatterFactory implements FormatterFactory {
/**
* {@inheritDoc}
*/
@Override
public Formatter createFormatter(Locale locale, Map<String, Object> fixedOptions) {
return new NumberFormatterImpl(locale, fixedOptions);
}
static class NumberFormatterImpl implements Formatter {
private final Locale locale;
private final Map<String, Object> fixedOptions;
private final LocalizedNumberFormatter icuFormatter;
final boolean advanced;
private static LocalizedNumberFormatter formatterForOptions(Locale locale, Map<String, Object> fixedOptions) {
UnlocalizedNumberFormatter nf;
String skeleton = OptUtils.getString(fixedOptions, "skeleton");
if (skeleton != null) {
nf = NumberFormatter.forSkeleton(skeleton);
} else {
nf = NumberFormatter.with();
Integer minFractionDigits = OptUtils.getInteger(fixedOptions, "minimumFractionDigits");
if (minFractionDigits != null) {
nf = nf.precision(Precision.minFraction(minFractionDigits));
}
}
return nf.locale(locale);
}
NumberFormatterImpl(Locale locale, Map<String, Object> fixedOptions) {
this.locale = locale;
this.fixedOptions = new HashMap<>(fixedOptions);
String skeleton = OptUtils.getString(fixedOptions, "skeleton");
boolean fancy = skeleton != null;
this.icuFormatter = formatterForOptions(locale, fixedOptions);
this.advanced = fancy;
}
LocalizedNumberFormatter getIcuFormatter() {
return icuFormatter;
}
/**
* {@inheritDoc}
*/
@Override
public String formatToString(Object toFormat, Map<String, Object> variableOptions) {
return format(toFormat, variableOptions).toString();
}
/**
* {@inheritDoc}
*/
@Override
public FormattedPlaceholder format(Object toFormat, Map<String, Object> variableOptions) {
LocalizedNumberFormatter realFormatter;
if (variableOptions.isEmpty()) {
realFormatter = this.icuFormatter;
} else {
Map<String, Object> mergedOptions = new HashMap<>(fixedOptions);
mergedOptions.putAll(variableOptions);
// This is really wasteful, as we don't use the existing
// formatter if even one option is variable.
// We can optimize, but for now will have to do.
realFormatter = formatterForOptions(locale, mergedOptions);
}
Integer offset = OptUtils.getInteger(variableOptions, "offset");
if (offset == null && fixedOptions != null) {
offset = OptUtils.getInteger(fixedOptions, "offset");
}
if (offset == null) {
offset = 0;
}
FormattedValue result = null;
if (toFormat == null) {
// This is also what MessageFormat does.
throw new NullPointerException("Argument to format can't be null");
} else if (toFormat instanceof Double) {
result = realFormatter.format((double) toFormat - offset);
} else if (toFormat instanceof Long) {
result = realFormatter.format((long) toFormat - offset);
} else if (toFormat instanceof Integer) {
result = realFormatter.format((int) toFormat - offset);
} else if (toFormat instanceof BigDecimal) {
BigDecimal bd = (BigDecimal) toFormat;
result = realFormatter.format(bd.subtract(BigDecimal.valueOf(offset)));
} else if (toFormat instanceof Number) {
result = realFormatter.format(((Number) toFormat).doubleValue() - offset);
} else if (toFormat instanceof CurrencyAmount) {
result = realFormatter.format((CurrencyAmount) toFormat);
} else {
// The behavior is not in the spec, will be in the registry.
// We can return "NaN", or try to parse the string as a number
String strValue = Objects.toString(toFormat);
Number nrValue = OptUtils.asNumber(strValue);
if (nrValue != null) {
result = realFormatter.format(nrValue.doubleValue() - offset);
} else {
result = new PlainStringFormattedValue("NaN");
}
}
return new FormattedPlaceholder(toFormat, result);
}
}
}