package com.oracle.truffle.js.nodes.intl;
import java.util.MissingResourceException;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.profiles.BranchProfile;
import com.oracle.truffle.js.nodes.JavaScriptBaseNode;
import com.oracle.truffle.js.runtime.Errors;
import com.oracle.truffle.js.runtime.JSContext;
import com.oracle.truffle.js.runtime.builtins.intl.JSNumberFormat;
import com.oracle.truffle.js.runtime.util.IntlUtil;
public abstract class InitializeNumberFormatNode extends JavaScriptBaseNode {
private final JSContext context;
@Child JSToCanonicalizedLocaleListNode toCanonicalizedLocaleListNode;
@Child CreateOptionsObjectNode createOptionsNode;
@Child GetStringOptionNode getLocaleMatcherOption;
@Child GetStringOptionNode getNumberingSystemOption;
@Child SetNumberFormatDigitOptionsNode setNumberFormatDigitOptions;
@Child GetStringOptionNode getStyleOption;
@Child GetStringOptionNode getCurrencyOption;
@Child GetStringOptionNode getCurrencyDisplayOption;
@Child GetStringOptionNode getCurrencySignOption;
@Child GetStringOptionNode getUnitOption;
@Child GetStringOptionNode getUnitDisplayOption;
@Child GetStringOptionNode getNotationOption;
@Child GetStringOptionNode getCompactDisplayOption;
@Child GetBooleanOptionNode getUseGroupingOption;
@Child GetStringOptionNode getSignDisplayOption;
private final BranchProfile errorBranch = BranchProfile.create();
protected InitializeNumberFormatNode(JSContext context) {
this.context = context;
this.toCanonicalizedLocaleListNode = JSToCanonicalizedLocaleListNode.create(context);
this.createOptionsNode = CreateOptionsObjectNodeGen.create(context);
this.getLocaleMatcherOption = GetStringOptionNode.create(context, IntlUtil.LOCALE_MATCHER,
new String[]{IntlUtil.LOOKUP, IntlUtil.BEST_FIT}, IntlUtil.BEST_FIT);
this.getNumberingSystemOption = GetStringOptionNode.create(context, IntlUtil.NUMBERING_SYSTEM, null, null);
this.getStyleOption = GetStringOptionNode.create(context, IntlUtil.STYLE, new String[]{IntlUtil.DECIMAL, IntlUtil.PERCENT, IntlUtil.CURRENCY, IntlUtil.UNIT}, IntlUtil.DECIMAL);
this.getCurrencyOption = GetStringOptionNode.create(context, IntlUtil.CURRENCY, null, null);
this.getCurrencyDisplayOption = GetStringOptionNode.create(context, IntlUtil.CURRENCY_DISPLAY, new String[]{IntlUtil.CODE, IntlUtil.SYMBOL, IntlUtil.NARROW_SYMBOL, IntlUtil.NAME},
IntlUtil.SYMBOL);
this.getCurrencySignOption = GetStringOptionNode.create(context, IntlUtil.CURRENCY_SIGN, new String[]{IntlUtil.STANDARD, IntlUtil.ACCOUNTING}, IntlUtil.STANDARD);
this.getUnitOption = GetStringOptionNode.create(context, IntlUtil.UNIT, null, null);
this.getUnitDisplayOption = GetStringOptionNode.create(context, IntlUtil.UNIT_DISPLAY, new String[]{IntlUtil.SHORT, IntlUtil.NARROW, IntlUtil.LONG}, IntlUtil.SHORT);
this.getNotationOption = GetStringOptionNode.create(context, IntlUtil.NOTATION, new String[]{IntlUtil.STANDARD, IntlUtil.SCIENTIFIC, IntlUtil.ENGINEERING, IntlUtil.COMPACT},
IntlUtil.STANDARD);
this.getCompactDisplayOption = GetStringOptionNode.create(context, IntlUtil.COMPACT_DISPLAY, new String[]{IntlUtil.SHORT, IntlUtil.LONG}, IntlUtil.SHORT);
this.getUseGroupingOption = GetBooleanOptionNode.create(context, IntlUtil.USE_GROUPING, true);
this.getSignDisplayOption = GetStringOptionNode.create(context, IntlUtil.SIGN_DISPLAY, new String[]{IntlUtil.AUTO, IntlUtil.NEVER, IntlUtil.ALWAYS, IntlUtil.EXCEPT_ZERO}, IntlUtil.AUTO);
this.setNumberFormatDigitOptions = SetNumberFormatDigitOptionsNode.create(context);
}
public abstract DynamicObject executeInit(DynamicObject collator, Object locales, Object options);
public static InitializeNumberFormatNode createInitalizeNumberFormatNode(JSContext context) {
return InitializeNumberFormatNodeGen.create(context);
}
@Specialization
public DynamicObject initializeNumberFormat(DynamicObject numberFormatObj, Object localesArg, Object optionsArg) {
try {
JSNumberFormat.InternalState state = JSNumberFormat.getInternalState(numberFormatObj);
String[] locales = toCanonicalizedLocaleListNode.executeLanguageTags(localesArg);
DynamicObject options = createOptionsNode.execute(optionsArg);
getLocaleMatcherOption.executeValue(options);
String numberingSystem = getNumberingSystemOption.executeValue(options);
if (numberingSystem != null) {
IntlUtil.validateUnicodeLocaleIdentifierType(numberingSystem, errorBranch);
numberingSystem = IntlUtil.normalizeUnicodeLocaleIdentifierType(numberingSystem);
}
state.resolveLocaleAndNumberingSystem(context, locales, numberingSystem);
setNumberFormatUnitOptions(state, options);
int mnfdDefault;
int mxfdDefault;
String style = state.getStyle();
if (IntlUtil.CURRENCY.equals(style)) {
int cDigits = JSNumberFormat.currencyDigits(state.getCurrency());
mnfdDefault = cDigits;
mxfdDefault = cDigits;
} else {
mnfdDefault = 0;
mxfdDefault = IntlUtil.PERCENT.equals(style) ? 0 : 3;
}
String notation = getNotationOption.executeValue(options);
state.setNotation(notation);
boolean compactNotation = IntlUtil.COMPACT.equals(notation);
setNumberFormatDigitOptions.execute(state, options, mnfdDefault, mxfdDefault, compactNotation);
String compactDisplay = getCompactDisplayOption.executeValue(options);
if (compactNotation) {
state.setCompactDisplay(compactDisplay);
}
boolean useGrouping = getUseGroupingOption.executeValue(options);
state.setGroupingUsed(useGrouping);
String signDisplay = getSignDisplayOption.executeValue(options);
state.setSignDisplay(signDisplay);
state.initializeNumberFormatter();
} catch (MissingResourceException e) {
errorBranch.enter();
throw Errors.createICU4JDataError(e);
}
return numberFormatObj;
}
private void setNumberFormatUnitOptions(JSNumberFormat.InternalState state, DynamicObject options) {
String style = getStyleOption.executeValue(options);
state.setStyle(style);
boolean styleIsCurrency = IntlUtil.CURRENCY.equals(style);
boolean styleIsUnit = IntlUtil.UNIT.equals(style);
String currency = getCurrencyOption.executeValue(options);
if (currency == null) {
if (styleIsCurrency) {
errorBranch.enter();
throw Errors.createTypeError("Currency can not be undefined when style is \"currency\".");
}
} else {
IntlUtil.ensureIsWellFormedCurrencyCode(currency);
}
String currencyDisplay = getCurrencyDisplayOption.executeValue(options);
String currencySign = getCurrencySignOption.executeValue(options);
String unit = getUnitOption.executeValue(options);
if (unit == null) {
if (styleIsUnit) {
errorBranch.enter();
throw Errors.createTypeError("Unit can not be undefined when style is \"unit\".");
}
} else {
IntlUtil.ensureIsWellFormedUnitIdentifier(unit);
}
String unitDisplay = getUnitDisplayOption.executeValue(options);
if (styleIsCurrency) {
currency = IntlUtil.toUpperCase(currency);
state.setCurrency(currency);
state.setCurrencyDisplay(currencyDisplay);
state.setCurrencySign(currencySign);
} else if (styleIsUnit) {
state.setUnit(unit);
state.setUnitDisplay(unitDisplay);
}
}
}