From a4905a73c08f188ee6c4f88c255ec2c5ac691c6e Mon Sep 17 00:00:00 2001 From: Shane Carr Date: Sat, 2 Sep 2017 04:53:46 +0000 Subject: [PATCH] ICU-13177 Changing more names of classes and moving code around. No behavior changes. X-SVN-Rev: 40368 --- ...AffixPatternUtils.java => AffixUtils.java} | 4 +- ...ties.java => DecimalFormatProperties.java} | 114 ++++---- ...rmatQuantity.java => DecimalQuantity.java} | 24 +- ...ty2.java => DecimalQuantity_64BitBCD.java} | 20 +- ....java => DecimalQuantity_AbstractBCD.java} | 38 +-- ...java => DecimalQuantity_ByteArrayBCD.java} | 20 +- ...va => DecimalQuantity_DualStorageBCD.java} | 30 +- ...ava => DecimalQuantity_SimpleStorage.java} | 50 ++-- .../src/com/ibm/icu/impl/number/Modifier.java | 2 +- .../src/com/ibm/icu/impl/number/Parse.java | 78 +++--- ...rnParser.java => PatternStringParser.java} | 253 ++++++++++++++++- ...ertyUtils.java => PatternStringUtils.java} | 259 +----------------- .../ibm/icu/impl/number/RoundingUtils.java | 4 +- .../ibm/icu/text/CompactDecimalFormat.java | 6 +- .../src/com/ibm/icu/text/DecimalFormat.java | 92 +++---- .../src/com/ibm/icu/text/NFSubstitution.java | 6 +- .../core/src/newapi/CompactNotation.java | 15 +- .../core/src/newapi/CurrencyRounder.java | 2 +- .../core/src/newapi/FormattedNumber.java | 6 +- .../main/classes/core/src/newapi/Grouper.java | 6 +- .../src/newapi/LocalizedNumberFormatter.java | 18 +- .../core/src/newapi/NumberFormatter.java | 15 + ...{Worker1.java => NumberFormatterImpl.java} | 44 +-- .../src/newapi/NumberFormatterSettings.java | 1 + .../core/src/newapi/NumberPropertyMapper.java | 65 ++--- .../main/classes/core/src/newapi/Rounder.java | 125 +++++++-- .../core/src/newapi/ScientificNotation.java | 4 +- .../newapi/{ => impl}/LongNameHandler.java | 13 +- .../core/src/newapi/impl/MicroProps.java | 85 +++--- .../src/newapi/impl/MicroPropsGenerator.java | 8 +- .../core/src/newapi/impl/MultiplierImpl.java | 4 +- .../{ => impl}/MutablePatternModifier.java | 56 ++-- .../test/format/CompactDecimalFormatTest.java | 4 +- .../format/NumberFormatDataDrivenTest.java | 19 +- .../icu/dev/test/format/NumberFormatTest.java | 11 +- .../test/number/AffixPatternUtilsTest.java | 44 +-- .../dev/test/number/FormatQuantityTest.java | 146 +++++----- .../dev/test/number/MurkyModifierTest.java | 8 +- .../dev/test/number/NumberFormatterTest.java | 15 +- .../dev/test/number/PatternStringTest.java | 51 ++-- .../icu/dev/test/number/PropertiesTest.java | 40 +-- 41 files changed, 964 insertions(+), 841 deletions(-) rename icu4j/main/classes/core/src/com/ibm/icu/impl/number/{AffixPatternUtils.java => AffixUtils.java} (99%) rename icu4j/main/classes/core/src/com/ibm/icu/impl/number/{Properties.java => DecimalFormatProperties.java} (91%) rename icu4j/main/classes/core/src/com/ibm/icu/impl/number/{FormatQuantity.java => DecimalQuantity.java} (88%) rename icu4j/main/classes/core/src/com/ibm/icu/impl/number/{FormatQuantity2.java => DecimalQuantity_64BitBCD.java} (86%) rename icu4j/main/classes/core/src/com/ibm/icu/impl/number/{FormatQuantityBCD.java => DecimalQuantity_AbstractBCD.java} (95%) rename icu4j/main/classes/core/src/com/ibm/icu/impl/number/{FormatQuantity3.java => DecimalQuantity_ByteArrayBCD.java} (88%) rename icu4j/main/classes/core/src/com/ibm/icu/impl/number/{FormatQuantity4.java => DecimalQuantity_DualStorageBCD.java} (91%) rename icu4j/main/classes/core/src/com/ibm/icu/impl/number/{FormatQuantity1.java => DecimalQuantity_SimpleStorage.java} (94%) rename icu4j/main/classes/core/src/com/ibm/icu/impl/number/{PatternParser.java => PatternStringParser.java} (55%) rename icu4j/main/classes/core/src/com/ibm/icu/impl/number/{PatternAndPropertyUtils.java => PatternStringUtils.java} (56%) rename icu4j/main/classes/core/src/newapi/{Worker1.java => NumberFormatterImpl.java} (88%) rename icu4j/main/classes/core/src/newapi/{ => impl}/LongNameHandler.java (92%) rename icu4j/main/classes/core/src/newapi/{ => impl}/MutablePatternModifier.java (90%) diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/AffixPatternUtils.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/AffixUtils.java similarity index 99% rename from icu4j/main/classes/core/src/com/ibm/icu/impl/number/AffixPatternUtils.java rename to icu4j/main/classes/core/src/com/ibm/icu/impl/number/AffixUtils.java index e0eef171262..e51f9efd14d 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/AffixPatternUtils.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/AffixUtils.java @@ -43,7 +43,7 @@ import com.ibm.icu.text.NumberFormat; * } * */ -public class AffixPatternUtils { +public class AffixUtils { private static final int STATE_BASE = 0; private static final int STATE_FIRST_QUOTE = 1; @@ -296,7 +296,7 @@ public class AffixPatternUtils { /** * Checks whether the given affix pattern contains at least one token of the given type, which is - * one of the constants "TYPE_" in {@link AffixPatternUtils}. + * one of the constants "TYPE_" in {@link AffixUtils}. * * @param affixPattern The affix pattern to check. * @param type The token type. diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/Properties.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalFormatProperties.java similarity index 91% rename from icu4j/main/classes/core/src/com/ibm/icu/impl/number/Properties.java rename to icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalFormatProperties.java index dc36c545d7e..2ee66346c67 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/Properties.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalFormatProperties.java @@ -25,9 +25,9 @@ import com.ibm.icu.util.Currency.CurrencyUsage; import newapi.impl.Padder.PadPosition; -public class Properties implements Cloneable, Serializable { +public class DecimalFormatProperties implements Cloneable, Serializable { - private static final Properties DEFAULT = new Properties(); + private static final DecimalFormatProperties DEFAULT = new DecimalFormatProperties(); /** Auto-generated. */ private static final long serialVersionUID = 4095518955889349243L; @@ -98,7 +98,7 @@ public class Properties implements Cloneable, Serializable { /| or #equals(), but it will NOT catch if you forget to add it to #hashCode(). |/ /+--------------------------------------------------------------------------------------------*/ - public Properties() { + public DecimalFormatProperties() { clear(); } @@ -114,7 +114,7 @@ public class Properties implements Cloneable, Serializable { * * @return The property bag, for chaining. */ - private Properties _clear() { + private DecimalFormatProperties _clear() { compactCustomData = null; compactStyle = null; currency = null; @@ -160,7 +160,7 @@ public class Properties implements Cloneable, Serializable { return this; } - private Properties _copyFrom(Properties other) { + private DecimalFormatProperties _copyFrom(DecimalFormatProperties other) { compactCustomData = other.compactCustomData; compactStyle = other.compactStyle; currency = other.currency; @@ -206,7 +206,7 @@ public class Properties implements Cloneable, Serializable { return this; } - private boolean _equals(Properties other) { + private boolean _equals(DecimalFormatProperties other) { boolean eq = true; eq = eq && _equalsHelper(compactCustomData, other.compactCustomData); eq = eq && _equalsHelper(compactStyle, other.compactStyle); @@ -327,16 +327,16 @@ public class Properties implements Cloneable, Serializable { return value.hashCode(); } - public Properties clear() { + public DecimalFormatProperties clear() { return _clear(); } /** Creates and returns a shallow copy of the property bag. */ @Override - public Properties clone() { + public DecimalFormatProperties clone() { // super.clone() returns a shallow copy. try { - return (Properties) super.clone(); + return (DecimalFormatProperties) super.clone(); } catch (CloneNotSupportedException e) { // Should never happen since super is Object throw new UnsupportedOperationException(e); @@ -349,7 +349,7 @@ public class Properties implements Cloneable, Serializable { * @param other The property bag from which to copy and which will not be modified. * @return The current property bag (the one modified by this operation), for chaining. */ - public Properties copyFrom(Properties other) { + public DecimalFormatProperties copyFrom(DecimalFormatProperties other) { return _copyFrom(other); } @@ -357,8 +357,8 @@ public class Properties implements Cloneable, Serializable { public boolean equals(Object other) { if (other == null) return false; if (this == other) return true; - if (!(other instanceof Properties)) return false; - return _equals((Properties) other); + if (!(other instanceof DecimalFormatProperties)) return false; + return _equals((DecimalFormatProperties) other); } /// BEGIN GETTERS/SETTERS /// @@ -557,7 +557,7 @@ public class Properties implements Cloneable, Serializable { // Get the field reference Field field = null; try { - field = Properties.class.getDeclaredField(name); + field = DecimalFormatProperties.class.getDeclaredField(name); } catch (NoSuchFieldException e) { // The field name does not exist! Possibly corrupted serialization. Ignore this entry. continue; @@ -605,7 +605,7 @@ public class Properties implements Cloneable, Serializable { * @param compactCustomData A map with the above structure. * @return The property bag, for chaining. */ - public Properties setCompactCustomData(Map> compactCustomData) { + public DecimalFormatProperties setCompactCustomData(Map> compactCustomData) { // TODO: compactCustomData is not immutable. this.compactCustomData = compactCustomData; return this; @@ -619,7 +619,7 @@ public class Properties implements Cloneable, Serializable { * @param compactStyle The style of prefixes/suffixes to append. * @return The property bag, for chaining. */ - public Properties setCompactStyle(CompactStyle compactStyle) { + public DecimalFormatProperties setCompactStyle(CompactStyle compactStyle) { this.compactStyle = compactStyle; return this; } @@ -630,7 +630,7 @@ public class Properties implements Cloneable, Serializable { * @param currency The currency. * @return The property bag, for chaining. */ - public Properties setCurrency(Currency currency) { + public DecimalFormatProperties setCurrency(Currency currency) { this.currency = currency; return this; } @@ -641,7 +641,7 @@ public class Properties implements Cloneable, Serializable { * @param currencyPluralInfo The currency plural info object. * @return The property bag, for chaining. */ - public Properties setCurrencyPluralInfo(CurrencyPluralInfo currencyPluralInfo) { + public DecimalFormatProperties setCurrencyPluralInfo(CurrencyPluralInfo currencyPluralInfo) { // TODO: In order to maintain immutability, we have to perform a clone here. // It would be better to just retire CurrencyPluralInfo entirely. if (currencyPluralInfo != null) { @@ -661,7 +661,7 @@ public class Properties implements Cloneable, Serializable { * @param currencyUsage The currency usage. Defaults to CurrencyUsage.STANDARD. * @return The property bag, for chaining. */ - public Properties setCurrencyUsage(CurrencyUsage currencyUsage) { + public DecimalFormatProperties setCurrencyUsage(CurrencyUsage currencyUsage) { this.currencyUsage = currencyUsage; return this; } @@ -675,7 +675,7 @@ public class Properties implements Cloneable, Serializable { * @param decimalPatternMatchRequired true to set an error if decimal is not present * @return The property bag, for chaining. */ - public Properties setDecimalPatternMatchRequired(boolean decimalPatternMatchRequired) { + public DecimalFormatProperties setDecimalPatternMatchRequired(boolean decimalPatternMatchRequired) { this.decimalPatternMatchRequired = decimalPatternMatchRequired; return this; } @@ -688,7 +688,7 @@ public class Properties implements Cloneable, Serializable { * @param decimalSeparatorAlwaysShown Whether to show the decimal point when it is optional. * @return The property bag, for chaining. */ - public Properties setDecimalSeparatorAlwaysShown(boolean alwaysShowDecimal) { + public DecimalFormatProperties setDecimalSeparatorAlwaysShown(boolean alwaysShowDecimal) { this.decimalSeparatorAlwaysShown = alwaysShowDecimal; return this; } @@ -701,7 +701,7 @@ public class Properties implements Cloneable, Serializable { * @param exponentSignAlwaysShown Whether to show the plus sign in positive exponents. * @return The property bag, for chaining. */ - public Properties setExponentSignAlwaysShown(boolean exponentSignAlwaysShown) { + public DecimalFormatProperties setExponentSignAlwaysShown(boolean exponentSignAlwaysShown) { this.exponentSignAlwaysShown = exponentSignAlwaysShown; return this; } @@ -721,7 +721,7 @@ public class Properties implements Cloneable, Serializable { * @see #setPadPosition * @see #setPadString */ - public Properties setFormatWidth(int paddingWidth) { + public DecimalFormatProperties setFormatWidth(int paddingWidth) { this.formatWidth = paddingWidth; return this; } @@ -734,7 +734,7 @@ public class Properties implements Cloneable, Serializable { * @param groupingSize The primary grouping size. * @return The property bag, for chaining. */ - public Properties setGroupingSize(int groupingSize) { + public DecimalFormatProperties setGroupingSize(int groupingSize) { this.groupingSize = groupingSize; return this; } @@ -747,7 +747,7 @@ public class Properties implements Cloneable, Serializable { * @return The property bag, for chaining. * @see #setMultiplier */ - public Properties setMagnitudeMultiplier(int magnitudeMultiplier) { + public DecimalFormatProperties setMagnitudeMultiplier(int magnitudeMultiplier) { this.magnitudeMultiplier = magnitudeMultiplier; return this; } @@ -761,7 +761,7 @@ public class Properties implements Cloneable, Serializable { * @see MathContext * @see #setRoundingMode */ - public Properties setMathContext(MathContext mathContext) { + public DecimalFormatProperties setMathContext(MathContext mathContext) { this.mathContext = mathContext; return this; } @@ -777,7 +777,7 @@ public class Properties implements Cloneable, Serializable { * @param maximumFractionDigits The maximum number of fraction digits to output. * @return The property bag, for chaining. */ - public Properties setMaximumFractionDigits(int maximumFractionDigits) { + public DecimalFormatProperties setMaximumFractionDigits(int maximumFractionDigits) { this.maximumFractionDigits = maximumFractionDigits; return this; } @@ -792,7 +792,7 @@ public class Properties implements Cloneable, Serializable { * @param maximumIntegerDigits The maximum number of integer digits to output. * @return The property bag, for chaining. */ - public Properties setMaximumIntegerDigits(int maximumIntegerDigits) { + public DecimalFormatProperties setMaximumIntegerDigits(int maximumIntegerDigits) { this.maximumIntegerDigits = maximumIntegerDigits; return this; } @@ -816,7 +816,7 @@ public class Properties implements Cloneable, Serializable { * @param maximumSignificantDigits The maximum number of significant digits to display. * @return The property bag, for chaining. */ - public Properties setMaximumSignificantDigits(int maximumSignificantDigits) { + public DecimalFormatProperties setMaximumSignificantDigits(int maximumSignificantDigits) { this.maximumSignificantDigits = maximumSignificantDigits; return this; } @@ -829,7 +829,7 @@ public class Properties implements Cloneable, Serializable { * @param minimumExponentDigits The minimum number of digits to display in the exponent field. * @return The property bag, for chaining. */ - public Properties setMinimumExponentDigits(int exponentDigits) { + public DecimalFormatProperties setMinimumExponentDigits(int exponentDigits) { this.minimumExponentDigits = exponentDigits; return this; } @@ -843,7 +843,7 @@ public class Properties implements Cloneable, Serializable { * @param minimumFractionDigits The minimum number of fraction digits to output. * @return The property bag, for chaining. */ - public Properties setMinimumFractionDigits(int minimumFractionDigits) { + public DecimalFormatProperties setMinimumFractionDigits(int minimumFractionDigits) { this.minimumFractionDigits = minimumFractionDigits; return this; } @@ -858,7 +858,7 @@ public class Properties implements Cloneable, Serializable { * enabling grouping. * @return The property bag, for chaining. */ - public Properties setMinimumGroupingDigits(int minimumGroupingDigits) { + public DecimalFormatProperties setMinimumGroupingDigits(int minimumGroupingDigits) { this.minimumGroupingDigits = minimumGroupingDigits; return this; } @@ -872,7 +872,7 @@ public class Properties implements Cloneable, Serializable { * @param minimumIntegerDigits The minimum number of integer digits to output. * @return The property bag, for chaining. */ - public Properties setMinimumIntegerDigits(int minimumIntegerDigits) { + public DecimalFormatProperties setMinimumIntegerDigits(int minimumIntegerDigits) { this.minimumIntegerDigits = minimumIntegerDigits; return this; } @@ -897,7 +897,7 @@ public class Properties implements Cloneable, Serializable { * @param minimumSignificantDigits The minimum number of significant digits to display. * @return The property bag, for chaining. */ - public Properties setMinimumSignificantDigits(int minimumSignificantDigits) { + public DecimalFormatProperties setMinimumSignificantDigits(int minimumSignificantDigits) { this.minimumSignificantDigits = minimumSignificantDigits; return this; } @@ -909,7 +909,7 @@ public class Properties implements Cloneable, Serializable { * @return The property bag, for chaining. * @see #setMagnitudeMultiplier */ - public Properties setMultiplier(BigDecimal multiplier) { + public DecimalFormatProperties setMultiplier(BigDecimal multiplier) { this.multiplier = multiplier; return this; } @@ -927,7 +927,7 @@ public class Properties implements Cloneable, Serializable { * @see PositiveNegativeAffixFormat * @see #setNegativePrefixPattern */ - public Properties setNegativePrefix(String negativePrefix) { + public DecimalFormatProperties setNegativePrefix(String negativePrefix) { this.negativePrefix = negativePrefix; return this; } @@ -944,7 +944,7 @@ public class Properties implements Cloneable, Serializable { * @see PositiveNegativeAffixFormat * @see #setNegativePrefix */ - public Properties setNegativePrefixPattern(String negativePrefixPattern) { + public DecimalFormatProperties setNegativePrefixPattern(String negativePrefixPattern) { this.negativePrefixPattern = negativePrefixPattern; return this; } @@ -963,7 +963,7 @@ public class Properties implements Cloneable, Serializable { * @see PositiveNegativeAffixFormat * @see #setNegativeSuffixPattern */ - public Properties setNegativeSuffix(String negativeSuffix) { + public DecimalFormatProperties setNegativeSuffix(String negativeSuffix) { this.negativeSuffix = negativeSuffix; return this; } @@ -980,7 +980,7 @@ public class Properties implements Cloneable, Serializable { * @see PositiveNegativeAffixFormat * @see #setNegativeSuffix */ - public Properties setNegativeSuffixPattern(String negativeSuffixPattern) { + public DecimalFormatProperties setNegativeSuffixPattern(String negativeSuffixPattern) { this.negativeSuffixPattern = negativeSuffixPattern; return this; } @@ -995,7 +995,7 @@ public class Properties implements Cloneable, Serializable { * @return The property bag, for chaining. * @see #setFormatWidth */ - public Properties setPadPosition(PadPosition paddingLocation) { + public DecimalFormatProperties setPadPosition(PadPosition paddingLocation) { this.padPosition = paddingLocation; return this; } @@ -1010,7 +1010,7 @@ public class Properties implements Cloneable, Serializable { * @return The property bag, for chaining. * @see #setFormatWidth */ - public Properties setPadString(String paddingString) { + public DecimalFormatProperties setPadString(String paddingString) { this.padString = paddingString; return this; } @@ -1027,7 +1027,7 @@ public class Properties implements Cloneable, Serializable { * @param parseCaseSensitive true to be case-sensitive when parsing; false to allow any case. * @return The property bag, for chaining. */ - public Properties setParseCaseSensitive(boolean parseCaseSensitive) { + public DecimalFormatProperties setParseCaseSensitive(boolean parseCaseSensitive) { this.parseCaseSensitive = parseCaseSensitive; return this; } @@ -1052,7 +1052,7 @@ public class Properties implements Cloneable, Serializable { * @param parseGroupingMode The {@link GroupingMode} to use; either DEFAULT or RESTRICTED. * @return The property bag, for chaining. */ - public Properties setParseGroupingMode(GroupingMode parseGroupingMode) { + public DecimalFormatProperties setParseGroupingMode(GroupingMode parseGroupingMode) { this.parseGroupingMode = parseGroupingMode; return this; } @@ -1065,7 +1065,7 @@ public class Properties implements Cloneable, Serializable { * fraction parts * @return The property bag, for chaining. */ - public Properties setParseIntegerOnly(boolean parseIntegerOnly) { + public DecimalFormatProperties setParseIntegerOnly(boolean parseIntegerOnly) { this.parseIntegerOnly = parseIntegerOnly; return this; } @@ -1077,7 +1077,7 @@ public class Properties implements Cloneable, Serializable { * @param parseMode Either {@link ParseMode#LENIENT} or {@link ParseMode#STRICT}. * @return The property bag, for chaining. */ - public Properties setParseMode(ParseMode parseMode) { + public DecimalFormatProperties setParseMode(ParseMode parseMode) { this.parseMode = parseMode; return this; } @@ -1089,7 +1089,7 @@ public class Properties implements Cloneable, Serializable { * @param parseIgnoreExponent true to ignore exponents; false to parse them. * @return The property bag, for chaining. */ - public Properties setParseNoExponent(boolean parseNoExponent) { + public DecimalFormatProperties setParseNoExponent(boolean parseNoExponent) { this.parseNoExponent = parseNoExponent; return this; } @@ -1102,7 +1102,7 @@ public class Properties implements Cloneable, Serializable { * BigInteger when possible. * @return The property bag, for chaining. */ - public Properties setParseToBigDecimal(boolean parseToBigDecimal) { + public DecimalFormatProperties setParseToBigDecimal(boolean parseToBigDecimal) { this.parseToBigDecimal = parseToBigDecimal; return this; } @@ -1113,7 +1113,7 @@ public class Properties implements Cloneable, Serializable { * @param pluralRules The object to reference. * @return The property bag, for chaining. */ - public Properties setPluralRules(PluralRules pluralRules) { + public DecimalFormatProperties setPluralRules(PluralRules pluralRules) { this.pluralRules = pluralRules; return this; } @@ -1130,7 +1130,7 @@ public class Properties implements Cloneable, Serializable { * @see PositiveNegativeAffixFormat * @see #setPositivePrefixPattern */ - public Properties setPositivePrefix(String positivePrefix) { + public DecimalFormatProperties setPositivePrefix(String positivePrefix) { this.positivePrefix = positivePrefix; return this; } @@ -1147,7 +1147,7 @@ public class Properties implements Cloneable, Serializable { * @see PositiveNegativeAffixFormat * @see #setPositivePrefix */ - public Properties setPositivePrefixPattern(String positivePrefixPattern) { + public DecimalFormatProperties setPositivePrefixPattern(String positivePrefixPattern) { this.positivePrefixPattern = positivePrefixPattern; return this; } @@ -1164,7 +1164,7 @@ public class Properties implements Cloneable, Serializable { * @see PositiveNegativeAffixFormat * @see #setPositiveSuffixPattern */ - public Properties setPositiveSuffix(String positiveSuffix) { + public DecimalFormatProperties setPositiveSuffix(String positiveSuffix) { this.positiveSuffix = positiveSuffix; return this; } @@ -1181,7 +1181,7 @@ public class Properties implements Cloneable, Serializable { * @see PositiveNegativeAffixFormat * @see #setPositiveSuffix */ - public Properties setPositiveSuffixPattern(String positiveSuffixPattern) { + public DecimalFormatProperties setPositiveSuffixPattern(String positiveSuffixPattern) { this.positiveSuffixPattern = positiveSuffixPattern; return this; } @@ -1201,7 +1201,7 @@ public class Properties implements Cloneable, Serializable { * @param roundingIncrement The interval to which to round. * @return The property bag, for chaining. */ - public Properties setRoundingIncrement(BigDecimal roundingIncrement) { + public DecimalFormatProperties setRoundingIncrement(BigDecimal roundingIncrement) { this.roundingIncrement = roundingIncrement; return this; } @@ -1218,7 +1218,7 @@ public class Properties implements Cloneable, Serializable { * @see RoundingMode * @see #setMathContext */ - public Properties setRoundingMode(RoundingMode roundingMode) { + public DecimalFormatProperties setRoundingMode(RoundingMode roundingMode) { this.roundingMode = roundingMode; return this; } @@ -1234,7 +1234,7 @@ public class Properties implements Cloneable, Serializable { * @param secondaryGroupingSize The secondary grouping size. * @return The property bag, for chaining. */ - public Properties setSecondaryGroupingSize(int secondaryGroupingSize) { + public DecimalFormatProperties setSecondaryGroupingSize(int secondaryGroupingSize) { this.secondaryGroupingSize = secondaryGroupingSize; return this; } @@ -1255,7 +1255,7 @@ public class Properties implements Cloneable, Serializable { * @param plusSignAlwaysShown Whether positive numbers should display a plus sign. * @return The property bag, for chaining. */ - public Properties setSignAlwaysShown(boolean signAlwaysShown) { + public DecimalFormatProperties setSignAlwaysShown(boolean signAlwaysShown) { this.signAlwaysShown = signAlwaysShown; return this; } @@ -1274,7 +1274,7 @@ public class Properties implements Cloneable, Serializable { * surrounded by <Properties>. */ public void toStringBare(StringBuilder result) { - Field[] fields = Properties.class.getDeclaredFields(); + Field[] fields = DecimalFormatProperties.class.getDeclaredFields(); for (Field field : fields) { Object myValue, defaultValue; try { @@ -1309,7 +1309,7 @@ public class Properties implements Cloneable, Serializable { ArrayList fieldsToSerialize = new ArrayList(); ArrayList valuesToSerialize = new ArrayList(); - Field[] fields = Properties.class.getDeclaredFields(); + Field[] fields = DecimalFormatProperties.class.getDeclaredFields(); for (Field field : fields) { if (Modifier.isStatic(field.getModifiers())) { continue; diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/FormatQuantity.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalQuantity.java similarity index 88% rename from icu4j/main/classes/core/src/com/ibm/icu/impl/number/FormatQuantity.java rename to icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalQuantity.java index c0f869bbf70..ef6c7b66da2 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/FormatQuantity.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalQuantity.java @@ -22,9 +22,9 @@ import com.ibm.icu.text.UFieldPosition; *

TODO: Should I change this to an abstract class so that logic for min/max digits doesn't need * to be copied to every implementation? */ -public interface FormatQuantity extends PluralRules.IFixedDecimal { +public interface DecimalQuantity extends PluralRules.IFixedDecimal { /** - * Sets the minimum and maximum integer digits that this {@link FormatQuantity} should generate. + * Sets the minimum and maximum integer digits that this {@link DecimalQuantity} should generate. * This method does not perform rounding. * * @param minInt The minimum number of integer digits. @@ -33,7 +33,7 @@ public interface FormatQuantity extends PluralRules.IFixedDecimal { public void setIntegerLength(int minInt, int maxInt); /** - * Sets the minimum and maximum fraction digits that this {@link FormatQuantity} should generate. + * Sets the minimum and maximum fraction digits that this {@link DecimalQuantity} should generate. * This method does not perform rounding. * * @param minFrac The minimum number of fraction digits. @@ -64,7 +64,7 @@ public interface FormatQuantity extends PluralRules.IFixedDecimal { /** * Rounds the number to an infinite number of decimal points. This has no effect except for - * forcing the double in {@link FormatQuantityBCD} to adopt its exact representation. + * forcing the double in {@link DecimalQuantity_AbstractBCD} to adopt its exact representation. */ public void roundToInfinity(); @@ -89,21 +89,21 @@ public interface FormatQuantity extends PluralRules.IFixedDecimal { */ public int getMagnitude() throws ArithmeticException; - /** @return Whether the value represented by this {@link FormatQuantity} is zero. */ + /** @return Whether the value represented by this {@link DecimalQuantity} is zero. */ public boolean isZero(); - /** @return Whether the value represented by this {@link FormatQuantity} is less than zero. */ + /** @return Whether the value represented by this {@link DecimalQuantity} is less than zero. */ public boolean isNegative(); - /** @return Whether the value represented by this {@link FormatQuantity} is infinite. */ + /** @return Whether the value represented by this {@link DecimalQuantity} is infinite. */ @Override public boolean isInfinite(); - /** @return Whether the value represented by this {@link FormatQuantity} is not a number. */ + /** @return Whether the value represented by this {@link DecimalQuantity} is not a number. */ @Override public boolean isNaN(); - /** @return The value contained in this {@link FormatQuantity} approximated as a double. */ + /** @return The value contained in this {@link DecimalQuantity} approximated as a double. */ public double toDouble(); public BigDecimal toBigDecimal(); @@ -112,7 +112,7 @@ public interface FormatQuantity extends PluralRules.IFixedDecimal { public int maxRepresentableDigits(); - // TODO: Should this method be removed, since FormatQuantity implements IFixedDecimal now? + // TODO: Should this method be removed, since DecimalQuantity implements IFixedDecimal now? /** * Computes the plural form for this number based on the specified set of rules. * @@ -182,9 +182,9 @@ public interface FormatQuantity extends PluralRules.IFixedDecimal { * * @return A copy of this instance which can be mutated without affecting this instance. */ - public FormatQuantity createCopy(); + public DecimalQuantity createCopy(); - public void copyFrom(FormatQuantity other); + public void copyFrom(DecimalQuantity other); /** This method is for internal testing only. */ public long getPositionFingerprint(); diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/FormatQuantity2.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalQuantity_64BitBCD.java similarity index 86% rename from icu4j/main/classes/core/src/com/ibm/icu/impl/number/FormatQuantity2.java rename to icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalQuantity_64BitBCD.java index a423ef04227..4954444a54c 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/FormatQuantity2.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalQuantity_64BitBCD.java @@ -5,7 +5,7 @@ package com.ibm.icu.impl.number; import java.math.BigDecimal; import java.math.BigInteger; -public final class FormatQuantity2 extends FormatQuantityBCD { +public final class DecimalQuantity_64BitBCD extends DecimalQuantity_AbstractBCD { /** * The BCD of the 16 digits of the number represented by this object. Every 4 bits of the long map @@ -21,27 +21,27 @@ public final class FormatQuantity2 extends FormatQuantityBCD { return 16; } - public FormatQuantity2(long input) { + public DecimalQuantity_64BitBCD(long input) { setToLong(input); } - public FormatQuantity2(int input) { + public DecimalQuantity_64BitBCD(int input) { setToInt(input); } - public FormatQuantity2(double input) { + public DecimalQuantity_64BitBCD(double input) { setToDouble(input); } - public FormatQuantity2(BigInteger input) { + public DecimalQuantity_64BitBCD(BigInteger input) { setToBigInteger(input); } - public FormatQuantity2(BigDecimal input) { + public DecimalQuantity_64BitBCD(BigDecimal input) { setToBigDecimal(input); } - public FormatQuantity2(FormatQuantity2 other) { + public DecimalQuantity_64BitBCD(DecimalQuantity_64BitBCD other) { copyFrom(other); } @@ -157,15 +157,15 @@ public final class FormatQuantity2 extends FormatQuantityBCD { } @Override - protected void copyBcdFrom(FormatQuantity _other) { - FormatQuantity2 other = (FormatQuantity2) _other; + protected void copyBcdFrom(DecimalQuantity _other) { + DecimalQuantity_64BitBCD other = (DecimalQuantity_64BitBCD) _other; bcd = other.bcd; } @Override public String toString() { return String.format( - "", + "", (lOptPos > 1000 ? "max" : String.valueOf(lOptPos)), lReqPos, rReqPos, diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/FormatQuantityBCD.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalQuantity_AbstractBCD.java similarity index 95% rename from icu4j/main/classes/core/src/com/ibm/icu/impl/number/FormatQuantityBCD.java rename to icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalQuantity_AbstractBCD.java index 90416bfa137..c814ee09a48 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/FormatQuantityBCD.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalQuantity_AbstractBCD.java @@ -15,9 +15,9 @@ import com.ibm.icu.text.UFieldPosition; /** * Represents numbers and digit display properties using Binary Coded Decimal (BCD). * - * @implements {@link FormatQuantity} + * @implements {@link DecimalQuantity} */ -public abstract class FormatQuantityBCD implements FormatQuantity { +public abstract class DecimalQuantity_AbstractBCD implements DecimalQuantity { /** * The power of ten corresponding to the least significant digit in the BCD. For example, if this @@ -51,10 +51,10 @@ public abstract class FormatQuantityBCD implements FormatQuantity { protected static final int NAN_FLAG = 4; // The following three fields relate to the double-to-ascii fast path algorithm. - // When a double is given to FormatQuantityBCD, it is converted to using a fast algorithm. The + // When a double is given to DecimalQuantityBCD, it is converted to using a fast algorithm. The // fast algorithm guarantees correctness to only the first ~12 digits of the double. The process // of rounding the number ensures that the converted digits are correct, falling back to a slow- - // path algorithm if required. Therefore, if a FormatQuantity is constructed from a double, it + // path algorithm if required. Therefore, if a DecimalQuantity is constructed from a double, it // is *required* that roundToMagnitude(), roundToIncrement(), or roundToInfinity() is called. If // you don't round, assertions will fail in certain other methods if you try calling them. @@ -108,9 +108,9 @@ public abstract class FormatQuantityBCD implements FormatQuantity { protected int rOptPos = Integer.MIN_VALUE; @Override - public void copyFrom(FormatQuantity _other) { + public void copyFrom(DecimalQuantity _other) { copyBcdFrom(_other); - FormatQuantityBCD other = (FormatQuantityBCD) _other; + DecimalQuantity_AbstractBCD other = (DecimalQuantity_AbstractBCD) _other; lOptPos = other.lOptPos; lReqPos = other.lReqPos; rReqPos = other.rReqPos; @@ -123,7 +123,7 @@ public abstract class FormatQuantityBCD implements FormatQuantity { isApproximate = other.isApproximate; } - public FormatQuantityBCD clear() { + public DecimalQuantity_AbstractBCD clear() { lOptPos = Integer.MAX_VALUE; lReqPos = 0; rReqPos = 0; @@ -135,7 +135,7 @@ public abstract class FormatQuantityBCD implements FormatQuantity { @Override public void setIntegerLength(int minInt, int maxInt) { - // Validation should happen outside of FormatQuantity, e.g., in the Rounder class. + // Validation should happen outside of DecimalQuantity, e.g., in the Rounder class. assert minInt >= 0; assert maxInt >= minInt; @@ -147,7 +147,7 @@ public abstract class FormatQuantityBCD implements FormatQuantity { @Override public void setFractionLength(int minFrac, int maxFrac) { - // Validation should happen outside of FormatQuantity, e.g., in the Rounder class. + // Validation should happen outside of DecimalQuantity, e.g., in the Rounder class. assert minFrac >= 0; assert maxFrac >= minFrac; @@ -311,13 +311,13 @@ public abstract class FormatQuantityBCD implements FormatQuantity { } @Override - public FormatQuantity createCopy() { - if (this instanceof FormatQuantity2) { - return new FormatQuantity2((FormatQuantity2) this); - } else if (this instanceof FormatQuantity3) { - return new FormatQuantity3((FormatQuantity3) this); - } else if (this instanceof FormatQuantity4) { - return new FormatQuantity4((FormatQuantity4) this); + public DecimalQuantity createCopy() { + if (this instanceof DecimalQuantity_64BitBCD) { + return new DecimalQuantity_64BitBCD((DecimalQuantity_64BitBCD) this); + } else if (this instanceof DecimalQuantity_ByteArrayBCD) { + return new DecimalQuantity_ByteArrayBCD((DecimalQuantity_ByteArrayBCD) this); + } else if (this instanceof DecimalQuantity_DualStorageBCD) { + return new DecimalQuantity_DualStorageBCD((DecimalQuantity_DualStorageBCD) this); } else { throw new IllegalArgumentException("Don't know how to copy " + this.getClass()); } @@ -501,7 +501,7 @@ public abstract class FormatQuantityBCD implements FormatQuantity { } /** - * Whether this {@link FormatQuantity4} has been explicitly converted to an exact double. true if + * Whether this {@link DecimalQuantity_DualStorageBCD} has been explicitly converted to an exact double. true if * backed by a double that was explicitly converted via convertToAccurateDouble; false otherwise. * Used for testing. * @@ -795,7 +795,7 @@ public abstract class FormatQuantityBCD implements FormatQuantity { /** * Appends a digit, optionally with one or more leading zeros, to the end of the value represented - * by this FormatQuantity. + * by this DecimalQuantity. * *

The primary use of this method is to construct numbers during a parsing loop. It allows * parsing to take advantage of the digit list infrastructure primarily designed for formatting. @@ -909,7 +909,7 @@ public abstract class FormatQuantityBCD implements FormatQuantity { */ protected abstract BigDecimal bcdToBigDecimal(); - protected abstract void copyBcdFrom(FormatQuantity _other); + protected abstract void copyBcdFrom(DecimalQuantity _other); /** * Removes trailing zeros from the BCD (adjusting the scale as required) and then computes the diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/FormatQuantity3.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalQuantity_ByteArrayBCD.java similarity index 88% rename from icu4j/main/classes/core/src/com/ibm/icu/impl/number/FormatQuantity3.java rename to icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalQuantity_ByteArrayBCD.java index 5024f47a37c..e428c6810c5 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/FormatQuantity3.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalQuantity_ByteArrayBCD.java @@ -5,7 +5,7 @@ package com.ibm.icu.impl.number; import java.math.BigDecimal; import java.math.BigInteger; -public final class FormatQuantity3 extends FormatQuantityBCD { +public final class DecimalQuantity_ByteArrayBCD extends DecimalQuantity_AbstractBCD { /** * The BCD of the 16 digits of the number represented by this object. Every 4 bits of the long map @@ -21,27 +21,27 @@ public final class FormatQuantity3 extends FormatQuantityBCD { return Integer.MAX_VALUE; } - public FormatQuantity3(long input) { + public DecimalQuantity_ByteArrayBCD(long input) { setToLong(input); } - public FormatQuantity3(int input) { + public DecimalQuantity_ByteArrayBCD(int input) { setToInt(input); } - public FormatQuantity3(double input) { + public DecimalQuantity_ByteArrayBCD(double input) { setToDouble(input); } - public FormatQuantity3(BigInteger input) { + public DecimalQuantity_ByteArrayBCD(BigInteger input) { setToBigInteger(input); } - public FormatQuantity3(BigDecimal input) { + public DecimalQuantity_ByteArrayBCD(BigDecimal input) { setToBigDecimal(input); } - public FormatQuantity3(FormatQuantity3 other) { + public DecimalQuantity_ByteArrayBCD(DecimalQuantity_ByteArrayBCD other) { copyFrom(other); } @@ -201,8 +201,8 @@ public final class FormatQuantity3 extends FormatQuantityBCD { } @Override - protected void copyBcdFrom(FormatQuantity _other) { - FormatQuantity3 other = (FormatQuantity3) _other; + protected void copyBcdFrom(DecimalQuantity _other) { + DecimalQuantity_ByteArrayBCD other = (DecimalQuantity_ByteArrayBCD) _other; System.arraycopy(other.bcd, 0, bcd, 0, bcd.length); } @@ -213,7 +213,7 @@ public final class FormatQuantity3 extends FormatQuantityBCD { sb.append(bcd[i]); } return String.format( - "", + "", (lOptPos > 1000 ? "max" : String.valueOf(lOptPos)), lReqPos, rReqPos, diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/FormatQuantity4.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalQuantity_DualStorageBCD.java similarity index 91% rename from icu4j/main/classes/core/src/com/ibm/icu/impl/number/FormatQuantity4.java rename to icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalQuantity_DualStorageBCD.java index f22cca4613e..a41f4761ba0 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/FormatQuantity4.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalQuantity_DualStorageBCD.java @@ -5,7 +5,11 @@ package com.ibm.icu.impl.number; import java.math.BigDecimal; import java.math.BigInteger; -public final class FormatQuantity4 extends FormatQuantityBCD { +/** + * A DecimalQuantity with internal storage as a 64-bit BCD, with fallback to a byte array + * for numbers that don't fit into the standard BCD. + */ +public final class DecimalQuantity_DualStorageBCD extends DecimalQuantity_AbstractBCD { /** * The BCD of the 16 digits of the number represented by this object. Every 4 bits of the long map @@ -25,35 +29,35 @@ public final class FormatQuantity4 extends FormatQuantityBCD { return Integer.MAX_VALUE; } - public FormatQuantity4() { + public DecimalQuantity_DualStorageBCD() { setBcdToZero(); } - public FormatQuantity4(long input) { + public DecimalQuantity_DualStorageBCD(long input) { setToLong(input); } - public FormatQuantity4(int input) { + public DecimalQuantity_DualStorageBCD(int input) { setToInt(input); } - public FormatQuantity4(double input) { + public DecimalQuantity_DualStorageBCD(double input) { setToDouble(input); } - public FormatQuantity4(BigInteger input) { + public DecimalQuantity_DualStorageBCD(BigInteger input) { setToBigInteger(input); } - public FormatQuantity4(BigDecimal input) { + public DecimalQuantity_DualStorageBCD(BigDecimal input) { setToBigDecimal(input); } - public FormatQuantity4(FormatQuantity4 other) { + public DecimalQuantity_DualStorageBCD(DecimalQuantity_DualStorageBCD other) { copyFrom(other); } - public FormatQuantity4(Number number) { + public DecimalQuantity_DualStorageBCD(Number number) { if (number instanceof Long) { setToLong(number.longValue()); } else if (number instanceof Integer) { @@ -317,8 +321,8 @@ public final class FormatQuantity4 extends FormatQuantityBCD { } @Override - protected void copyBcdFrom(FormatQuantity _other) { - FormatQuantity4 other = (FormatQuantity4) _other; + protected void copyBcdFrom(DecimalQuantity _other) { + DecimalQuantity_DualStorageBCD other = (DecimalQuantity_DualStorageBCD) _other; if (other.usingBytes) { usingBytes = true; ensureCapacity(other.precision); @@ -376,7 +380,7 @@ public final class FormatQuantity4 extends FormatQuantityBCD { } /** - * Checks whether this {@link FormatQuantity4} is using its internal byte array storage mechanism. + * Checks whether this {@link DecimalQuantity_DualStorageBCD} is using its internal byte array storage mechanism. * * @return true if an internal byte array is being used; false if a long is being used. * @internal @@ -398,7 +402,7 @@ public final class FormatQuantity4 extends FormatQuantityBCD { sb.append(Long.toHexString(bcdLong)); } return String.format( - "", + "", (lOptPos > 1000 ? "max" : String.valueOf(lOptPos)), lReqPos, rReqPos, diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/FormatQuantity1.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalQuantity_SimpleStorage.java similarity index 94% rename from icu4j/main/classes/core/src/com/ibm/icu/impl/number/FormatQuantity1.java rename to icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalQuantity_SimpleStorage.java index e68cf99bbfe..cf7929df666 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/FormatQuantity1.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/DecimalQuantity_SimpleStorage.java @@ -13,14 +13,14 @@ import com.ibm.icu.text.PluralRules.Operand; import com.ibm.icu.text.UFieldPosition; /** - * This is an older implementation of FormatQuantity. A newer, faster implementation is - * FormatQuantity2. I kept this implementation around because it was useful for testing purposes + * This is an older implementation of DecimalQuantity. A newer, faster implementation is + * DecimalQuantity2. I kept this implementation around because it was useful for testing purposes * (being able to compare the output of one implementation with the other). * *

This class is NOT IMMUTABLE and NOT THREAD SAFE and is intended to be used by a single thread * to format a number through a formatter, which is thread-safe. */ -public class FormatQuantity1 implements FormatQuantity { +public class DecimalQuantity_SimpleStorage implements DecimalQuantity { // Four positions: left optional '(', left required '[', right required ']', right optional ')'. // These four positions determine which digits are displayed in the output string. They do NOT // affect rounding. These positions are internal-only and can be specified only by the public @@ -98,7 +98,7 @@ public class FormatQuantity1 implements FormatQuantity { return Integer.MAX_VALUE; } - public FormatQuantity1(long input) { + public DecimalQuantity_SimpleStorage(long input) { if (input < 0) { setNegative(true); input *= -1; @@ -111,13 +111,13 @@ public class FormatQuantity1 implements FormatQuantity { } /** - * Creates a FormatQuantity from the given double value. Internally attempts several strategies + * Creates a DecimalQuantity from the given double value. Internally attempts several strategies * for converting the double to an exact representation, falling back on a BigDecimal if it fails * to do so. * - * @param input The double to represent by this FormatQuantity. + * @param input The double to represent by this DecimalQuantity. */ - public FormatQuantity1(double input) { + public DecimalQuantity_SimpleStorage(double input) { if (input < 0) { setNegative(true); input *= -1; @@ -191,7 +191,7 @@ public class FormatQuantity1 implements FormatQuantity { static final double LOG_2_OF_TEN = 3.32192809489; - public FormatQuantity1(double input, boolean fast) { + public DecimalQuantity_SimpleStorage(double input, boolean fast) { if (input < 0) { setNegative(true); input *= -1; @@ -230,11 +230,11 @@ public class FormatQuantity1 implements FormatQuantity { } } - public FormatQuantity1(BigDecimal decimal) { + public DecimalQuantity_SimpleStorage(BigDecimal decimal) { setToBigDecimal(decimal); } - public FormatQuantity1(FormatQuantity1 other) { + public DecimalQuantity_SimpleStorage(DecimalQuantity_SimpleStorage other) { copyFrom(other); } @@ -254,20 +254,20 @@ public class FormatQuantity1 implements FormatQuantity { } @Override - public FormatQuantity1 createCopy() { - return new FormatQuantity1(this); + public DecimalQuantity_SimpleStorage createCopy() { + return new DecimalQuantity_SimpleStorage(this); } /** - * Make the internal state of this FormatQuantity equal to another FormatQuantity. + * Make the internal state of this DecimalQuantity equal to another DecimalQuantity. * - * @param other The template FormatQuantity. All properties from this FormatQuantity will be - * copied into this FormatQuantity. + * @param other The template DecimalQuantity. All properties from this DecimalQuantity will be + * copied into this DecimalQuantity. */ @Override - public void copyFrom(FormatQuantity other) { + public void copyFrom(DecimalQuantity other) { // TODO: Check before casting - FormatQuantity1 _other = (FormatQuantity1) other; + DecimalQuantity_SimpleStorage _other = (DecimalQuantity_SimpleStorage) other; lOptPos = _other.lOptPos; lReqPos = _other.lReqPos; rReqPos = _other.rReqPos; @@ -457,7 +457,7 @@ public class FormatQuantity1 implements FormatQuantity { } } - /** @return The power of ten of the highest digit represented by this FormatQuantity */ + /** @return The power of ten of the highest digit represented by this DecimalQuantity */ @Override public int getMagnitude() throws ArithmeticException { int scale = (primary == -1) ? scaleBigDecimal(fallback) : primaryScale; @@ -470,8 +470,8 @@ public class FormatQuantity1 implements FormatQuantity { } /** - * Changes the magnitude of this FormatQuantity. If the indices of the represented digits had been - * previously specified, those indices are moved relative to the FormatQuantity. + * Changes the magnitude of this DecimalQuantity. If the indices of the represented digits had been + * previously specified, those indices are moved relative to the DecimalQuantity. * *

This method does NOT perform rounding. * @@ -496,7 +496,7 @@ public class FormatQuantity1 implements FormatQuantity { return a + b; } - /** @return If the number represented by this FormatQuantity is less than zero */ + /** @return If the number represented by this DecimalQuantity is less than zero */ @Override public boolean isNegative() { return (flags & NEGATIVE_FLAG) != 0; @@ -525,7 +525,7 @@ public class FormatQuantity1 implements FormatQuantity { } /** - * Returns a representation of this FormatQuantity as a double, with possible loss of information. + * Returns a representation of this DecimalQuantity as a double, with possible loss of information. */ @Override public double toDouble() { @@ -686,7 +686,7 @@ public class FormatQuantity1 implements FormatQuantity { private int fractionCount() { // TODO: This is temporary. - FormatQuantity1 copy = new FormatQuantity1(this); + DecimalQuantity_SimpleStorage copy = new DecimalQuantity_SimpleStorage(this); int fractionCount = 0; while (copy.hasNextFraction()) { copy.nextFraction(); @@ -718,7 +718,7 @@ public class FormatQuantity1 implements FormatQuantity { @Override public byte getDigit(int magnitude) { // TODO: This is temporary. - FormatQuantity1 copy = new FormatQuantity1(this); + DecimalQuantity_SimpleStorage copy = new DecimalQuantity_SimpleStorage(this); if (magnitude < 0) { for (int p = -1; p > magnitude; p--) { copy.nextFraction(); @@ -817,7 +817,7 @@ public class FormatQuantity1 implements FormatQuantity { @Override public String toString() { StringBuilder sb = new StringBuilder(); - sb.append(" 1000 ? "max" : lOptPos); sb.append(":"); diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/Modifier.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/Modifier.java index 11eb56bc85b..577cb1e82fe 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/Modifier.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/Modifier.java @@ -2,7 +2,7 @@ // License & terms of use: http://www.unicode.org/copyright.html#License package com.ibm.icu.impl.number; -import newapi.MutablePatternModifier; +import newapi.impl.MutablePatternModifier; /** * A Modifier is an object that can be passed through the formatting pipeline until it is finally applied to the string diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/Parse.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/Parse.java index 87b588ae0f9..4835b674845 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/Parse.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/Parse.java @@ -113,7 +113,7 @@ public class Parse { } /** - * @see Parse#parse(String, ParsePosition, ParseMode, boolean, boolean, Properties, + * @see Parse#parse(String, ParsePosition, ParseMode, boolean, boolean, DecimalFormatProperties, * DecimalFormatSymbols) */ private static enum StateName { @@ -203,7 +203,7 @@ public class Parse { int score; // Numerical value: - FormatQuantity4 fq = new FormatQuantity4(); + DecimalQuantity_DualStorageBCD fq = new DecimalQuantity_DualStorageBCD(); int numDigits; int trailingZeros; int exponent; @@ -400,7 +400,7 @@ public class Parse { * * @return The Number. Never null. */ - Number toNumber(Properties properties) { + Number toNumber(DecimalFormatProperties properties) { // Check for NaN, infinity, and -0.0 if (sawNaN) { return Double.NaN; @@ -470,7 +470,7 @@ public class Parse { * * @return The CurrencyAmount. Never null. */ - public CurrencyAmount toCurrencyAmount(Properties properties) { + public CurrencyAmount toCurrencyAmount(DecimalFormatProperties properties) { assert isoCode != null; Number number = toNumber(properties); Currency currency = Currency.getInstance(isoCode); @@ -495,7 +495,7 @@ public class Parse { sb.append("{"); sb.append(currentAffixPattern); sb.append(":"); - sb.append(AffixPatternUtils.getOffset(currentStepwiseParserTag) - 1); + sb.append(AffixUtils.getOffset(currentStepwiseParserTag) - 1); sb.append("}"); } sb.append(" "); @@ -539,7 +539,7 @@ public class Parse { int prevLength; // Properties and Symbols memory: - Properties properties; + DecimalFormatProperties properties; DecimalFormatSymbols symbols; ParseMode mode; boolean caseSensitive; @@ -680,7 +680,7 @@ public class Parse { static final AffixHolder EMPTY_POSITIVE = new AffixHolder("", "", true, false); static final AffixHolder EMPTY_NEGATIVE = new AffixHolder("", "", true, true); - static void addToState(ParserState state, Properties properties) { + static void addToState(ParserState state, DecimalFormatProperties properties) { AffixHolder pp = fromPropertiesPositivePattern(properties); AffixHolder np = fromPropertiesNegativePattern(properties); AffixHolder ps = fromPropertiesPositiveString(properties); @@ -691,7 +691,7 @@ public class Parse { if (ns != null) state.affixHolders.add(ns); } - static AffixHolder fromPropertiesPositivePattern(Properties properties) { + static AffixHolder fromPropertiesPositivePattern(DecimalFormatProperties properties) { String ppp = properties.getPositivePrefixPattern(); String psp = properties.getPositiveSuffixPattern(); if (properties.getSignAlwaysShown()) { @@ -699,13 +699,13 @@ public class Parse { boolean foundSign = false; String npp = properties.getNegativePrefixPattern(); String nsp = properties.getNegativeSuffixPattern(); - if (AffixPatternUtils.containsType(npp, AffixPatternUtils.TYPE_MINUS_SIGN)) { + if (AffixUtils.containsType(npp, AffixUtils.TYPE_MINUS_SIGN)) { foundSign = true; - ppp = AffixPatternUtils.replaceType(npp, AffixPatternUtils.TYPE_MINUS_SIGN, '+'); + ppp = AffixUtils.replaceType(npp, AffixUtils.TYPE_MINUS_SIGN, '+'); } - if (AffixPatternUtils.containsType(nsp, AffixPatternUtils.TYPE_MINUS_SIGN)) { + if (AffixUtils.containsType(nsp, AffixUtils.TYPE_MINUS_SIGN)) { foundSign = true; - psp = AffixPatternUtils.replaceType(nsp, AffixPatternUtils.TYPE_MINUS_SIGN, '+'); + psp = AffixUtils.replaceType(nsp, AffixUtils.TYPE_MINUS_SIGN, '+'); } if (!foundSign) { ppp = "+" + ppp; @@ -714,7 +714,7 @@ public class Parse { return getInstance(ppp, psp, false, false); } - static AffixHolder fromPropertiesNegativePattern(Properties properties) { + static AffixHolder fromPropertiesNegativePattern(DecimalFormatProperties properties) { String npp = properties.getNegativePrefixPattern(); String nsp = properties.getNegativeSuffixPattern(); if (npp == null && nsp == null) { @@ -729,14 +729,14 @@ public class Parse { return getInstance(npp, nsp, false, true); } - static AffixHolder fromPropertiesPositiveString(Properties properties) { + static AffixHolder fromPropertiesPositiveString(DecimalFormatProperties properties) { String pp = properties.getPositivePrefix(); String ps = properties.getPositiveSuffix(); if (pp == null && ps == null) return null; return getInstance(pp, ps, true, false); } - static AffixHolder fromPropertiesNegativeString(Properties properties) { + static AffixHolder fromPropertiesNegativeString(DecimalFormatProperties properties) { String np = properties.getNegativePrefix(); String ns = properties.getNegativeSuffix(); if (np == null && ns == null) return null; @@ -826,18 +826,18 @@ public class Parse { } } - private static final ThreadLocal threadLocalProperties = - new ThreadLocal() { + private static final ThreadLocal threadLocalProperties = + new ThreadLocal() { @Override - protected Properties initialValue() { - return new Properties(); + protected DecimalFormatProperties initialValue() { + return new DecimalFormatProperties(); } }; private void addPattern(String pattern) { - Properties properties = threadLocalProperties.get(); + DecimalFormatProperties properties = threadLocalProperties.get(); try { - PatternAndPropertyUtils.parseToExistingProperties(pattern, properties); + PatternStringParser.parseToExistingProperties(pattern, properties); } catch (IllegalArgumentException e) { // This should only happen if there is a bug in CLDR data. Fail silently. } @@ -912,7 +912,7 @@ public class Parse { 0xFE63, 0xFE63, 0xFF0D, 0xFF0D) .freeze(); - public static Number parse(String input, Properties properties, DecimalFormatSymbols symbols) { + public static Number parse(String input, DecimalFormatProperties properties, DecimalFormatSymbols symbols) { ParsePosition ppos = threadLocalParsePosition.get(); ppos.setIndex(0); return parse(input, ppos, properties, symbols); @@ -940,19 +940,19 @@ public class Parse { public static Number parse( CharSequence input, ParsePosition ppos, - Properties properties, + DecimalFormatProperties properties, DecimalFormatSymbols symbols) { StateItem best = _parse(input, ppos, false, properties, symbols); return (best == null) ? null : best.toNumber(properties); } public static CurrencyAmount parseCurrency( - String input, Properties properties, DecimalFormatSymbols symbols) throws ParseException { + String input, DecimalFormatProperties properties, DecimalFormatSymbols symbols) throws ParseException { return parseCurrency(input, null, properties, symbols); } public static CurrencyAmount parseCurrency( - CharSequence input, ParsePosition ppos, Properties properties, DecimalFormatSymbols symbols) + CharSequence input, ParsePosition ppos, DecimalFormatProperties properties, DecimalFormatSymbols symbols) throws ParseException { if (ppos == null) { ppos = threadLocalParsePosition.get(); @@ -967,7 +967,7 @@ public class Parse { CharSequence input, ParsePosition ppos, boolean parseCurrency, - Properties properties, + DecimalFormatProperties properties, DecimalFormatSymbols symbols) { if (input == null || ppos == null || properties == null || symbols == null) { @@ -1716,7 +1716,7 @@ public class Parse { added = acceptString(cp, nextName, null, state, item, str, 0, false); } else { added = - acceptAffixPattern(cp, nextName, state, item, str, AffixPatternUtils.nextToken(0, str)); + acceptAffixPattern(cp, nextName, state, item, str, AffixUtils.nextToken(0, str)); } // Record state in the added entries for (int i = Long.numberOfTrailingZeros(added); (1L << i) <= added; i++) { @@ -1899,27 +1899,27 @@ public class Parse { if (typeOrCp < 0) { // Symbol switch (typeOrCp) { - case AffixPatternUtils.TYPE_MINUS_SIGN: + case AffixUtils.TYPE_MINUS_SIGN: resolvedMinusSign = true; break; - case AffixPatternUtils.TYPE_PLUS_SIGN: + case AffixUtils.TYPE_PLUS_SIGN: resolvedPlusSign = true; break; - case AffixPatternUtils.TYPE_PERCENT: + case AffixUtils.TYPE_PERCENT: resolvedStr = state.symbols.getPercentString(); if (resolvedStr.length() != 1 || resolvedStr.charAt(0) != '%') { resolvedCp = '%'; // accept ASCII percent as well as locale percent } break; - case AffixPatternUtils.TYPE_PERMILLE: + case AffixUtils.TYPE_PERMILLE: resolvedStr = state.symbols.getPerMillString(); if (resolvedStr.length() != 1 || resolvedStr.charAt(0) != '‰') { resolvedCp = '‰'; // accept ASCII permille as well as locale permille } break; - case AffixPatternUtils.TYPE_CURRENCY_SINGLE: - case AffixPatternUtils.TYPE_CURRENCY_DOUBLE: - case AffixPatternUtils.TYPE_CURRENCY_TRIPLE: + case AffixUtils.TYPE_CURRENCY_SINGLE: + case AffixUtils.TYPE_CURRENCY_DOUBLE: + case AffixUtils.TYPE_CURRENCY_TRIPLE: resolvedCurrency = true; break; default: @@ -2094,7 +2094,7 @@ public class Parse { int typeOrCp = isString ? Character.codePointAt(str, (int) offsetOrTag) - : AffixPatternUtils.getTypeOrCp(offsetOrTag); + : AffixUtils.getTypeOrCp(offsetOrTag); if (isIgnorable(typeOrCp, state)) { // Look for the next nonignorable code point @@ -2107,7 +2107,7 @@ public class Parse { nextOffsetOrTag = isString ? nextOffsetOrTag + Character.charCount(nextTypeOrCp) - : AffixPatternUtils.nextToken(nextOffsetOrTag, str); + : AffixUtils.nextToken(nextOffsetOrTag, str); if (firstOffsetOrTag == 0L) firstOffsetOrTag = nextOffsetOrTag; if (isString ? nextOffsetOrTag >= str.length() : nextOffsetOrTag < 0) { // Integer.MIN_VALUE is an invalid value for either a type or a cp; @@ -2118,7 +2118,7 @@ public class Parse { nextTypeOrCp = isString ? Character.codePointAt(str, (int) nextOffsetOrTag) - : AffixPatternUtils.getTypeOrCp(nextOffsetOrTag); + : AffixUtils.getTypeOrCp(nextOffsetOrTag); if (!isIgnorable(nextTypeOrCp, state)) break; } @@ -2177,7 +2177,7 @@ public class Parse { nextOffsetOrTag = isString ? nextOffsetOrTag + Character.charCount(nextTypeOrCp) - : AffixPatternUtils.nextToken(nextOffsetOrTag, str); + : AffixUtils.nextToken(nextOffsetOrTag, str); if (firstOffsetOrTag == 0L) firstOffsetOrTag = nextOffsetOrTag; if (isString ? nextOffsetOrTag >= str.length() : nextOffsetOrTag < 0) { nextTypeOrCp = -1; @@ -2186,7 +2186,7 @@ public class Parse { nextTypeOrCp = isString ? Character.codePointAt(str, (int) nextOffsetOrTag) - : AffixPatternUtils.getTypeOrCp(nextOffsetOrTag); + : AffixUtils.getTypeOrCp(nextOffsetOrTag); if (!isIgnorable(nextTypeOrCp, state)) break; } diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/PatternParser.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/PatternStringParser.java similarity index 55% rename from icu4j/main/classes/core/src/com/ibm/icu/impl/number/PatternParser.java rename to icu4j/main/classes/core/src/com/ibm/icu/impl/number/PatternStringParser.java index f469d75587f..208ad2c5a94 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/PatternParser.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/PatternStringParser.java @@ -6,20 +6,24 @@ import newapi.impl.AffixPatternProvider; import newapi.impl.Padder.PadPosition; /** Implements a recursive descent parser for decimal format patterns. */ -public class PatternParser { +public class PatternStringParser { + + public static final int IGNORE_ROUNDING_NEVER = 0; + public static final int IGNORE_ROUNDING_IF_CURRENCY = 1; + public static final int IGNORE_ROUNDING_ALWAYS = 2; /** * Runs the recursive descent parser on the given pattern string, returning a data structure with raw information * about the pattern string. * *

- * To obtain a more useful form of the data, consider using {@link PatternAndPropertyUtils#parse} instead. + * To obtain a more useful form of the data, consider using {@link #parseToProperties} instead. * * @param patternString * The LDML decimal format pattern (Excel-style pattern) to parse. * @return The results of the parse. */ - public static ParsedPatternInfo parse(String patternString) { + public static ParsedPatternInfo parseToPatternInfo(String patternString) { ParserState state = new ParserState(patternString); ParsedPatternInfo result = new ParsedPatternInfo(patternString); consumePattern(state, result); @@ -27,9 +31,59 @@ public class PatternParser { } /** - * Contains information about - * @author sffc + * Parses a pattern string into a new property bag. * + * @param pattern + * The pattern string, like "#,##0.00" + * @param ignoreRounding + * Whether to leave out rounding information (minFrac, maxFrac, and rounding increment) when parsing the + * pattern. This may be desirable if a custom rounding mode, such as CurrencyUsage, is to be used + * instead. One of {@link PatternStringParser#IGNORE_ROUNDING_ALWAYS}, + * {@link PatternStringParser#IGNORE_ROUNDING_IF_CURRENCY}, or + * {@link PatternStringParser#IGNORE_ROUNDING_NEVER}. + * @return A property bag object. + * @throws IllegalArgumentException + * If there is a syntax error in the pattern string. + */ + public static DecimalFormatProperties parseToProperties(String pattern, int ignoreRounding) { + DecimalFormatProperties properties = new DecimalFormatProperties(); + parseToExistingPropertiesImpl(pattern, properties, ignoreRounding); + return properties; + } + + public static DecimalFormatProperties parseToProperties(String pattern) { + return parseToProperties(pattern, PatternStringParser.IGNORE_ROUNDING_NEVER); + } + + /** + * Parses a pattern string into an existing property bag. All properties that can be encoded into a pattern string + * will be overwritten with either their default value or with the value coming from the pattern string. Properties + * that cannot be encoded into a pattern string, such as rounding mode, are not modified. + * + * @param pattern + * The pattern string, like "#,##0.00" + * @param properties + * The property bag object to overwrite. + * @param ignoreRounding + * See {@link #parseToProperties(String pattern, int ignoreRounding)}. + * @throws IllegalArgumentException + * If there was a syntax error in the pattern string. + */ + public static void parseToExistingProperties(String pattern, DecimalFormatProperties properties, + int ignoreRounding) { + parseToExistingPropertiesImpl(pattern, properties, ignoreRounding); + } + + public static void parseToExistingProperties(String pattern, DecimalFormatProperties properties) { + parseToExistingProperties(pattern, properties, PatternStringParser.IGNORE_ROUNDING_NEVER); + } + + ///////////////////////////////////////////////////// + /// BEGIN RECURSIVE DESCENT PARSER IMPLEMENTATION /// + ///////////////////////////////////////////////////// + + /** + * Contains raw information about the parsed decimal format pattern string. */ public static class ParsedPatternInfo implements AffixPatternProvider { public String pattern; @@ -113,7 +167,7 @@ public class PatternParser { @Override public boolean containsSymbolType(int type) { - return AffixPatternUtils.containsType(pattern, type); + return AffixUtils.containsType(pattern, type); } } @@ -130,7 +184,7 @@ public class PatternParser { public boolean hasDecimal = false; public int widthExceptAffixes = 0; public PadPosition paddingLocation = null; - public FormatQuantity4 rounding = null; + public DecimalQuantity_DualStorageBCD rounding = null; public boolean exponentHasPlusSign = false; public int exponentZeros = 0; public boolean hasPercentSign = false; @@ -353,7 +407,7 @@ public class PatternParser { result.integerNumerals += 1; result.integerTotal += 1; if (state.peek() != '0' && result.rounding == null) { - result.rounding = new FormatQuantity4(); + result.rounding = new DecimalQuantity_DualStorageBCD(); } if (result.rounding != null) { result.rounding.appendDigit((byte) (state.peek() - '0'), 0, true); @@ -409,7 +463,7 @@ public class PatternParser { zeroCounter++; } else { if (result.rounding == null) { - result.rounding = new FormatQuantity4(); + result.rounding = new DecimalQuantity_DualStorageBCD(); } result.rounding.appendDigit((byte) (state.peek() - '0'), zeroCounter, false); zeroCounter = 0; @@ -440,4 +494,185 @@ public class PatternParser { result.widthExceptAffixes++; } } + + /////////////////////////////////////////////////// + /// END RECURSIVE DESCENT PARSER IMPLEMENTATION /// + /////////////////////////////////////////////////// + + private static void parseToExistingPropertiesImpl(String pattern, DecimalFormatProperties properties, int ignoreRounding) { + if (pattern == null || pattern.length() == 0) { + // Backwards compatibility requires that we reset to the default values. + // TODO: Only overwrite the properties that "saveToProperties" normally touches? + properties.clear(); + return; + } + + // TODO: Use thread locals here? + ParsedPatternInfo patternInfo = parseToPatternInfo(pattern); + patternInfoToProperties(properties, patternInfo, ignoreRounding); + } + + /** Finalizes the temporary data stored in the ParsedPatternInfo to the Properties. */ + private static void patternInfoToProperties(DecimalFormatProperties properties, ParsedPatternInfo patternInfo, + int _ignoreRounding) { + // Translate from PatternParseResult to Properties. + // Note that most data from "negative" is ignored per the specification of DecimalFormat. + + ParsedSubpatternInfo positive = patternInfo.positive; + ParsedSubpatternInfo negative = patternInfo.negative; + + boolean ignoreRounding; + if (_ignoreRounding == PatternStringParser.IGNORE_ROUNDING_NEVER) { + ignoreRounding = false; + } else if (_ignoreRounding == PatternStringParser.IGNORE_ROUNDING_IF_CURRENCY) { + ignoreRounding = positive.hasCurrencySign; + } else { + assert _ignoreRounding == PatternStringParser.IGNORE_ROUNDING_ALWAYS; + ignoreRounding = true; + } + + // Grouping settings + short grouping1 = (short) (positive.groupingSizes & 0xffff); + short grouping2 = (short) ((positive.groupingSizes >>> 16) & 0xffff); + short grouping3 = (short) ((positive.groupingSizes >>> 32) & 0xffff); + if (grouping2 != -1) { + properties.setGroupingSize(grouping1); + } else { + properties.setGroupingSize(-1); + } + if (grouping3 != -1) { + properties.setSecondaryGroupingSize(grouping2); + } else { + properties.setSecondaryGroupingSize(-1); + } + + // For backwards compatibility, require that the pattern emit at least one min digit. + int minInt, minFrac; + if (positive.integerTotal == 0 && positive.fractionTotal > 0) { + // patterns like ".##" + minInt = 0; + minFrac = Math.max(1, positive.fractionNumerals); + } else if (positive.integerNumerals == 0 && positive.fractionNumerals == 0) { + // patterns like "#.##" + minInt = 1; + minFrac = 0; + } else { + minInt = positive.integerNumerals; + minFrac = positive.fractionNumerals; + } + + // Rounding settings + // Don't set basic rounding when there is a currency sign; defer to CurrencyUsage + if (positive.integerAtSigns > 0) { + properties.setMinimumFractionDigits(-1); + properties.setMaximumFractionDigits(-1); + properties.setRoundingIncrement(null); + properties.setMinimumSignificantDigits(positive.integerAtSigns); + properties.setMaximumSignificantDigits(positive.integerAtSigns + positive.integerTrailingHashSigns); + } else if (positive.rounding != null) { + if (!ignoreRounding) { + properties.setMinimumFractionDigits(minFrac); + properties.setMaximumFractionDigits(positive.fractionTotal); + properties.setRoundingIncrement(positive.rounding.toBigDecimal().setScale(positive.fractionNumerals)); + } else { + properties.setMinimumFractionDigits(-1); + properties.setMaximumFractionDigits(-1); + properties.setRoundingIncrement(null); + } + properties.setMinimumSignificantDigits(-1); + properties.setMaximumSignificantDigits(-1); + } else { + if (!ignoreRounding) { + properties.setMinimumFractionDigits(minFrac); + properties.setMaximumFractionDigits(positive.fractionTotal); + properties.setRoundingIncrement(null); + } else { + properties.setMinimumFractionDigits(-1); + properties.setMaximumFractionDigits(-1); + properties.setRoundingIncrement(null); + } + properties.setMinimumSignificantDigits(-1); + properties.setMaximumSignificantDigits(-1); + } + + // If the pattern ends with a '.' then force the decimal point. + if (positive.hasDecimal && positive.fractionTotal == 0) { + properties.setDecimalSeparatorAlwaysShown(true); + } else { + properties.setDecimalSeparatorAlwaysShown(false); + } + + // Scientific notation settings + if (positive.exponentZeros > 0) { + properties.setExponentSignAlwaysShown(positive.exponentHasPlusSign); + properties.setMinimumExponentDigits(positive.exponentZeros); + if (positive.integerAtSigns == 0) { + // patterns without '@' can define max integer digits, used for engineering notation + properties.setMinimumIntegerDigits(positive.integerNumerals); + properties.setMaximumIntegerDigits(positive.integerTotal); + } else { + // patterns with '@' cannot define max integer digits + properties.setMinimumIntegerDigits(1); + properties.setMaximumIntegerDigits(-1); + } + } else { + properties.setExponentSignAlwaysShown(false); + properties.setMinimumExponentDigits(-1); + properties.setMinimumIntegerDigits(minInt); + properties.setMaximumIntegerDigits(-1); + } + + // Compute the affix patterns (required for both padding and affixes) + String posPrefix = patternInfo.getString(AffixPatternProvider.Flags.PREFIX); + String posSuffix = patternInfo.getString(0); + + // Padding settings + if (positive.paddingEndpoints != 0) { + // The width of the positive prefix and suffix templates are included in the padding + int paddingWidth = positive.widthExceptAffixes + AffixUtils.estimateLength(posPrefix) + + AffixUtils.estimateLength(posSuffix); + properties.setFormatWidth(paddingWidth); + String rawPaddingString = patternInfo.getString(AffixPatternProvider.Flags.PADDING); + if (rawPaddingString.length() == 1) { + properties.setPadString(rawPaddingString); + } else if (rawPaddingString.length() == 2) { + if (rawPaddingString.charAt(0) == '\'') { + properties.setPadString("'"); + } else { + properties.setPadString(rawPaddingString); + } + } else { + properties.setPadString(rawPaddingString.substring(1, rawPaddingString.length() - 1)); + } + assert positive.paddingLocation != null; + properties.setPadPosition(positive.paddingLocation); + } else { + properties.setFormatWidth(-1); + properties.setPadString(null); + properties.setPadPosition(null); + } + + // Set the affixes + // Always call the setter, even if the prefixes are empty, especially in the case of the + // negative prefix pattern, to prevent default values from overriding the pattern. + properties.setPositivePrefixPattern(posPrefix); + properties.setPositiveSuffixPattern(posSuffix); + if (negative != null) { + properties.setNegativePrefixPattern(patternInfo + .getString(AffixPatternProvider.Flags.NEGATIVE_SUBPATTERN | AffixPatternProvider.Flags.PREFIX)); + properties.setNegativeSuffixPattern(patternInfo.getString(AffixPatternProvider.Flags.NEGATIVE_SUBPATTERN)); + } else { + properties.setNegativePrefixPattern(null); + properties.setNegativeSuffixPattern(null); + } + + // Set the magnitude multiplier + if (positive.hasPercentSign) { + properties.setMagnitudeMultiplier(2); + } else if (positive.hasPerMilleSign) { + properties.setMagnitudeMultiplier(3); + } else { + properties.setMagnitudeMultiplier(0); + } + } } diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/PatternAndPropertyUtils.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/PatternStringUtils.java similarity index 56% rename from icu4j/main/classes/core/src/com/ibm/icu/impl/number/PatternAndPropertyUtils.java rename to icu4j/main/classes/core/src/com/ibm/icu/impl/number/PatternStringUtils.java index 06a0dd12563..d1420418736 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/PatternAndPropertyUtils.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/PatternStringUtils.java @@ -4,67 +4,15 @@ package com.ibm.icu.impl.number; import java.math.BigDecimal; -import com.ibm.icu.impl.number.PatternParser.ParsedPatternInfo; -import com.ibm.icu.impl.number.PatternParser.ParsedSubpatternInfo; import com.ibm.icu.text.DecimalFormatSymbols; -import newapi.impl.AffixPatternProvider; import newapi.impl.Padder; import newapi.impl.Padder.PadPosition; /** - * Handles parsing and creation of the compact pattern string representation of a decimal format. + * Assorted utilities relating to decimal formatting pattern strings. */ -public class PatternAndPropertyUtils { - - /** - * Parses a pattern string into a new property bag. - * - * @param pattern - * The pattern string, like "#,##0.00" - * @param ignoreRounding - * Whether to leave out rounding information (minFrac, maxFrac, and rounding increment) when parsing the - * pattern. This may be desirable if a custom rounding mode, such as CurrencyUsage, is to be used - * instead. One of {@link #IGNORE_ROUNDING_ALWAYS}, {@link #IGNORE_ROUNDING_IF_CURRENCY}, or - * {@link #IGNORE_ROUNDING_NEVER}. - * @return A property bag object. - * @throws IllegalArgumentException - * If there is a syntax error in the pattern string. - */ - public static Properties parseToProperties(String pattern, int ignoreRounding) { - Properties properties = new Properties(); - parse(pattern, properties, ignoreRounding); - return properties; - } - - public static Properties parseToProperties(String pattern) { - return parseToProperties(pattern, PatternAndPropertyUtils.IGNORE_ROUNDING_NEVER); - } - - /** - * Parses a pattern string into an existing property bag. All properties that can be encoded into a pattern string - * will be overwritten with either their default value or with the value coming from the pattern string. Properties - * that cannot be encoded into a pattern string, such as rounding mode, are not modified. - * - * @param pattern - * The pattern string, like "#,##0.00" - * @param properties - * The property bag object to overwrite. - * @param ignoreRounding - * Whether to leave out rounding information (minFrac, maxFrac, and rounding increment) when parsing the - * pattern. This may be desirable if a custom rounding mode, such as CurrencyUsage, is to be used - * instead. One of {@link #IGNORE_ROUNDING_ALWAYS}, {@link #IGNORE_ROUNDING_IF_CURRENCY}, or - * {@link #IGNORE_ROUNDING_NEVER}. - * @throws IllegalArgumentException - * If there was a syntax error in the pattern string. - */ - public static void parseToExistingProperties(String pattern, Properties properties, int ignoreRounding) { - parse(pattern, properties, ignoreRounding); - } - - public static void parseToExistingProperties(String pattern, Properties properties) { - parseToExistingProperties(pattern, properties, PatternAndPropertyUtils.IGNORE_ROUNDING_NEVER); - } +public class PatternStringUtils { /** * Creates a pattern string from a property bag. @@ -77,7 +25,7 @@ public class PatternAndPropertyUtils { * The property bag to serialize. * @return A pattern string approximately serializing the property bag. */ - public static String propertiesToString(Properties properties) { + public static String propertiesToPatternString(DecimalFormatProperties properties) { StringBuilder sb = new StringBuilder(); // Convenience references @@ -109,7 +57,7 @@ public class PatternAndPropertyUtils { // Prefixes if (ppp != null) sb.append(ppp); - AffixPatternUtils.escape(pp, sb); + AffixUtils.escape(pp, sb); int afterPrefixPos = sb.length(); // Figure out the grouping sizes. @@ -201,7 +149,7 @@ public class PatternAndPropertyUtils { int beforeSuffixPos = sb.length(); if (psp != null) sb.append(psp); - AffixPatternUtils.escape(ps, sb); + AffixUtils.escape(ps, sb); // Resolve Padding if (paddingWidth != -1) { @@ -212,24 +160,24 @@ public class PatternAndPropertyUtils { int addedLength; switch (paddingLocation) { case BEFORE_PREFIX: - addedLength = escapePaddingString(paddingString, sb, 0); + addedLength = PatternStringUtils.escapePaddingString(paddingString, sb, 0); sb.insert(0, '*'); afterPrefixPos += addedLength + 1; beforeSuffixPos += addedLength + 1; break; case AFTER_PREFIX: - addedLength = escapePaddingString(paddingString, sb, afterPrefixPos); + addedLength = PatternStringUtils.escapePaddingString(paddingString, sb, afterPrefixPos); sb.insert(afterPrefixPos, '*'); afterPrefixPos += addedLength + 1; beforeSuffixPos += addedLength + 1; break; case BEFORE_SUFFIX: - escapePaddingString(paddingString, sb, beforeSuffixPos); + PatternStringUtils.escapePaddingString(paddingString, sb, beforeSuffixPos); sb.insert(beforeSuffixPos, '*'); break; case AFTER_SUFFIX: sb.append('*'); - escapePaddingString(paddingString, sb, sb.length()); + PatternStringUtils.escapePaddingString(paddingString, sb, sb.length()); break; } } @@ -241,13 +189,13 @@ public class PatternAndPropertyUtils { sb.append(';'); if (npp != null) sb.append(npp); - AffixPatternUtils.escape(np, sb); + AffixUtils.escape(np, sb); // Copy the positive digit format into the negative. // This is optional; the pattern is the same as if '#' were appended here instead. sb.append(sb, afterPrefixPos, beforeSuffixPos); if (nsp != null) sb.append(nsp); - AffixPatternUtils.escape(ns, sb); + AffixUtils.escape(ns, sb); } return sb.toString(); @@ -296,6 +244,9 @@ public class PatternAndPropertyUtils { *

* Locale symbols are not allowed to contain the ASCII quote character. * + *

+ * This method is provided for backwards compatibility and should not be used in any new code. + * * @param input * The pattern to convert. * @param symbols @@ -304,9 +255,7 @@ public class PatternAndPropertyUtils { * true to convert from standard to localized notation; false to convert from localized to standard * notation. * @return The pattern expressed in the other notation. - * @deprecated ICU 59 This method is provided for backwards compatibility and should not be used in any new code. */ - @Deprecated public static String convertLocalized(String input, DecimalFormatSymbols symbols, boolean toLocalized) { if (input == null) return null; @@ -441,184 +390,4 @@ public class PatternAndPropertyUtils { return result.toString(); } - public static final int IGNORE_ROUNDING_NEVER = 0; - public static final int IGNORE_ROUNDING_IF_CURRENCY = 1; - public static final int IGNORE_ROUNDING_ALWAYS = 2; - - static void parse(String pattern, Properties properties, int ignoreRounding) { - if (pattern == null || pattern.length() == 0) { - // Backwards compatibility requires that we reset to the default values. - // TODO: Only overwrite the properties that "saveToProperties" normally touches? - properties.clear(); - return; - } - - // TODO: Use thread locals here? - ParsedPatternInfo patternInfo = PatternParser.parse(pattern); - saveToProperties(properties, patternInfo, ignoreRounding); - } - - /** Finalizes the temporary data stored in the ParsedPatternInfo to the Properties. */ - private static void saveToProperties(Properties properties, ParsedPatternInfo patternInfo, int _ignoreRounding) { - // Translate from PatternParseResult to Properties. - // Note that most data from "negative" is ignored per the specification of DecimalFormat. - - ParsedSubpatternInfo positive = patternInfo.positive; - ParsedSubpatternInfo negative = patternInfo.negative; - - boolean ignoreRounding; - if (_ignoreRounding == IGNORE_ROUNDING_NEVER) { - ignoreRounding = false; - } else if (_ignoreRounding == IGNORE_ROUNDING_IF_CURRENCY) { - ignoreRounding = positive.hasCurrencySign; - } else { - assert _ignoreRounding == IGNORE_ROUNDING_ALWAYS; - ignoreRounding = true; - } - - // Grouping settings - short grouping1 = (short) (positive.groupingSizes & 0xffff); - short grouping2 = (short) ((positive.groupingSizes >>> 16) & 0xffff); - short grouping3 = (short) ((positive.groupingSizes >>> 32) & 0xffff); - if (grouping2 != -1) { - properties.setGroupingSize(grouping1); - } else { - properties.setGroupingSize(-1); - } - if (grouping3 != -1) { - properties.setSecondaryGroupingSize(grouping2); - } else { - properties.setSecondaryGroupingSize(-1); - } - - // For backwards compatibility, require that the pattern emit at least one min digit. - int minInt, minFrac; - if (positive.integerTotal == 0 && positive.fractionTotal > 0) { - // patterns like ".##" - minInt = 0; - minFrac = Math.max(1, positive.fractionNumerals); - } else if (positive.integerNumerals == 0 && positive.fractionNumerals == 0) { - // patterns like "#.##" - minInt = 1; - minFrac = 0; - } else { - minInt = positive.integerNumerals; - minFrac = positive.fractionNumerals; - } - - // Rounding settings - // Don't set basic rounding when there is a currency sign; defer to CurrencyUsage - if (positive.integerAtSigns > 0) { - properties.setMinimumFractionDigits(-1); - properties.setMaximumFractionDigits(-1); - properties.setRoundingIncrement(null); - properties.setMinimumSignificantDigits(positive.integerAtSigns); - properties.setMaximumSignificantDigits(positive.integerAtSigns + positive.integerTrailingHashSigns); - } else if (positive.rounding != null) { - if (!ignoreRounding) { - properties.setMinimumFractionDigits(minFrac); - properties.setMaximumFractionDigits(positive.fractionTotal); - properties.setRoundingIncrement( - positive.rounding.toBigDecimal().setScale(positive.fractionNumerals)); - } else { - properties.setMinimumFractionDigits(-1); - properties.setMaximumFractionDigits(-1); - properties.setRoundingIncrement(null); - } - properties.setMinimumSignificantDigits(-1); - properties.setMaximumSignificantDigits(-1); - } else { - if (!ignoreRounding) { - properties.setMinimumFractionDigits(minFrac); - properties.setMaximumFractionDigits(positive.fractionTotal); - properties.setRoundingIncrement(null); - } else { - properties.setMinimumFractionDigits(-1); - properties.setMaximumFractionDigits(-1); - properties.setRoundingIncrement(null); - } - properties.setMinimumSignificantDigits(-1); - properties.setMaximumSignificantDigits(-1); - } - - // If the pattern ends with a '.' then force the decimal point. - if (positive.hasDecimal && positive.fractionTotal == 0) { - properties.setDecimalSeparatorAlwaysShown(true); - } else { - properties.setDecimalSeparatorAlwaysShown(false); - } - - // Scientific notation settings - if (positive.exponentZeros > 0) { - properties.setExponentSignAlwaysShown(positive.exponentHasPlusSign); - properties.setMinimumExponentDigits(positive.exponentZeros); - if (positive.integerAtSigns == 0) { - // patterns without '@' can define max integer digits, used for engineering notation - properties.setMinimumIntegerDigits(positive.integerNumerals); - properties.setMaximumIntegerDigits(positive.integerTotal); - } else { - // patterns with '@' cannot define max integer digits - properties.setMinimumIntegerDigits(1); - properties.setMaximumIntegerDigits(-1); - } - } else { - properties.setExponentSignAlwaysShown(false); - properties.setMinimumExponentDigits(-1); - properties.setMinimumIntegerDigits(minInt); - properties.setMaximumIntegerDigits(-1); - } - - // Compute the affix patterns (required for both padding and affixes) - String posPrefix = patternInfo.getString(AffixPatternProvider.Flags.PREFIX); - String posSuffix = patternInfo.getString(0); - - // Padding settings - if (positive.paddingEndpoints != 0) { - // The width of the positive prefix and suffix templates are included in the padding - int paddingWidth = positive.widthExceptAffixes + AffixPatternUtils.estimateLength(posPrefix) - + AffixPatternUtils.estimateLength(posSuffix); - properties.setFormatWidth(paddingWidth); - String rawPaddingString = patternInfo.getString(AffixPatternProvider.Flags.PADDING); - if (rawPaddingString.length() == 1) { - properties.setPadString(rawPaddingString); - } else if (rawPaddingString.length() == 2) { - if (rawPaddingString.charAt(0) == '\'') { - properties.setPadString("'"); - } else { - properties.setPadString(rawPaddingString); - } - } else { - properties.setPadString(rawPaddingString.substring(1, rawPaddingString.length() - 1)); - } - assert positive.paddingLocation != null; - properties.setPadPosition(positive.paddingLocation); - } else { - properties.setFormatWidth(-1); - properties.setPadString(null); - properties.setPadPosition(null); - } - - // Set the affixes - // Always call the setter, even if the prefixes are empty, especially in the case of the - // negative prefix pattern, to prevent default values from overriding the pattern. - properties.setPositivePrefixPattern(posPrefix); - properties.setPositiveSuffixPattern(posSuffix); - if (negative != null) { - properties.setNegativePrefixPattern(patternInfo - .getString(AffixPatternProvider.Flags.NEGATIVE_SUBPATTERN | AffixPatternProvider.Flags.PREFIX)); - properties.setNegativeSuffixPattern(patternInfo.getString(AffixPatternProvider.Flags.NEGATIVE_SUBPATTERN)); - } else { - properties.setNegativePrefixPattern(null); - properties.setNegativeSuffixPattern(null); - } - - // Set the magnitude multiplier - if (positive.hasPercentSign) { - properties.setMagnitudeMultiplier(2); - } else if (positive.hasPerMilleSign) { - properties.setMagnitudeMultiplier(3); - } else { - properties.setMagnitudeMultiplier(0); - } - } } diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/RoundingUtils.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/RoundingUtils.java index 7aa15eb5f42..e07c6e8c1a7 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/impl/number/RoundingUtils.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/number/RoundingUtils.java @@ -133,7 +133,7 @@ public class RoundingUtils { * @param properties The property bag. * @return A {@link MathContext}. Never null. */ - public static MathContext getMathContextOrUnlimited(Properties properties) { + public static MathContext getMathContextOrUnlimited(DecimalFormatProperties properties) { MathContext mathContext = properties.getMathContext(); if (mathContext == null) { RoundingMode roundingMode = properties.getRoundingMode(); @@ -151,7 +151,7 @@ public class RoundingUtils { * @param properties The property bag. * @return A {@link MathContext}. Never null. */ - public static MathContext getMathContextOr34Digits(Properties properties) { + public static MathContext getMathContextOr34Digits(DecimalFormatProperties properties) { MathContext mathContext = properties.getMathContext(); if (mathContext == null) { RoundingMode roundingMode = properties.getRoundingMode(); diff --git a/icu4j/main/classes/core/src/com/ibm/icu/text/CompactDecimalFormat.java b/icu4j/main/classes/core/src/com/ibm/icu/text/CompactDecimalFormat.java index 3442c0ebc0f..0a643cd7d96 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/text/CompactDecimalFormat.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/text/CompactDecimalFormat.java @@ -12,7 +12,7 @@ package com.ibm.icu.text; import java.text.ParsePosition; import java.util.Locale; -import com.ibm.icu.impl.number.Properties; +import com.ibm.icu.impl.number.DecimalFormatProperties; import com.ibm.icu.util.CurrencyAmount; import com.ibm.icu.util.ULocale; @@ -122,11 +122,11 @@ public class CompactDecimalFormat extends DecimalFormat { CompactDecimalFormat(ULocale locale, CompactStyle style) { // Minimal properties: let the non-shim code path do most of the logic for us. symbols = DecimalFormatSymbols.getInstance(locale); - properties = new Properties(); + properties = new DecimalFormatProperties(); properties.setCompactStyle(style); properties.setGroupingSize(-2); // do not forward grouping information properties.setMinimumGroupingDigits(2); - exportedProperties = new Properties(); + exportedProperties = new DecimalFormatProperties(); refreshFormatter(); } diff --git a/icu4j/main/classes/core/src/com/ibm/icu/text/DecimalFormat.java b/icu4j/main/classes/core/src/com/ibm/icu/text/DecimalFormat.java index d84fdbe0f75..63e20a93f02 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/text/DecimalFormat.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/text/DecimalFormat.java @@ -13,10 +13,11 @@ import java.text.FieldPosition; import java.text.ParseException; import java.text.ParsePosition; -import com.ibm.icu.impl.number.AffixPatternUtils; +import com.ibm.icu.impl.number.AffixUtils; +import com.ibm.icu.impl.number.DecimalFormatProperties; import com.ibm.icu.impl.number.Parse; -import com.ibm.icu.impl.number.PatternAndPropertyUtils; -import com.ibm.icu.impl.number.Properties; +import com.ibm.icu.impl.number.PatternStringParser; +import com.ibm.icu.impl.number.PatternStringUtils; import com.ibm.icu.lang.UCharacter; import com.ibm.icu.math.BigDecimal; import com.ibm.icu.math.MathContext; @@ -30,8 +31,6 @@ import com.ibm.icu.util.ULocale.Category; import newapi.FormattedNumber; import newapi.LocalizedNumberFormatter; import newapi.NumberFormatter; -import newapi.NumberPropertyMapper; -import newapi.impl.MacroProps; import newapi.impl.Padder.PadPosition; /** @@ -252,7 +251,7 @@ public class DecimalFormat extends NumberFormat { * In principle this should be final, but serialize and clone won't work if it is final. Does not * need to be volatile because the reference never changes. */ - /* final */ transient Properties properties; + /* final */ transient DecimalFormatProperties properties; /** * The symbols for the current locale. Volatile because threads may read and write at the same @@ -271,7 +270,7 @@ public class DecimalFormat extends NumberFormat { * The effective properties as exported from the formatter object. Volatile because threads may * read and write at the same time. */ - transient volatile Properties exportedProperties; + transient volatile DecimalFormatProperties exportedProperties; //=====================================================================================// // CONSTRUCTORS // @@ -298,10 +297,10 @@ public class DecimalFormat extends NumberFormat { ULocale def = ULocale.getDefault(ULocale.Category.FORMAT); String pattern = getPattern(def, NumberFormat.NUMBERSTYLE); symbols = getDefaultSymbols(); - properties = new Properties(); - exportedProperties = new Properties(); + properties = new DecimalFormatProperties(); + exportedProperties = new DecimalFormatProperties(); // Regression: ignore pattern rounding information if the pattern has currency symbols. - setPropertiesFromPattern(pattern, PatternAndPropertyUtils.IGNORE_ROUNDING_IF_CURRENCY); + setPropertiesFromPattern(pattern, PatternStringParser.IGNORE_ROUNDING_IF_CURRENCY); refreshFormatter(); } @@ -327,10 +326,10 @@ public class DecimalFormat extends NumberFormat { */ public DecimalFormat(String pattern) { symbols = getDefaultSymbols(); - properties = new Properties(); - exportedProperties = new Properties(); + properties = new DecimalFormatProperties(); + exportedProperties = new DecimalFormatProperties(); // Regression: ignore pattern rounding information if the pattern has currency symbols. - setPropertiesFromPattern(pattern, PatternAndPropertyUtils.IGNORE_ROUNDING_IF_CURRENCY); + setPropertiesFromPattern(pattern, PatternStringParser.IGNORE_ROUNDING_IF_CURRENCY); refreshFormatter(); } @@ -356,10 +355,10 @@ public class DecimalFormat extends NumberFormat { */ public DecimalFormat(String pattern, DecimalFormatSymbols symbols) { this.symbols = (DecimalFormatSymbols) symbols.clone(); - properties = new Properties(); - exportedProperties = new Properties(); + properties = new DecimalFormatProperties(); + exportedProperties = new DecimalFormatProperties(); // Regression: ignore pattern rounding information if the pattern has currency symbols. - setPropertiesFromPattern(pattern, PatternAndPropertyUtils.IGNORE_ROUNDING_IF_CURRENCY); + setPropertiesFromPattern(pattern, PatternStringParser.IGNORE_ROUNDING_IF_CURRENCY); refreshFormatter(); } @@ -393,8 +392,8 @@ public class DecimalFormat extends NumberFormat { /** Package-private constructor used by NumberFormat. */ DecimalFormat(String pattern, DecimalFormatSymbols symbols, int choice) { this.symbols = (DecimalFormatSymbols) symbols.clone(); - properties = new Properties(); - exportedProperties = new Properties(); + properties = new DecimalFormatProperties(); + exportedProperties = new DecimalFormatProperties(); // If choice is a currency type, ignore the rounding information. if (choice == CURRENCYSTYLE || choice == ISOCURRENCYSTYLE @@ -402,9 +401,9 @@ public class DecimalFormat extends NumberFormat { || choice == CASHCURRENCYSTYLE || choice == STANDARDCURRENCYSTYLE || choice == PLURALCURRENCYSTYLE) { - setPropertiesFromPattern(pattern, PatternAndPropertyUtils.IGNORE_ROUNDING_ALWAYS); + setPropertiesFromPattern(pattern, PatternStringParser.IGNORE_ROUNDING_ALWAYS); } else { - setPropertiesFromPattern(pattern, PatternAndPropertyUtils.IGNORE_ROUNDING_IF_CURRENCY); + setPropertiesFromPattern(pattern, PatternStringParser.IGNORE_ROUNDING_IF_CURRENCY); } refreshFormatter(); } @@ -445,7 +444,7 @@ public class DecimalFormat extends NumberFormat { * @stable ICU 2.0 */ public synchronized void applyPattern(String pattern) { - setPropertiesFromPattern(pattern, PatternAndPropertyUtils.IGNORE_ROUNDING_NEVER); + setPropertiesFromPattern(pattern, PatternStringParser.IGNORE_ROUNDING_NEVER); // Backwards compatibility: clear out user-specified prefix and suffix, // as well as CurrencyPluralInfo. properties.setPositivePrefix(null); @@ -469,7 +468,7 @@ public class DecimalFormat extends NumberFormat { * @stable ICU 2.0 */ public synchronized void applyLocalizedPattern(String localizedPattern) { - String pattern = PatternAndPropertyUtils.convertLocalized(localizedPattern, symbols, false); + String pattern = PatternStringUtils.convertLocalized(localizedPattern, symbols, false); applyPattern(pattern); } @@ -483,7 +482,7 @@ public class DecimalFormat extends NumberFormat { DecimalFormat other = (DecimalFormat) super.clone(); other.symbols = (DecimalFormatSymbols) symbols.clone(); other.properties = properties.clone(); - other.exportedProperties = new Properties(); + other.exportedProperties = new DecimalFormatProperties(); other.refreshFormatter(); return other; } @@ -525,15 +524,15 @@ public class DecimalFormat extends NumberFormat { // Extra int for possible future use: ois.readInt(); // 1) Property Bag - properties = (Properties) ois.readObject(); + properties = (DecimalFormatProperties) ois.readObject(); // 2) DecimalFormatSymbols symbols = (DecimalFormatSymbols) ois.readObject(); // Re-build transient fields - exportedProperties = new Properties(); + exportedProperties = new DecimalFormatProperties(); refreshFormatter(); } else { ///// LEGACY SERIALIZATION FORMAT ///// - properties = new Properties(); + properties = new DecimalFormatProperties(); // Loop through the fields. Not all fields necessarily exist in the serialization. String pp = null, ppp = null, ps = null, psp = null; String np = null, npp = null, ns = null, nsp = null; @@ -667,7 +666,7 @@ public class DecimalFormat extends NumberFormat { if (symbols == null) { symbols = getDefaultSymbols(); } - exportedProperties = new Properties(); + exportedProperties = new DecimalFormatProperties(); refreshFormatter(); } } @@ -775,7 +774,7 @@ public class DecimalFormat extends NumberFormat { */ @Override public Number parse(String text, ParsePosition parsePosition) { - Properties pprops = threadLocalProperties.get(); + DecimalFormatProperties pprops = threadLocalProperties.get(); synchronized (this) { pprops.copyFrom(properties); } @@ -796,7 +795,7 @@ public class DecimalFormat extends NumberFormat { @Override public CurrencyAmount parseCurrency(CharSequence text, ParsePosition parsePosition) { try { - Properties pprops = threadLocalProperties.get(); + DecimalFormatProperties pprops = threadLocalProperties.get(); synchronized (this) { pprops.copyFrom(properties); } @@ -2377,13 +2376,13 @@ public class DecimalFormat extends NumberFormat { // to keep affix patterns intact. In particular, pull rounding properties // so that CurrencyUsage is reflected properly. // TODO: Consider putting this logic in PatternString.java instead. - Properties tprops = threadLocalProperties.get().copyFrom(properties); + DecimalFormatProperties tprops = threadLocalProperties.get().copyFrom(properties); if (useCurrency(properties)) { tprops.setMinimumFractionDigits(exportedProperties.getMinimumFractionDigits()); tprops.setMaximumFractionDigits(exportedProperties.getMaximumFractionDigits()); tprops.setRoundingIncrement(exportedProperties.getRoundingIncrement()); } - return PatternAndPropertyUtils.propertiesToString(tprops); + return PatternStringUtils.propertiesToPatternString(tprops); } /** @@ -2396,7 +2395,7 @@ public class DecimalFormat extends NumberFormat { */ public synchronized String toLocalizedPattern() { String pattern = toPattern(); - return PatternAndPropertyUtils.convertLocalized(pattern, symbols, true); + return PatternStringUtils.convertLocalized(pattern, symbols, true); } /** @@ -2422,11 +2421,11 @@ public class DecimalFormat extends NumberFormat { return formatter.format(number).getFixedDecimal(); } - private static final ThreadLocal threadLocalProperties = - new ThreadLocal() { + private static final ThreadLocal threadLocalProperties = + new ThreadLocal() { @Override - protected Properties initialValue() { - return new Properties(); + protected DecimalFormatProperties initialValue() { + return new DecimalFormatProperties(); } }; @@ -2437,7 +2436,6 @@ public class DecimalFormat extends NumberFormat { // The only time when this happens is during legacy deserialization. return; } - MacroProps macros = NumberPropertyMapper.oldToNew(properties, symbols, exportedProperties); ULocale locale = this.getLocale(ULocale.ACTUAL_LOCALE); if (locale == null) { // Constructor @@ -2448,7 +2446,7 @@ public class DecimalFormat extends NumberFormat { locale = symbols.getULocale(); } assert locale != null; - formatter = NumberFormatter.with().macros(macros).locale(locale); + formatter = NumberFormatter.fromDecimalFormat(properties, symbols, exportedProperties).locale(locale); } /** @@ -2478,14 +2476,14 @@ public class DecimalFormat extends NumberFormat { * Returns true if the currency is set in The property bag or if currency symbols are present in * the prefix/suffix pattern. */ - private static boolean useCurrency(Properties properties) { + private static boolean useCurrency(DecimalFormatProperties properties) { return ((properties.getCurrency() != null) || properties.getCurrencyPluralInfo() != null || properties.getCurrencyUsage() != null - || AffixPatternUtils.hasCurrencySymbols(properties.getPositivePrefixPattern()) - || AffixPatternUtils.hasCurrencySymbols(properties.getPositiveSuffixPattern()) - || AffixPatternUtils.hasCurrencySymbols(properties.getNegativePrefixPattern()) - || AffixPatternUtils.hasCurrencySymbols(properties.getNegativeSuffixPattern())); + || AffixUtils.hasCurrencySymbols(properties.getPositivePrefixPattern()) + || AffixUtils.hasCurrencySymbols(properties.getPositiveSuffixPattern()) + || AffixUtils.hasCurrencySymbols(properties.getNegativePrefixPattern()) + || AffixUtils.hasCurrencySymbols(properties.getNegativeSuffixPattern())); } /** @@ -2495,15 +2493,15 @@ public class DecimalFormat extends NumberFormat { * @param ignoreRounding Whether to leave out rounding information (minFrac, maxFrac, and rounding * increment) when parsing the pattern. This may be desirable if a custom rounding mode, such * as CurrencyUsage, is to be used instead. One of {@link - * PatternAndPropertyUtils#IGNORE_ROUNDING_ALWAYS}, {@link PatternAndPropertyUtils#IGNORE_ROUNDING_IF_CURRENCY}, - * or {@link PatternAndPropertyUtils#IGNORE_ROUNDING_NEVER}. + * PatternStringParser#IGNORE_ROUNDING_ALWAYS}, {@link PatternStringParser#IGNORE_ROUNDING_IF_CURRENCY}, + * or {@link PatternStringParser#IGNORE_ROUNDING_NEVER}. * @see PatternAndPropertyUtils#parseToExistingProperties */ void setPropertiesFromPattern(String pattern, int ignoreRounding) { if (pattern == null) { throw new NullPointerException(); } - PatternAndPropertyUtils.parseToExistingProperties(pattern, properties, ignoreRounding); + PatternStringParser.parseToExistingProperties(pattern, properties, ignoreRounding); } /** @@ -2527,7 +2525,7 @@ public class DecimalFormat extends NumberFormat { * @deprecated This API is ICU internal only. */ @Deprecated - public void set(Properties props); + public void set(DecimalFormatProperties props); } /** diff --git a/icu4j/main/classes/core/src/com/ibm/icu/text/NFSubstitution.java b/icu4j/main/classes/core/src/com/ibm/icu/text/NFSubstitution.java index 24a0dce1856..909bbb64282 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/text/NFSubstitution.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/text/NFSubstitution.java @@ -10,7 +10,7 @@ package com.ibm.icu.text; import java.text.ParsePosition; -import com.ibm.icu.impl.number.FormatQuantity4; +import com.ibm.icu.impl.number.DecimalQuantity_DualStorageBCD; //=================================================================== // NFSubstitution (abstract base class) @@ -1241,7 +1241,7 @@ class FractionalPartSubstitution extends NFSubstitution { // (this is slower, but more accurate, than doing it from the // other end) - FormatQuantity4 fq = new FormatQuantity4(number); + DecimalQuantity_DualStorageBCD fq = new DecimalQuantity_DualStorageBCD(number); fq.roundToInfinity(); // ensure doubles are resolved using slow path boolean pad = false; @@ -1316,7 +1316,7 @@ class FractionalPartSubstitution extends NFSubstitution { double result; int digit; - FormatQuantity4 fq = new FormatQuantity4(); + DecimalQuantity_DualStorageBCD fq = new DecimalQuantity_DualStorageBCD(); int leadingZeros = 0; while (workText.length() > 0 && workPos.getIndex() != 0) { workPos.setIndex(0); diff --git a/icu4j/main/classes/core/src/newapi/CompactNotation.java b/icu4j/main/classes/core/src/newapi/CompactNotation.java index e0830ec91da..17aa57b369e 100644 --- a/icu4j/main/classes/core/src/newapi/CompactNotation.java +++ b/icu4j/main/classes/core/src/newapi/CompactNotation.java @@ -7,18 +7,19 @@ import java.util.Map; import java.util.Set; import com.ibm.icu.impl.StandardPlural; -import com.ibm.icu.impl.number.FormatQuantity; -import com.ibm.icu.impl.number.PatternParser; -import com.ibm.icu.impl.number.PatternParser.ParsedPatternInfo; +import com.ibm.icu.impl.number.DecimalQuantity; +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.CompactDecimalFormat.CompactType; import com.ibm.icu.text.PluralRules; import com.ibm.icu.util.ULocale; -import newapi.MutablePatternModifier.ImmutableMurkyModifier; import newapi.impl.CompactData; import newapi.impl.MicroProps; import newapi.impl.MicroPropsGenerator; +import newapi.impl.MutablePatternModifier; +import newapi.impl.MutablePatternModifier.ImmutableMurkyModifier; public class CompactNotation extends Notation { @@ -78,7 +79,7 @@ public class CompactNotation extends Notation { Set allPatterns = data.getAllPatterns(); for (String patternString : allPatterns) { CompactModInfo info = new CompactModInfo(); - ParsedPatternInfo patternInfo = PatternParser.parse(patternString); + ParsedPatternInfo patternInfo = PatternStringParser.parseToPatternInfo(patternString); buildReference.setPatternInfo(patternInfo); info.mod = buildReference.createImmutable(); info.numDigits = patternInfo.positive.integerTotal; @@ -88,7 +89,7 @@ public class CompactNotation extends Notation { } @Override - public MicroProps processQuantity(FormatQuantity input) { + public MicroProps processQuantity(DecimalQuantity input) { MicroProps micros = parent.processQuantity(input); assert micros.rounding != null; @@ -119,7 +120,7 @@ public class CompactNotation extends Notation { // Unsafe code path. // Overwrite the PatternInfo in the existing modMiddle assert micros.modMiddle instanceof MutablePatternModifier; - ParsedPatternInfo patternInfo = PatternParser.parse(patternString); + ParsedPatternInfo patternInfo = PatternStringParser.parseToPatternInfo(patternString); ((MutablePatternModifier) micros.modMiddle).setPatternInfo(patternInfo); numDigits = patternInfo.positive.integerTotal; } diff --git a/icu4j/main/classes/core/src/newapi/CurrencyRounder.java b/icu4j/main/classes/core/src/newapi/CurrencyRounder.java index 631084e9a3d..0749dcc4080 100644 --- a/icu4j/main/classes/core/src/newapi/CurrencyRounder.java +++ b/icu4j/main/classes/core/src/newapi/CurrencyRounder.java @@ -20,7 +20,7 @@ public abstract class CurrencyRounder extends Rounder { * *

* Calling this method is not required, because the currency specified in - * {@link NumberFormatter#unit(MeasureUnit)} or via a {@link CurrencyAmount} passed into + * {@link NumberFormatterSettings#unit(MeasureUnit)} or via a {@link CurrencyAmount} passed into * {@link LocalizedNumberFormatter#format(Measure)} is automatically applied to currency rounding strategies. * However, this method enables you to override that automatic association. * diff --git a/icu4j/main/classes/core/src/newapi/FormattedNumber.java b/icu4j/main/classes/core/src/newapi/FormattedNumber.java index 310086c0490..682f88cb655 100644 --- a/icu4j/main/classes/core/src/newapi/FormattedNumber.java +++ b/icu4j/main/classes/core/src/newapi/FormattedNumber.java @@ -8,7 +8,7 @@ import java.text.AttributedCharacterIterator; import java.text.FieldPosition; import java.util.Arrays; -import com.ibm.icu.impl.number.FormatQuantity; +import com.ibm.icu.impl.number.DecimalQuantity; import com.ibm.icu.impl.number.NumberStringBuilder; import com.ibm.icu.text.PluralRules.IFixedDecimal; import com.ibm.icu.util.ICUUncheckedIOException; @@ -17,10 +17,10 @@ import newapi.impl.MicroProps; public class FormattedNumber { NumberStringBuilder nsb; - FormatQuantity fq; + DecimalQuantity fq; MicroProps micros; - FormattedNumber(NumberStringBuilder nsb, FormatQuantity fq, MicroProps micros) { + FormattedNumber(NumberStringBuilder nsb, DecimalQuantity fq, MicroProps micros) { this.nsb = nsb; this.fq = fq; this.micros = micros; diff --git a/icu4j/main/classes/core/src/newapi/Grouper.java b/icu4j/main/classes/core/src/newapi/Grouper.java index e4aeadc712b..296dbc3cb24 100644 --- a/icu4j/main/classes/core/src/newapi/Grouper.java +++ b/icu4j/main/classes/core/src/newapi/Grouper.java @@ -2,8 +2,8 @@ // License & terms of use: http://www.unicode.org/copyright.html#License package newapi; -import com.ibm.icu.impl.number.FormatQuantity; -import com.ibm.icu.impl.number.PatternParser.ParsedPatternInfo; +import com.ibm.icu.impl.number.DecimalQuantity; +import com.ibm.icu.impl.number.PatternStringParser.ParsedPatternInfo; public class Grouper { @@ -85,7 +85,7 @@ public class Grouper { return getInstance(grouping1, grouping2, min2); } - boolean groupAtPosition(int position, FormatQuantity value) { + boolean groupAtPosition(int position, DecimalQuantity value) { assert grouping1 != -2; if (grouping1 == -1 || grouping1 == 0) { // Either -1 or 0 means "no grouping" diff --git a/icu4j/main/classes/core/src/newapi/LocalizedNumberFormatter.java b/icu4j/main/classes/core/src/newapi/LocalizedNumberFormatter.java index 9152360fbff..cd0956f13ba 100644 --- a/icu4j/main/classes/core/src/newapi/LocalizedNumberFormatter.java +++ b/icu4j/main/classes/core/src/newapi/LocalizedNumberFormatter.java @@ -5,8 +5,8 @@ package newapi; import java.util.Objects; import java.util.concurrent.atomic.AtomicLongFieldUpdater; -import com.ibm.icu.impl.number.FormatQuantity; -import com.ibm.icu.impl.number.FormatQuantity4; +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.util.Measure; import com.ibm.icu.util.MeasureUnit; @@ -21,22 +21,22 @@ public class LocalizedNumberFormatter extends NumberFormatterSettings parent, int key, Object value) { super(parent, key, value); } public FormattedNumber format(long input) { - return format(new FormatQuantity4(input)); + return format(new DecimalQuantity_DualStorageBCD(input)); } public FormattedNumber format(double input) { - return format(new FormatQuantity4(input)); + return format(new DecimalQuantity_DualStorageBCD(input)); } public FormattedNumber format(Number input) { - return format(new FormatQuantity4(input)); + return format(new DecimalQuantity_DualStorageBCD(input)); } public FormattedNumber format(Measure input) { @@ -68,18 +68,18 @@ public class LocalizedNumberFormatter extends NumberFormatterSettings + * This class, as well as NumberPropertyMapper, could go into the impl package, but they depend on too many + * package-private members of the public APIs. + */ +class NumberFormatterImpl { - public static Worker1 fromMacros(MacroProps macros) { + public static NumberFormatterImpl fromMacros(MacroProps macros) { // Build a "safe" MicroPropsGenerator, which is thread-safe and can be used repeatedly. MicroPropsGenerator microPropsGenerator = macrosToMicroGenerator(macros, true); - return new Worker1(microPropsGenerator); + return new NumberFormatterImpl(microPropsGenerator); } - public static MicroProps applyStatic(MacroProps macros, FormatQuantity inValue, NumberStringBuilder outString) { + public static MicroProps applyStatic(MacroProps macros, DecimalQuantity inValue, NumberStringBuilder outString) { // Build an "unsafe" MicroPropsGenerator, which is cheaper but can be used only once. MicroPropsGenerator microPropsGenerator = macrosToMicroGenerator(macros, false); MicroProps micros = microPropsGenerator.processQuantity(inValue); @@ -45,11 +55,11 @@ public class Worker1 { final MicroPropsGenerator microPropsGenerator; - private Worker1(MicroPropsGenerator microsGenerator) { + private NumberFormatterImpl(MicroPropsGenerator microsGenerator) { this.microPropsGenerator = microsGenerator; } - public MicroProps apply(FormatQuantity inValue, NumberStringBuilder outString) { + public MicroProps apply(DecimalQuantity inValue, NumberStringBuilder outString) { MicroProps micros = microPropsGenerator.processQuantity(inValue); microsToString(micros, inValue, outString); return micros; @@ -75,7 +85,7 @@ public class Worker1 { String innerPattern = null; LongNameHandler longNames = null; - Rounder defaultRounding = Rounder.none(); + Rounder defaultRounding = Rounder.unlimited(); Currency currency = DEFAULT_CURRENCY; UnitWidth unitWidth = null; boolean perMille = false; @@ -131,7 +141,7 @@ public class Worker1 { } // Parse the pattern, which is used for grouping and affixes only. - ParsedPatternInfo patternInfo = PatternParser.parse(innerPattern); + ParsedPatternInfo patternInfo = PatternStringParser.parseToPatternInfo(innerPattern); // Symbols if (macros.symbols == null) { @@ -242,16 +252,16 @@ public class Worker1 { ////////// /** - * Synthesizes the output string from a MicroProps and FormatQuantity. + * Synthesizes the output string from a MicroProps and DecimalQuantity. * * @param micros * The MicroProps after the quantity has been consumed. Will not be mutated. * @param quantity - * The FormatQuantity to be rendered. May be mutated. + * The DecimalQuantity to be rendered. May be mutated. * @param string * The output string. Will be mutated. */ - private static void microsToString(MicroProps micros, FormatQuantity quantity, NumberStringBuilder string) { + private static void microsToString(MicroProps micros, DecimalQuantity quantity, NumberStringBuilder string) { quantity.adjustMagnitude(micros.multiplier); micros.rounding.apply(quantity); if (micros.integerWidth.maxInt == -1) { @@ -265,7 +275,7 @@ public class Worker1 { length += micros.padding.applyModsAndMaybePad(micros, string, 0, length); } - private static int writeNumber(MicroProps micros, FormatQuantity quantity, NumberStringBuilder string) { + private static int writeNumber(MicroProps micros, DecimalQuantity quantity, NumberStringBuilder string) { int length = 0; if (quantity.isInfinite()) { length += string.insert(length, micros.symbols.getInfinity(), NumberFormat.Field.INTEGER); @@ -290,7 +300,7 @@ public class Worker1 { return length; } - private static int writeIntegerDigits(MicroProps micros, FormatQuantity quantity, NumberStringBuilder string) { + private static int writeIntegerDigits(MicroProps micros, DecimalQuantity quantity, NumberStringBuilder string) { int length = 0; int integerCount = quantity.getUpperDisplayMagnitude() + 1; for (int i = 0; i < integerCount; i++) { @@ -313,7 +323,7 @@ public class Worker1 { return length; } - private static int writeFractionDigits(MicroProps micros, FormatQuantity quantity, NumberStringBuilder string) { + private static int writeFractionDigits(MicroProps micros, DecimalQuantity quantity, NumberStringBuilder string) { int length = 0; int fractionCount = -quantity.getLowerDisplayMagnitude(); for (int i = 0; i < fractionCount; i++) { diff --git a/icu4j/main/classes/core/src/newapi/NumberFormatterSettings.java b/icu4j/main/classes/core/src/newapi/NumberFormatterSettings.java index c370b2436b6..c81e610eec2 100644 --- a/icu4j/main/classes/core/src/newapi/NumberFormatterSettings.java +++ b/icu4j/main/classes/core/src/newapi/NumberFormatterSettings.java @@ -377,6 +377,7 @@ public abstract class NumberFormatterSettings current = this; while (current != null) { diff --git a/icu4j/main/classes/core/src/newapi/NumberPropertyMapper.java b/icu4j/main/classes/core/src/newapi/NumberPropertyMapper.java index c273cac446d..943d7c9e4de 100644 --- a/icu4j/main/classes/core/src/newapi/NumberPropertyMapper.java +++ b/icu4j/main/classes/core/src/newapi/NumberPropertyMapper.java @@ -6,11 +6,10 @@ import java.math.BigDecimal; import java.math.MathContext; import com.ibm.icu.impl.StandardPlural; -import com.ibm.icu.impl.number.AffixPatternUtils; -import com.ibm.icu.impl.number.PatternAndPropertyUtils; -import com.ibm.icu.impl.number.PatternParser; -import com.ibm.icu.impl.number.PatternParser.ParsedPatternInfo; -import com.ibm.icu.impl.number.Properties; +import com.ibm.icu.impl.number.AffixUtils; +import com.ibm.icu.impl.number.DecimalFormatProperties; +import com.ibm.icu.impl.number.PatternStringParser; +import com.ibm.icu.impl.number.PatternStringParser.ParsedPatternInfo; import com.ibm.icu.impl.number.RoundingUtils; import com.ibm.icu.text.CompactDecimalFormat.CompactStyle; import com.ibm.icu.text.CurrencyPluralInfo; @@ -30,11 +29,15 @@ import newapi.impl.MacroProps; import newapi.impl.MultiplierImpl; import newapi.impl.Padder; -/** @author sffc */ -public final class NumberPropertyMapper { +/** + *

+ * This class, as well as NumberFormatterImpl, could go into the impl package, but they depend on too many + * package-private members of the public APIs. + */ +final class NumberPropertyMapper { /** Convenience method to create a NumberFormatter directly from Properties. */ - public static UnlocalizedNumberFormatter create(Properties properties, DecimalFormatSymbols symbols) { + public static UnlocalizedNumberFormatter create(DecimalFormatProperties properties, DecimalFormatSymbols symbols) { MacroProps macros = oldToNew(properties, symbols, null); return NumberFormatter.with().macros(macros); } @@ -44,14 +47,14 @@ public final class NumberPropertyMapper { * public API if there is demand. */ public static UnlocalizedNumberFormatter create(String pattern, DecimalFormatSymbols symbols) { - Properties properties = PatternAndPropertyUtils.parseToProperties(pattern); + DecimalFormatProperties properties = PatternStringParser.parseToProperties(pattern); return create(properties, symbols); } /** - * Creates a new {@link MacroProps} object based on the content of a {@link Properties} object. In other words, maps - * Properties to MacroProps. This function is used by the JDK-compatibility API to call into the ICU 60 fluent - * number formatting pipeline. + * Creates a new {@link MacroProps} object based on the content of a {@link DecimalFormatProperties} object. In + * other words, maps Properties to MacroProps. This function is used by the JDK-compatibility API to call into the + * ICU 60 fluent number formatting pipeline. * * @param properties * The property bag to be mapped. @@ -61,8 +64,8 @@ public final class NumberPropertyMapper { * A property bag in which to store validated properties. * @return A new MacroProps containing all of the information in the Properties. */ - public static MacroProps oldToNew(Properties properties, DecimalFormatSymbols symbols, - Properties exportedProperties) { + public static MacroProps oldToNew(DecimalFormatProperties properties, DecimalFormatSymbols symbols, + DecimalFormatProperties exportedProperties) { MacroProps macros = new MacroProps(); ULocale locale = symbols.getULocale(); @@ -85,13 +88,13 @@ public final class NumberPropertyMapper { AffixPatternProvider affixProvider; if (properties.getCurrencyPluralInfo() == null) { affixProvider = new PropertiesAffixPatternProvider( - properties.getPositivePrefix() != null ? AffixPatternUtils.escape(properties.getPositivePrefix()) + properties.getPositivePrefix() != null ? AffixUtils.escape(properties.getPositivePrefix()) : properties.getPositivePrefixPattern(), - properties.getPositiveSuffix() != null ? AffixPatternUtils.escape(properties.getPositiveSuffix()) + properties.getPositiveSuffix() != null ? AffixUtils.escape(properties.getPositiveSuffix()) : properties.getPositiveSuffixPattern(), - properties.getNegativePrefix() != null ? AffixPatternUtils.escape(properties.getNegativePrefix()) + properties.getNegativePrefix() != null ? AffixUtils.escape(properties.getNegativePrefix()) : properties.getNegativePrefixPattern(), - properties.getNegativeSuffix() != null ? AffixPatternUtils.escape(properties.getNegativeSuffix()) + properties.getNegativeSuffix() != null ? AffixUtils.escape(properties.getNegativeSuffix()) : properties.getNegativeSuffixPattern()); } else { affixProvider = new CurrencyPluralInfoAffixProvider(properties.getCurrencyPluralInfo()); @@ -371,8 +374,8 @@ public final class NumberPropertyMapper { @Override public boolean positiveHasPlusSign() { - return AffixPatternUtils.containsType(posPrefixPattern, AffixPatternUtils.TYPE_PLUS_SIGN) - || AffixPatternUtils.containsType(posSuffixPattern, AffixPatternUtils.TYPE_PLUS_SIGN); + return AffixUtils.containsType(posPrefixPattern, AffixUtils.TYPE_PLUS_SIGN) + || AffixUtils.containsType(posSuffixPattern, AffixUtils.TYPE_PLUS_SIGN); } @Override @@ -382,24 +385,22 @@ public final class NumberPropertyMapper { @Override public boolean negativeHasMinusSign() { - return AffixPatternUtils.containsType(negPrefixPattern, AffixPatternUtils.TYPE_MINUS_SIGN) - || AffixPatternUtils.containsType(negSuffixPattern, AffixPatternUtils.TYPE_MINUS_SIGN); + return AffixUtils.containsType(negPrefixPattern, AffixUtils.TYPE_MINUS_SIGN) + || AffixUtils.containsType(negSuffixPattern, AffixUtils.TYPE_MINUS_SIGN); } @Override public boolean hasCurrencySign() { - return AffixPatternUtils.hasCurrencySymbols(posPrefixPattern) - || AffixPatternUtils.hasCurrencySymbols(posSuffixPattern) - || AffixPatternUtils.hasCurrencySymbols(negPrefixPattern) - || AffixPatternUtils.hasCurrencySymbols(negSuffixPattern); + return AffixUtils.hasCurrencySymbols(posPrefixPattern) || AffixUtils.hasCurrencySymbols(posSuffixPattern) + || AffixUtils.hasCurrencySymbols(negPrefixPattern) + || AffixUtils.hasCurrencySymbols(negSuffixPattern); } @Override public boolean containsSymbolType(int type) { - return AffixPatternUtils.containsType(posPrefixPattern, type) - || AffixPatternUtils.containsType(posSuffixPattern, type) - || AffixPatternUtils.containsType(negPrefixPattern, type) - || AffixPatternUtils.containsType(negSuffixPattern, type); + return AffixUtils.containsType(posPrefixPattern, type) || AffixUtils.containsType(posSuffixPattern, type) + || AffixUtils.containsType(negPrefixPattern, type) + || AffixUtils.containsType(negSuffixPattern, type); } } @@ -409,8 +410,8 @@ public final class NumberPropertyMapper { public CurrencyPluralInfoAffixProvider(CurrencyPluralInfo cpi) { affixesByPlural = new ParsedPatternInfo[StandardPlural.COUNT]; for (StandardPlural plural : StandardPlural.VALUES) { - affixesByPlural[plural.ordinal()] = PatternParser - .parse(cpi.getCurrencyPluralPattern(plural.getKeyword())); + affixesByPlural[plural.ordinal()] = PatternStringParser + .parseToPatternInfo(cpi.getCurrencyPluralPattern(plural.getKeyword())); } } diff --git a/icu4j/main/classes/core/src/newapi/Rounder.java b/icu4j/main/classes/core/src/newapi/Rounder.java index 37ad2e1c1f0..a21776fbd91 100644 --- a/icu4j/main/classes/core/src/newapi/Rounder.java +++ b/icu4j/main/classes/core/src/newapi/Rounder.java @@ -6,7 +6,7 @@ import java.math.BigDecimal; import java.math.MathContext; import java.math.RoundingMode; -import com.ibm.icu.impl.number.FormatQuantity; +import com.ibm.icu.impl.number.DecimalQuantity; import com.ibm.icu.impl.number.RoundingUtils; import com.ibm.icu.util.Currency; import com.ibm.icu.util.Currency.CurrencyUsage; @@ -25,14 +25,55 @@ public abstract class Rounder implements Cloneable { mathContext = RoundingUtils.mathContextUnlimited(RoundingMode.HALF_EVEN); } - public static Rounder none() { + /** + * Show all available digits to full precision. + * + *

+ * NOTE: If you are formatting doubles and you know that the number of fraction places or + * significant digits is bounded, consider using {@link #maxFraction} or {@link #maxDigits} instead to maximize + * performance. + * + * @return A rounding strategy for {@link NumberFormatterSettings#rounding}. + */ + public static Rounder unlimited() { return constructInfinite(); } + /** + * Show numbers rounded if necessary to the nearest integer. + * + * @return A rounding strategy for {@link NumberFormatterSettings#rounding}. + */ public static FractionRounder integer() { return constructFraction(0, 0); } + /** + * Show numbers rounded if necessary to a certain number of fraction places (digits after the decimal mark). + * Additionally, pad with zeros to ensure that this number digits are always shown. + * + *

+ * Example output with minMaxFractionDigits = 3: + * + *

+ * 87,650.000
+ * 8,765.000
+ * 876.500
+ * 87.650
+ * 8.765
+ * 0.876
+ * 0.088
+ * 0.009
+ * 0.000 (zero) + * + *

+ * This method is equivalent to {@link #minMaxFraction} with both arguments equal. + * + * @param minMaxFractionDigits + * The minimum and maximum number of digits to display after the decimal mark (rounding if too long or + * padding with zeros if too short). + * @return A rounding strategy for {@link NumberFormatterSettings#rounding}. + */ public static FractionRounder fixedFraction(int minMaxFractionDigits) { if (minMaxFractionDigits >= 0 && minMaxFractionDigits <= MAX_VALUE) { return constructFraction(minMaxFractionDigits, minMaxFractionDigits); @@ -41,6 +82,18 @@ public abstract class Rounder implements Cloneable { } } + /** + * Always show a certain number of digits after the decimal mark, padding with zeros if necessary. Do not perform + * rounding (display numbers to their full precision). + * + *

+ * NOTE: If you are formatting doubles and you know that the number of fraction places is + * bounded, consider using {@link #fixedFraction} or {@link #minMaxFraction} instead to maximize performance. + * + * @param minFractionDigits + * The minimum number of digits to display after the decimal mark (padding with zeros if necessary). + * @return A rounding strategy for {@link NumberFormatterSettings#rounding}. + */ public static FractionRounder minFraction(int minFractionDigits) { if (minFractionDigits >= 0 && minFractionDigits < MAX_VALUE) { return constructFraction(minFractionDigits, -1); @@ -49,6 +102,14 @@ public abstract class Rounder implements Cloneable { } } + /** + * Show numbers rounded if necessary to a certain number of fraction places (digits after the decimal mark). Unlike + * the other fraction rounding strategies, this strategy does not pad zeros to the end of the number. + * + * @param maxFractionDigits + * The maximum number of digits to display after the decimal mark (rounding if necessary). + * @return A rounding strategy for {@link NumberFormatterSettings#rounding}. + */ public static FractionRounder maxFraction(int maxFractionDigits) { if (maxFractionDigits >= 0 && maxFractionDigits < MAX_VALUE) { return constructFraction(0, maxFractionDigits); @@ -57,6 +118,16 @@ public abstract class Rounder implements Cloneable { } } + /** + * Show numbers rounded if necessary to a certain number of fraction places (digits after the decimal mark); in + * addition, always show a certain number of digits after the decimal mark, padding with zeros if necessary. + * + * @param minFractionDigits + * The minimum number of digits to display after the decimal mark (padding with zeros if necessary). + * @param maxFractionDigits + * The maximum number of digits to display after the decimal mark (rounding if necessary). + * @return A rounding strategy for {@link NumberFormatterSettings#rounding}. + */ public static FractionRounder minMaxFraction(int minFractionDigits, int maxFractionDigits) { if (minFractionDigits >= 0 && maxFractionDigits <= MAX_VALUE && minFractionDigits <= maxFractionDigits) { return constructFraction(minFractionDigits, maxFractionDigits); @@ -90,7 +161,8 @@ public abstract class Rounder implements Cloneable { } public static Rounder minMaxDigits(int minSignificantDigits, int maxSignificantDigits) { - if (minSignificantDigits > 0 && maxSignificantDigits <= MAX_VALUE && minSignificantDigits <= maxSignificantDigits) { + if (minSignificantDigits > 0 && maxSignificantDigits <= MAX_VALUE + && minSignificantDigits <= maxSignificantDigits) { return constructSignificant(minSignificantDigits, maxSignificantDigits); } else { throw new IllegalArgumentException("Significant digits must be between 0 and " + MAX_VALUE); @@ -154,6 +226,13 @@ public abstract class Rounder implements Cloneable { } } + /** + * @internal + * @deprecated ICU 60 This API is ICU internal only. + */ + @Deprecated + public abstract void apply(DecimalQuantity value); + ////////////////////////// // PACKAGE-PRIVATE APIS // ////////////////////////// @@ -266,12 +345,10 @@ public abstract class Rounder implements Cloneable { } } - abstract void apply(FormatQuantity value); - - int chooseMultiplierAndApply(FormatQuantity input, MultiplierProducer producer) { + int chooseMultiplierAndApply(DecimalQuantity input, MultiplierProducer producer) { // TODO: Make a better and more efficient implementation. // TODO: Avoid the object creation here. - FormatQuantity copy = input.createCopy(); + DecimalQuantity copy = input.createCopy(); assert !input.isZero(); int magnitude = input.getMagnitude(); @@ -299,11 +376,11 @@ public abstract class Rounder implements Cloneable { static class InfiniteRounderImpl extends Rounder { - private InfiniteRounderImpl() { + public InfiniteRounderImpl() { } @Override - void apply(FormatQuantity value) { + public void apply(DecimalQuantity value) { value.roundToInfinity(); value.setFractionLength(0, Integer.MAX_VALUE); } @@ -313,13 +390,13 @@ public abstract class Rounder implements Cloneable { final int minFrac; final int maxFrac; - private FractionRounderImpl(int minFrac, int maxFrac) { + public FractionRounderImpl(int minFrac, int maxFrac) { this.minFrac = minFrac; this.maxFrac = maxFrac; } @Override - void apply(FormatQuantity value) { + public void apply(DecimalQuantity value) { value.roundToMagnitude(getRoundingMagnitudeFraction(maxFrac), mathContext); value.setFractionLength(Math.max(0, -getDisplayMagnitudeFraction(minFrac)), Integer.MAX_VALUE); } @@ -329,19 +406,19 @@ public abstract class Rounder implements Cloneable { final int minSig; final int maxSig; - private SignificantRounderImpl(int minSig, int maxSig) { + public SignificantRounderImpl(int minSig, int maxSig) { this.minSig = minSig; this.maxSig = maxSig; } @Override - void apply(FormatQuantity value) { + public void apply(DecimalQuantity value) { value.roundToMagnitude(getRoundingMagnitudeSignificant(value, maxSig), mathContext); value.setFractionLength(Math.max(0, -getDisplayMagnitudeSignificant(value, minSig)), Integer.MAX_VALUE); } /** Version of {@link #apply} that obeys minInt constraints. Used for scientific notation compatibility mode. */ - public void apply(FormatQuantity quantity, int minInt) { + public void apply(DecimalQuantity quantity, int minInt) { assert quantity.isZero(); quantity.setFractionLength(minSig - minInt, Integer.MAX_VALUE); } @@ -353,7 +430,7 @@ public abstract class Rounder implements Cloneable { final int minSig; final int maxSig; - private FracSigRounderImpl(int minFrac, int maxFrac, int minSig, int maxSig) { + public FracSigRounderImpl(int minFrac, int maxFrac, int minSig, int maxSig) { this.minFrac = minFrac; this.maxFrac = maxFrac; this.minSig = minSig; @@ -361,7 +438,7 @@ public abstract class Rounder implements Cloneable { } @Override - void apply(FormatQuantity value) { + public void apply(DecimalQuantity value) { int displayMag = getDisplayMagnitudeFraction(minFrac); int roundingMag = getRoundingMagnitudeFraction(maxFrac); if (minSig == -1) { @@ -381,12 +458,12 @@ public abstract class Rounder implements Cloneable { static class IncrementRounderImpl extends Rounder { final BigDecimal increment; - private IncrementRounderImpl(BigDecimal increment) { + public IncrementRounderImpl(BigDecimal increment) { this.increment = increment; } @Override - void apply(FormatQuantity value) { + public void apply(DecimalQuantity value) { value.roundToIncrement(increment, mathContext); value.setFractionLength(increment.scale(), increment.scale()); } @@ -395,12 +472,12 @@ public abstract class Rounder implements Cloneable { static class CurrencyRounderImpl extends CurrencyRounder { final CurrencyUsage usage; - private CurrencyRounderImpl(CurrencyUsage usage) { + public CurrencyRounderImpl(CurrencyUsage usage) { this.usage = usage; } @Override - void apply(FormatQuantity value) { + public void apply(DecimalQuantity value) { // Call .withCurrency() before .apply()! throw new AssertionError(); } @@ -408,11 +485,11 @@ public abstract class Rounder implements Cloneable { static class PassThroughRounderImpl extends Rounder { - private PassThroughRounderImpl() { + public PassThroughRounderImpl() { } @Override - void apply(FormatQuantity value) { + public void apply(DecimalQuantity value) { // TODO: Assert that value has already been rounded } } @@ -424,7 +501,7 @@ public abstract class Rounder implements Cloneable { return -maxFrac; } - private static int getRoundingMagnitudeSignificant(FormatQuantity value, int maxSig) { + private static int getRoundingMagnitudeSignificant(DecimalQuantity value, int maxSig) { if (maxSig == -1) { return Integer.MIN_VALUE; } @@ -439,7 +516,7 @@ public abstract class Rounder implements Cloneable { return -minFrac; } - private static int getDisplayMagnitudeSignificant(FormatQuantity value, int minSig) { + private static int getDisplayMagnitudeSignificant(DecimalQuantity value, int minSig) { int magnitude = value.isZero() ? 0 : value.getMagnitude(); return magnitude - minSig + 1; } diff --git a/icu4j/main/classes/core/src/newapi/ScientificNotation.java b/icu4j/main/classes/core/src/newapi/ScientificNotation.java index 3ac73e293ea..8ba2b4b3fb2 100644 --- a/icu4j/main/classes/core/src/newapi/ScientificNotation.java +++ b/icu4j/main/classes/core/src/newapi/ScientificNotation.java @@ -2,7 +2,7 @@ // License & terms of use: http://www.unicode.org/copyright.html#License package newapi; -import com.ibm.icu.impl.number.FormatQuantity; +import com.ibm.icu.impl.number.DecimalQuantity; import com.ibm.icu.impl.number.Modifier; import com.ibm.icu.impl.number.NumberStringBuilder; import com.ibm.icu.text.DecimalFormatSymbols; @@ -84,7 +84,7 @@ public class ScientificNotation extends Notation implements Cloneable { } @Override - public MicroProps processQuantity(FormatQuantity quantity) { + public MicroProps processQuantity(DecimalQuantity quantity) { MicroProps micros = parent.processQuantity(quantity); assert micros.rounding != null; diff --git a/icu4j/main/classes/core/src/newapi/LongNameHandler.java b/icu4j/main/classes/core/src/newapi/impl/LongNameHandler.java similarity index 92% rename from icu4j/main/classes/core/src/newapi/LongNameHandler.java rename to icu4j/main/classes/core/src/newapi/impl/LongNameHandler.java index 222c6f1f8c9..cae21f72498 100644 --- a/icu4j/main/classes/core/src/newapi/LongNameHandler.java +++ b/icu4j/main/classes/core/src/newapi/impl/LongNameHandler.java @@ -1,6 +1,6 @@ // © 2017 and later: Unicode, Inc. and others. // License & terms of use: http://www.unicode.org/copyright.html#License -package newapi; +package newapi.impl; import java.util.EnumMap; import java.util.Map; @@ -8,7 +8,7 @@ import java.util.Map; import com.ibm.icu.impl.CurrencyData; import com.ibm.icu.impl.SimpleFormatterImpl; import com.ibm.icu.impl.StandardPlural; -import com.ibm.icu.impl.number.FormatQuantity; +import com.ibm.icu.impl.number.DecimalQuantity; import com.ibm.icu.impl.number.Modifier; import com.ibm.icu.impl.number.modifiers.SimpleModifier; import com.ibm.icu.text.NumberFormat.Field; @@ -18,11 +18,8 @@ import com.ibm.icu.util.MeasureUnit; import com.ibm.icu.util.ULocale; import newapi.NumberFormatter.UnitWidth; -import newapi.impl.MeasureData; -import newapi.impl.MicroProps; -import newapi.impl.MicroPropsGenerator; -class LongNameHandler implements MicroPropsGenerator { +public class LongNameHandler implements MicroPropsGenerator { private final Map data; /* unsafe */ PluralRules rules; @@ -98,10 +95,10 @@ class LongNameHandler implements MicroPropsGenerator { } @Override - public MicroProps processQuantity(FormatQuantity quantity) { + public MicroProps processQuantity(DecimalQuantity quantity) { MicroProps micros = parent.processQuantity(quantity); // TODO: Avoid the copy here? - FormatQuantity copy = quantity.createCopy(); + DecimalQuantity copy = quantity.createCopy(); micros.rounding.apply(copy); micros.modOuter = data.get(copy.getStandardPlural(rules)); return micros; diff --git a/icu4j/main/classes/core/src/newapi/impl/MicroProps.java b/icu4j/main/classes/core/src/newapi/impl/MicroProps.java index 3c9d9262cc9..82c6541f442 100644 --- a/icu4j/main/classes/core/src/newapi/impl/MicroProps.java +++ b/icu4j/main/classes/core/src/newapi/impl/MicroProps.java @@ -2,59 +2,64 @@ // License & terms of use: http://www.unicode.org/copyright.html#License package newapi.impl; -import com.ibm.icu.impl.number.FormatQuantity; +import com.ibm.icu.impl.number.DecimalQuantity; import com.ibm.icu.impl.number.Modifier; import com.ibm.icu.text.DecimalFormatSymbols; import newapi.Grouper; import newapi.IntegerWidth; -import newapi.NumberFormatter; -import newapi.Rounder; import newapi.NumberFormatter.DecimalMarkDisplay; import newapi.NumberFormatter.SignDisplay; +import newapi.Rounder; public class MicroProps implements Cloneable, MicroPropsGenerator { - // Populated globally: - public SignDisplay sign; - public DecimalFormatSymbols symbols; - public Padder padding; - public DecimalMarkDisplay decimal; - public IntegerWidth integerWidth; + // Populated globally: + public SignDisplay sign; + public DecimalFormatSymbols symbols; + public Padder padding; + public DecimalMarkDisplay decimal; + public IntegerWidth integerWidth; - // Populated by notation/unit: - public Modifier modOuter; - public Modifier modMiddle; - public Modifier modInner; - public Rounder rounding; - public Grouper grouping; - public int multiplier; - public boolean useCurrency; + // Populated by notation/unit: + public Modifier modOuter; + public Modifier modMiddle; + public Modifier modInner; + public Rounder rounding; + public Grouper grouping; + public int multiplier; + public boolean useCurrency; - private final boolean immutable; + private final boolean immutable; + private volatile boolean exhausted; - /** - * @param immutable Whether this MicroProps should behave as an immutable after construction with - * respect to the quantity chain. - */ - public MicroProps(boolean immutable) { - this.immutable = immutable; - } - - @Override - public MicroProps processQuantity(FormatQuantity quantity) { - if (immutable) { - return (MicroProps) this.clone(); - } else { - return this; + /** + * @param immutable + * Whether this MicroProps should behave as an immutable after construction with respect to the quantity + * chain. + */ + public MicroProps(boolean immutable) { + this.immutable = immutable; } - } - @Override - public Object clone() { - try { - return super.clone(); - } catch (CloneNotSupportedException e) { - throw new AssertionError(e); + @Override + public MicroProps processQuantity(DecimalQuantity quantity) { + if (immutable) { + return (MicroProps) this.clone(); + } else if (exhausted) { + // Safety check + throw new AssertionError("Cannot re-use a mutable MicroProps in the quantity chain"); + } else { + exhausted = true; + return this; + } + } + + @Override + public Object clone() { + try { + return super.clone(); + } catch (CloneNotSupportedException e) { + throw new AssertionError(e); + } } - } } diff --git a/icu4j/main/classes/core/src/newapi/impl/MicroPropsGenerator.java b/icu4j/main/classes/core/src/newapi/impl/MicroPropsGenerator.java index 41822b077ea..72620e7f5ae 100644 --- a/icu4j/main/classes/core/src/newapi/impl/MicroPropsGenerator.java +++ b/icu4j/main/classes/core/src/newapi/impl/MicroPropsGenerator.java @@ -2,7 +2,7 @@ // License & terms of use: http://www.unicode.org/copyright.html#License package newapi.impl; -import com.ibm.icu.impl.number.FormatQuantity; +import com.ibm.icu.impl.number.DecimalQuantity; /** * This interface is used when all number formatting settings, including the locale, are known, except for the quantity @@ -31,7 +31,7 @@ import com.ibm.icu.impl.number.FormatQuantity; * } * * @Override - * public MicroProps processQuantity(FormatQuantity quantity) { + * public MicroProps processQuantity(DecimalQuantity quantity) { * MicroProps micros = this.parent.processQuantity(quantity); * // Perform manipulations on micros and/or quantity * return micros; @@ -44,11 +44,11 @@ import com.ibm.icu.impl.number.FormatQuantity; */ public interface MicroPropsGenerator { /** - * Considers the given {@link FormatQuantity}, optionally mutates it, and returns a {@link MicroProps}. + * Considers the given {@link DecimalQuantity}, optionally mutates it, and returns a {@link MicroProps}. * * @param quantity * The quantity for consideration and optional mutation. * @return A MicroProps instance resolved for the quantity. */ - public MicroProps processQuantity(FormatQuantity quantity); + public MicroProps processQuantity(DecimalQuantity quantity); } \ No newline at end of file diff --git a/icu4j/main/classes/core/src/newapi/impl/MultiplierImpl.java b/icu4j/main/classes/core/src/newapi/impl/MultiplierImpl.java index 40dcffa292a..1ef44e2b887 100644 --- a/icu4j/main/classes/core/src/newapi/impl/MultiplierImpl.java +++ b/icu4j/main/classes/core/src/newapi/impl/MultiplierImpl.java @@ -4,7 +4,7 @@ package newapi.impl; import java.math.BigDecimal; -import com.ibm.icu.impl.number.FormatQuantity; +import com.ibm.icu.impl.number.DecimalQuantity; public class MultiplierImpl implements MicroPropsGenerator, Cloneable { final int magnitudeMultiplier; @@ -34,7 +34,7 @@ public class MultiplierImpl implements MicroPropsGenerator, Cloneable { } @Override - public MicroProps processQuantity(FormatQuantity quantity) { + public MicroProps processQuantity(DecimalQuantity quantity) { MicroProps micros = parent.processQuantity(quantity); quantity.adjustMagnitude(magnitudeMultiplier); if (bigDecimalMultiplier != null) { diff --git a/icu4j/main/classes/core/src/newapi/MutablePatternModifier.java b/icu4j/main/classes/core/src/newapi/impl/MutablePatternModifier.java similarity index 90% rename from icu4j/main/classes/core/src/newapi/MutablePatternModifier.java rename to icu4j/main/classes/core/src/newapi/impl/MutablePatternModifier.java index f730b0bdeb2..abd7cedf4db 100644 --- a/icu4j/main/classes/core/src/newapi/MutablePatternModifier.java +++ b/icu4j/main/classes/core/src/newapi/impl/MutablePatternModifier.java @@ -1,12 +1,12 @@ // © 2017 and later: Unicode, Inc. and others. // License & terms of use: http://www.unicode.org/copyright.html#License -package newapi; +package newapi.impl; import com.ibm.icu.impl.StandardPlural; -import com.ibm.icu.impl.number.AffixPatternUtils; -import com.ibm.icu.impl.number.AffixPatternUtils.SymbolProvider; -import com.ibm.icu.impl.number.FormatQuantity; -import com.ibm.icu.impl.number.PatternParser; +import com.ibm.icu.impl.number.AffixUtils; +import com.ibm.icu.impl.number.AffixUtils.SymbolProvider; +import com.ibm.icu.impl.number.DecimalQuantity; +import com.ibm.icu.impl.number.PatternStringParser; import com.ibm.icu.impl.number.Modifier; import com.ibm.icu.impl.number.NumberStringBuilder; import com.ibm.icu.impl.number.modifiers.ConstantMultiFieldModifier; @@ -15,11 +15,9 @@ import com.ibm.icu.text.DecimalFormatSymbols; import com.ibm.icu.text.PluralRules; import com.ibm.icu.util.Currency; +import newapi.NumberFormatter; import newapi.NumberFormatter.SignDisplay; import newapi.NumberFormatter.UnitWidth; -import newapi.impl.AffixPatternProvider; -import newapi.impl.MicroProps; -import newapi.impl.MicroPropsGenerator; /** * This class is a {@link Modifier} that wraps a decimal format pattern. It applies the pattern's affixes in @@ -86,7 +84,7 @@ public class MutablePatternModifier implements Modifier, SymbolProvider, CharSeq /** * Sets a reference to the parsed decimal format pattern, usually obtained from - * {@link PatternParser#parse(String)}, but any implementation of {@link AffixPatternProvider} is accepted. + * {@link PatternStringParser#parseToPatternInfo(String)}, but any implementation of {@link AffixPatternProvider} is accepted. */ public void setPatternInfo(AffixPatternProvider patternInfo) { this.patternInfo = patternInfo; @@ -157,7 +155,7 @@ public class MutablePatternModifier implements Modifier, SymbolProvider, CharSeq * This is currently true only if there is a currency long name placeholder in the pattern ("¤¤¤"). */ public boolean needsPlurals() { - return patternInfo.containsSymbolType(AffixPatternUtils.TYPE_CURRENCY_TRIPLE); + return patternInfo.containsSymbolType(AffixUtils.TYPE_CURRENCY_TRIPLE); } /** @@ -219,7 +217,7 @@ public class MutablePatternModifier implements Modifier, SymbolProvider, CharSeq } public static interface ImmutableMurkyModifier extends MicroPropsGenerator { - public void applyToMicros(MicroProps micros, FormatQuantity quantity); + public void applyToMicros(MicroProps micros, DecimalQuantity quantity); } public static class ImmutableMurkyModifierWithoutPlurals implements ImmutableMurkyModifier { @@ -234,7 +232,7 @@ public class MutablePatternModifier implements Modifier, SymbolProvider, CharSeq } @Override - public MicroProps processQuantity(FormatQuantity quantity) { + public MicroProps processQuantity(DecimalQuantity quantity) { assert parent != null; MicroProps micros = parent.processQuantity(quantity); applyToMicros(micros, quantity); @@ -242,7 +240,7 @@ public class MutablePatternModifier implements Modifier, SymbolProvider, CharSeq } @Override - public void applyToMicros(MicroProps micros, FormatQuantity quantity) { + public void applyToMicros(MicroProps micros, DecimalQuantity quantity) { if (quantity.isNegative()) { micros.modMiddle = negative; } else { @@ -273,7 +271,7 @@ public class MutablePatternModifier implements Modifier, SymbolProvider, CharSeq } @Override - public MicroProps processQuantity(FormatQuantity quantity) { + public MicroProps processQuantity(DecimalQuantity quantity) { assert parent != null; MicroProps micros = parent.processQuantity(quantity); applyToMicros(micros, quantity); @@ -281,9 +279,9 @@ public class MutablePatternModifier implements Modifier, SymbolProvider, CharSeq } @Override - public void applyToMicros(MicroProps micros, FormatQuantity quantity) { + public void applyToMicros(MicroProps micros, DecimalQuantity quantity) { // TODO: Fix this. Avoid the copy. - FormatQuantity copy = quantity.createCopy(); + DecimalQuantity copy = quantity.createCopy(); copy.roundToInfinity(); StandardPlural plural = copy.getStandardPlural(rules); Modifier mod = mods[getModIndex(quantity.isNegative(), plural)]; @@ -297,11 +295,11 @@ public class MutablePatternModifier implements Modifier, SymbolProvider, CharSeq } @Override - public MicroProps processQuantity(FormatQuantity fq) { + public MicroProps processQuantity(DecimalQuantity fq) { MicroProps micros = parent.processQuantity(fq); if (needsPlurals()) { // TODO: Fix this. Avoid the copy. - FormatQuantity copy = fq.createCopy(); + DecimalQuantity copy = fq.createCopy(); micros.rounding.apply(copy); setNumberProperties(fq.isNegative(), copy.getStandardPlural(rules)); } else { @@ -333,14 +331,14 @@ public class MutablePatternModifier implements Modifier, SymbolProvider, CharSeq private int insertPrefix(NumberStringBuilder sb, int position) { enterCharSequenceMode(true); - int length = AffixPatternUtils.unescape(this, sb, position, this); + int length = AffixUtils.unescape(this, sb, position, this); exitCharSequenceMode(); return length; } private int insertSuffix(NumberStringBuilder sb, int position) { enterCharSequenceMode(false); - int length = AffixPatternUtils.unescape(this, sb, position, this); + int length = AffixUtils.unescape(this, sb, position, this); exitCharSequenceMode(); return length; } @@ -348,24 +346,24 @@ public class MutablePatternModifier implements Modifier, SymbolProvider, CharSeq @Override public CharSequence getSymbol(int type) { switch (type) { - case AffixPatternUtils.TYPE_MINUS_SIGN: + case AffixUtils.TYPE_MINUS_SIGN: return symbols.getMinusSignString(); - case AffixPatternUtils.TYPE_PLUS_SIGN: + case AffixUtils.TYPE_PLUS_SIGN: return symbols.getPlusSignString(); - case AffixPatternUtils.TYPE_PERCENT: + case AffixUtils.TYPE_PERCENT: return symbols.getPercentString(); - case AffixPatternUtils.TYPE_PERMILLE: + case AffixUtils.TYPE_PERMILLE: return symbols.getPerMillString(); - case AffixPatternUtils.TYPE_CURRENCY_SINGLE: + case AffixUtils.TYPE_CURRENCY_SINGLE: // FormatWidth ISO overrides the singular currency symbol if (unitWidth == UnitWidth.ISO_CODE) { return currency2; } else { return currency1; } - case AffixPatternUtils.TYPE_CURRENCY_DOUBLE: + case AffixUtils.TYPE_CURRENCY_DOUBLE: return currency2; - case AffixPatternUtils.TYPE_CURRENCY_TRIPLE: + case AffixUtils.TYPE_CURRENCY_TRIPLE: // NOTE: This is the code path only for patterns containing "". // Most plural currencies are formatted in DataUtils. assert plural != null; @@ -374,9 +372,9 @@ public class MutablePatternModifier implements Modifier, SymbolProvider, CharSeq } else { return currency3[plural.ordinal()]; } - case AffixPatternUtils.TYPE_CURRENCY_QUAD: + case AffixUtils.TYPE_CURRENCY_QUAD: return "\uFFFD"; - case AffixPatternUtils.TYPE_CURRENCY_QUINT: + case AffixUtils.TYPE_CURRENCY_QUINT: return "\uFFFD"; default: throw new AssertionError(); diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/CompactDecimalFormatTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/CompactDecimalFormatTest.java index db5e74a7f3c..6f6140fdc67 100644 --- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/CompactDecimalFormatTest.java +++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/CompactDecimalFormatTest.java @@ -27,7 +27,7 @@ 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.impl.number.DecimalFormatProperties; import com.ibm.icu.text.CompactDecimalFormat; import com.ibm.icu.text.CompactDecimalFormat.CompactStyle; import com.ibm.icu.text.DecimalFormat; @@ -664,7 +664,7 @@ public class CompactDecimalFormatTest extends TestFmwk { CompactDecimalFormat cdf = CompactDecimalFormat.getInstance(ULocale.ENGLISH, CompactStyle.SHORT); cdf.setProperties(new PropertySetter() { @Override - public void set(Properties props) { + public void set(DecimalFormatProperties props) { props.setCompactCustomData(customData); } }); diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/NumberFormatDataDrivenTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/NumberFormatDataDrivenTest.java index 57c559d3373..2c51bf0dd34 100644 --- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/NumberFormatDataDrivenTest.java +++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/NumberFormatDataDrivenTest.java @@ -10,8 +10,9 @@ import org.junit.Test; import com.ibm.icu.dev.test.TestUtil; import com.ibm.icu.impl.number.Parse.ParseMode; -import com.ibm.icu.impl.number.PatternAndPropertyUtils; -import com.ibm.icu.impl.number.Properties; +import com.ibm.icu.impl.number.PatternStringParser; +import com.ibm.icu.impl.number.PatternStringUtils; +import com.ibm.icu.impl.number.DecimalFormatProperties; import com.ibm.icu.text.DecimalFormatSymbols; import com.ibm.icu.text.DecimalFormat_ICU58; import com.ibm.icu.util.CurrencyAmount; @@ -423,7 +424,7 @@ public class NumberFormatDataDrivenTest { } }; - static void propertiesFromTuple(DataDrivenNumberFormatTestData tuple, Properties properties) { + static void propertiesFromTuple(DataDrivenNumberFormatTestData tuple, DecimalFormatProperties properties) { if (tuple.minIntegerDigits != null) { properties.setMinimumIntegerDigits(tuple.minIntegerDigits); } @@ -509,8 +510,8 @@ public class NumberFormatDataDrivenTest { } if (tuple.localizedPattern != null) { DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(tuple.locale); - String converted = PatternAndPropertyUtils.convertLocalized(tuple.localizedPattern, symbols, false); - PatternAndPropertyUtils.parseToExistingProperties(converted, properties); + String converted = PatternStringUtils.convertLocalized(tuple.localizedPattern, symbols, false); + PatternStringParser.parseToExistingProperties(converted, properties); } if (tuple.lenient != null) { properties.setParseMode(tuple.lenient == 0 ? ParseMode.STRICT : ParseMode.LENIENT); @@ -547,12 +548,12 @@ public class NumberFormatDataDrivenTest { public String format(DataDrivenNumberFormatTestData tuple) { String pattern = (tuple.pattern == null) ? "0" : tuple.pattern; ULocale locale = (tuple.locale == null) ? ULocale.ENGLISH : tuple.locale; - Properties properties = - PatternAndPropertyUtils.parseToProperties( + DecimalFormatProperties properties = + PatternStringParser.parseToProperties( pattern, tuple.currency != null - ? PatternAndPropertyUtils.IGNORE_ROUNDING_ALWAYS - : PatternAndPropertyUtils.IGNORE_ROUNDING_NEVER); + ? PatternStringParser.IGNORE_ROUNDING_ALWAYS + : PatternStringParser.IGNORE_ROUNDING_NEVER); propertiesFromTuple(tuple, properties); DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(locale); LocalizedNumberFormatter fmt = NumberPropertyMapper.create(properties, symbols).locale(locale); diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/NumberFormatTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/NumberFormatTest.java index 20cb8f1ea04..ff800d3b316 100644 --- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/NumberFormatTest.java +++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/NumberFormatTest.java @@ -32,6 +32,7 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Locale; +import java.util.Random; import java.util.Set; import org.junit.Test; @@ -43,7 +44,7 @@ import com.ibm.icu.impl.ICUConfig; import com.ibm.icu.impl.LocaleUtility; import com.ibm.icu.impl.data.ResourceReader; import com.ibm.icu.impl.data.TokenIterator; -import com.ibm.icu.impl.number.Properties; +import com.ibm.icu.impl.number.DecimalFormatProperties; import com.ibm.icu.math.BigDecimal; import com.ibm.icu.math.MathContext; import com.ibm.icu.text.CompactDecimalFormat; @@ -989,8 +990,14 @@ public class NumberFormatTest extends TestFmwk { @Test public void TestCurrencyPatterns() { int i; + Random rnd = new Random(2017); Locale[] locs = NumberFormat.getAvailableLocales(); for (i=0; i", curr, AffixPatternUtils.hasCurrencySymbols(input)); - assertEquals("Length on <" + input + ">", length, AffixPatternUtils.estimateLength(input)); + "Currency on <" + input + ">", curr, AffixUtils.hasCurrencySymbols(input)); + assertEquals("Length on <" + input + ">", length, AffixUtils.estimateLength(input)); String actual = unescapeWithDefaults(input); assertEquals("Output on <" + input + ">", output, actual); @@ -150,11 +150,11 @@ public class AffixPatternUtilsTest { assertEquals( "Contains on input " + input, hasMinusSign, - AffixPatternUtils.containsType(input, AffixPatternUtils.TYPE_MINUS_SIGN)); + AffixUtils.containsType(input, AffixUtils.TYPE_MINUS_SIGN)); assertEquals( "Replace on input" + input, output, - AffixPatternUtils.replaceType(input, AffixPatternUtils.TYPE_MINUS_SIGN, '+')); + AffixUtils.replaceType(input, AffixUtils.TYPE_MINUS_SIGN, '+')); } } @@ -164,13 +164,13 @@ public class AffixPatternUtilsTest { for (String str : invalidExamples) { try { - AffixPatternUtils.hasCurrencySymbols(str); + AffixUtils.hasCurrencySymbols(str); fail("No exception was thrown on an invalid string"); } catch (IllegalArgumentException e) { // OK } try { - AffixPatternUtils.estimateLength(str); + AffixUtils.estimateLength(str); fail("No exception was thrown on an invalid string"); } catch (IllegalArgumentException e) { // OK @@ -208,20 +208,20 @@ public class AffixPatternUtilsTest { String input = cas[0]; String expected = cas[1]; sb.clear(); - AffixPatternUtils.unescape(input, sb, 0, provider); + AffixUtils.unescape(input, sb, 0, provider); assertEquals("With symbol provider on <" + input + ">", expected, sb.toString()); } // Test insertion position sb.clear(); sb.append("abcdefg", null); - AffixPatternUtils.unescape("-+%", sb, 4, provider); + AffixUtils.unescape("-+%", sb, 4, provider); assertEquals("Symbol provider into middle", "abcd123efg", sb.toString()); } private static String unescapeWithDefaults(String input) { NumberStringBuilder nsb = new NumberStringBuilder(); - AffixPatternUtils.unescape(input, nsb, 0, DEFAULT_SYMBOL_PROVIDER); + AffixUtils.unescape(input, nsb, 0, DEFAULT_SYMBOL_PROVIDER); return nsb.toString(); } } diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/FormatQuantityTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/FormatQuantityTest.java index 6d1b3617504..0943a5fdfbc 100644 --- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/FormatQuantityTest.java +++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/FormatQuantityTest.java @@ -13,12 +13,12 @@ import java.util.Random; import org.junit.Test; import com.ibm.icu.dev.test.TestFmwk; -import com.ibm.icu.impl.number.FormatQuantity; -import com.ibm.icu.impl.number.FormatQuantity1; -import com.ibm.icu.impl.number.FormatQuantity2; -import com.ibm.icu.impl.number.FormatQuantity3; -import com.ibm.icu.impl.number.FormatQuantity4; -import com.ibm.icu.impl.number.Properties; +import com.ibm.icu.impl.number.DecimalQuantity; +import com.ibm.icu.impl.number.DecimalQuantity_SimpleStorage; +import com.ibm.icu.impl.number.DecimalQuantity_64BitBCD; +import com.ibm.icu.impl.number.DecimalQuantity_ByteArrayBCD; +import com.ibm.icu.impl.number.DecimalQuantity_DualStorageBCD; +import com.ibm.icu.impl.number.DecimalFormatProperties; import com.ibm.icu.text.CompactDecimalFormat.CompactStyle; import com.ibm.icu.text.DecimalFormatSymbols; import com.ibm.icu.util.ULocale; @@ -27,34 +27,34 @@ import newapi.LocalizedNumberFormatter; import newapi.NumberPropertyMapper; /** TODO: This is a temporary name for this class. Suggestions for a better name? */ -public class FormatQuantityTest extends TestFmwk { +public class DecimalQuantityTest extends TestFmwk { @Test public void testBehavior() throws ParseException { - // Make a list of several formatters to test the behavior of FormatQuantity. + // Make a list of several formatters to test the behavior of DecimalQuantity. List formats = new ArrayList(); DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(ULocale.ENGLISH); - Properties properties = new Properties(); + DecimalFormatProperties properties = new DecimalFormatProperties(); formats.add(NumberPropertyMapper.create(properties, symbols).locale(ULocale.ENGLISH)); properties = - new Properties() + new DecimalFormatProperties() .setMinimumSignificantDigits(3) .setMaximumSignificantDigits(3) .setCompactStyle(CompactStyle.LONG); formats.add(NumberPropertyMapper.create(properties, symbols).locale(ULocale.ENGLISH)); properties = - new Properties() + new DecimalFormatProperties() .setMinimumExponentDigits(1) .setMaximumIntegerDigits(3) .setMaximumFractionDigits(1); formats.add(NumberPropertyMapper.create(properties, symbols).locale(ULocale.ENGLISH)); - properties = new Properties().setRoundingIncrement(new BigDecimal("0.5")); + properties = new DecimalFormatProperties().setRoundingIncrement(new BigDecimal("0.5")); formats.add(NumberPropertyMapper.create(properties, symbols).locale(ULocale.ENGLISH)); String[] cases = { @@ -99,68 +99,68 @@ public class FormatQuantityTest extends TestFmwk { int i = 0; for (String str : cases) { - testFormatQuantity(i++, str, formats, 0); + testDecimalQuantity(i++, str, formats, 0); } i = 0; for (String str : hardCases) { - testFormatQuantity(i++, str, formats, 1); + testDecimalQuantity(i++, str, formats, 1); } i = 0; for (String str : doubleCases) { - testFormatQuantity(i++, str, formats, 2); + testDecimalQuantity(i++, str, formats, 2); } } - static void testFormatQuantity(int t, String str, List formats, int mode) { + static void testDecimalQuantity(int t, String str, List formats, int mode) { if (mode == 2) { assertEquals("Double is not valid", Double.toString(Double.parseDouble(str)), str); } - List qs = new ArrayList(); + List qs = new ArrayList(); BigDecimal d = new BigDecimal(str); - qs.add(new FormatQuantity1(d)); - if (mode == 0) qs.add(new FormatQuantity2(d)); - qs.add(new FormatQuantity3(d)); - qs.add(new FormatQuantity4(d)); + qs.add(new DecimalQuantity_SimpleStorage(d)); + if (mode == 0) qs.add(new DecimalQuantity_64BitBCD(d)); + qs.add(new DecimalQuantity_ByteArrayBCD(d)); + qs.add(new DecimalQuantity_DualStorageBCD(d)); if (new BigDecimal(Double.toString(d.doubleValue())).compareTo(d) == 0) { double dv = d.doubleValue(); - qs.add(new FormatQuantity1(dv)); - if (mode == 0) qs.add(new FormatQuantity2(dv)); - qs.add(new FormatQuantity3(dv)); - qs.add(new FormatQuantity4(dv)); + qs.add(new DecimalQuantity_SimpleStorage(dv)); + if (mode == 0) qs.add(new DecimalQuantity_64BitBCD(dv)); + qs.add(new DecimalQuantity_ByteArrayBCD(dv)); + qs.add(new DecimalQuantity_DualStorageBCD(dv)); } if (new BigDecimal(Long.toString(d.longValue())).compareTo(d) == 0) { double lv = d.longValue(); - qs.add(new FormatQuantity1(lv)); - if (mode == 0) qs.add(new FormatQuantity2(lv)); - qs.add(new FormatQuantity3(lv)); - qs.add(new FormatQuantity4(lv)); + qs.add(new DecimalQuantity_SimpleStorage(lv)); + if (mode == 0) qs.add(new DecimalQuantity_64BitBCD(lv)); + qs.add(new DecimalQuantity_ByteArrayBCD(lv)); + qs.add(new DecimalQuantity_DualStorageBCD(lv)); } - testFormatQuantityExpectedOutput(qs.get(0), str); + testDecimalQuantityExpectedOutput(qs.get(0), str); if (qs.size() == 1) { return; } for (int i = 1; i < qs.size(); i++) { - FormatQuantity q0 = qs.get(0); - FormatQuantity q1 = qs.get(i); - testFormatQuantityExpectedOutput(q1, str); - testFormatQuantityRounding(q0, q1); - testFormatQuantityRoundingInterval(q0, q1); - testFormatQuantityMath(q0, q1); - testFormatQuantityWithFormats(q0, q1, formats); + DecimalQuantity q0 = qs.get(0); + DecimalQuantity q1 = qs.get(i); + testDecimalQuantityExpectedOutput(q1, str); + testDecimalQuantityRounding(q0, q1); + testDecimalQuantityRoundingInterval(q0, q1); + testDecimalQuantityMath(q0, q1); + testDecimalQuantityWithFormats(q0, q1, formats); } } - private static void testFormatQuantityExpectedOutput(FormatQuantity rq, String expected) { + private static void testDecimalQuantityExpectedOutput(DecimalQuantity rq, String expected) { StringBuilder sb = new StringBuilder(); - FormatQuantity q0 = rq.createCopy(); + DecimalQuantity q0 = rq.createCopy(); // Force an accurate double q0.roundToInfinity(); q0.setIntegerLength(1, Integer.MAX_VALUE); @@ -182,68 +182,68 @@ public class FormatQuantityTest extends TestFmwk { private static final MathContext MATH_CONTEXT_PRECISION = new MathContext(3, RoundingMode.HALF_UP); - private static void testFormatQuantityRounding(FormatQuantity rq0, FormatQuantity rq1) { - FormatQuantity q0 = rq0.createCopy(); - FormatQuantity q1 = rq1.createCopy(); + private static void testDecimalQuantityRounding(DecimalQuantity rq0, DecimalQuantity rq1) { + DecimalQuantity q0 = rq0.createCopy(); + DecimalQuantity q1 = rq1.createCopy(); q0.roundToMagnitude(-1, MATH_CONTEXT_HALF_EVEN); q1.roundToMagnitude(-1, MATH_CONTEXT_HALF_EVEN); - testFormatQuantityBehavior(q0, q1); + testDecimalQuantityBehavior(q0, q1); q0 = rq0.createCopy(); q1 = rq1.createCopy(); q0.roundToMagnitude(-1, MATH_CONTEXT_CEILING); q1.roundToMagnitude(-1, MATH_CONTEXT_CEILING); - testFormatQuantityBehavior(q0, q1); + testDecimalQuantityBehavior(q0, q1); q0 = rq0.createCopy(); q1 = rq1.createCopy(); q0.roundToMagnitude(-1, MATH_CONTEXT_PRECISION); q1.roundToMagnitude(-1, MATH_CONTEXT_PRECISION); - testFormatQuantityBehavior(q0, q1); + testDecimalQuantityBehavior(q0, q1); } - private static void testFormatQuantityRoundingInterval(FormatQuantity rq0, FormatQuantity rq1) { - FormatQuantity q0 = rq0.createCopy(); - FormatQuantity q1 = rq1.createCopy(); + private static void testDecimalQuantityRoundingInterval(DecimalQuantity rq0, DecimalQuantity rq1) { + DecimalQuantity q0 = rq0.createCopy(); + DecimalQuantity q1 = rq1.createCopy(); q0.roundToIncrement(new BigDecimal("0.05"), MATH_CONTEXT_HALF_EVEN); q1.roundToIncrement(new BigDecimal("0.05"), MATH_CONTEXT_HALF_EVEN); - testFormatQuantityBehavior(q0, q1); + testDecimalQuantityBehavior(q0, q1); q0 = rq0.createCopy(); q1 = rq1.createCopy(); q0.roundToIncrement(new BigDecimal("0.05"), MATH_CONTEXT_CEILING); q1.roundToIncrement(new BigDecimal("0.05"), MATH_CONTEXT_CEILING); - testFormatQuantityBehavior(q0, q1); + testDecimalQuantityBehavior(q0, q1); } - private static void testFormatQuantityMath(FormatQuantity rq0, FormatQuantity rq1) { - FormatQuantity q0 = rq0.createCopy(); - FormatQuantity q1 = rq1.createCopy(); + private static void testDecimalQuantityMath(DecimalQuantity rq0, DecimalQuantity rq1) { + DecimalQuantity q0 = rq0.createCopy(); + DecimalQuantity q1 = rq1.createCopy(); q0.adjustMagnitude(-3); q1.adjustMagnitude(-3); - testFormatQuantityBehavior(q0, q1); + testDecimalQuantityBehavior(q0, q1); q0 = rq0.createCopy(); q1 = rq1.createCopy(); q0.multiplyBy(new BigDecimal("3.14159")); q1.multiplyBy(new BigDecimal("3.14159")); - testFormatQuantityBehavior(q0, q1); + testDecimalQuantityBehavior(q0, q1); } - private static void testFormatQuantityWithFormats( - FormatQuantity rq0, FormatQuantity rq1, List formats) { + private static void testDecimalQuantityWithFormats( + DecimalQuantity rq0, DecimalQuantity rq1, List formats) { for (LocalizedNumberFormatter format : formats) { - FormatQuantity q0 = rq0.createCopy(); - FormatQuantity q1 = rq1.createCopy(); + DecimalQuantity q0 = rq0.createCopy(); + DecimalQuantity q1 = rq1.createCopy(); String s1 = format.format(q0).toString(); String s2 = format.format(q1).toString(); assertEquals("Different output from formatter (" + q0 + ", " + q1 + ")", s1, s2); } } - private static void testFormatQuantityBehavior(FormatQuantity rq0, FormatQuantity rq1) { - FormatQuantity q0 = rq0.createCopy(); - FormatQuantity q1 = rq1.createCopy(); + private static void testDecimalQuantityBehavior(DecimalQuantity rq0, DecimalQuantity rq1) { + DecimalQuantity q0 = rq0.createCopy(); + DecimalQuantity q1 = rq1.createCopy(); assertEquals("Different sign (" + q0 + ", " + q1 + ")", q0.isNegative(), q1.isNegative()); @@ -279,19 +279,19 @@ public class FormatQuantityTest extends TestFmwk { q1.getDigit(m)); } - if (rq0 instanceof FormatQuantity4) { - String message = ((FormatQuantity4) rq0).checkHealth(); + if (rq0 instanceof DecimalQuantity_DualStorageBCD) { + String message = ((DecimalQuantity_DualStorageBCD) rq0).checkHealth(); if (message != null) errln(message); } - if (rq1 instanceof FormatQuantity4) { - String message = ((FormatQuantity4) rq1).checkHealth(); + if (rq1 instanceof DecimalQuantity_DualStorageBCD) { + String message = ((DecimalQuantity_DualStorageBCD) rq1).checkHealth(); if (message != null) errln(message); } } @Test public void testSwitchStorage() { - FormatQuantity4 fq = new FormatQuantity4(); + DecimalQuantity_DualStorageBCD fq = new DecimalQuantity_DualStorageBCD(); fq.setToLong(1234123412341234L); assertFalse("Should not be using byte array", fq.usingBytes()); @@ -311,7 +311,7 @@ public class FormatQuantityTest extends TestFmwk { @Test public void testAppend() { - FormatQuantity4 fq = new FormatQuantity4(); + DecimalQuantity_DualStorageBCD fq = new DecimalQuantity_DualStorageBCD(); fq.appendDigit((byte) 1, 0, true); assertBigDecimalEquals("Failed on append", "1.", fq.toBigDecimal()); assertNull("Failed health check", fq.checkHealth()); @@ -401,15 +401,15 @@ public class FormatQuantityTest extends TestFmwk { checkDoubleBehavior(d, false, ""); } - assertEquals("NaN check failed", Double.NaN, new FormatQuantity4(Double.NaN).toDouble()); + assertEquals("NaN check failed", Double.NaN, new DecimalQuantity_DualStorageBCD(Double.NaN).toDouble()); assertEquals( "Inf check failed", Double.POSITIVE_INFINITY, - new FormatQuantity4(Double.POSITIVE_INFINITY).toDouble()); + new DecimalQuantity_DualStorageBCD(Double.POSITIVE_INFINITY).toDouble()); assertEquals( "-Inf check failed", Double.NEGATIVE_INFINITY, - new FormatQuantity4(Double.NEGATIVE_INFINITY).toDouble()); + new DecimalQuantity_DualStorageBCD(Double.NEGATIVE_INFINITY).toDouble()); // Generate random doubles String alert = "UNEXPECTED FAILURE: PLEASE REPORT THIS MESSAGE TO THE ICU TEAM: "; @@ -422,7 +422,7 @@ public class FormatQuantityTest extends TestFmwk { } private static void checkDoubleBehavior(double d, boolean explicitRequired, String alert) { - FormatQuantity4 fq = new FormatQuantity4(d); + DecimalQuantity_DualStorageBCD fq = new DecimalQuantity_DualStorageBCD(d); if (explicitRequired) assertTrue(alert + "Should be using approximate double", !fq.explicitExactDouble); assertEquals(alert + "Initial construction from hard double", d, fq.toDouble()); @@ -459,7 +459,7 @@ public class FormatQuantityTest extends TestFmwk { MathContext mc = (MathContext) cas[2]; boolean usesExact = (Boolean) cas[3]; - FormatQuantity4 fq = new FormatQuantity4(d); + DecimalQuantity_DualStorageBCD fq = new DecimalQuantity_DualStorageBCD(d); assertTrue("Should be using approximate double", !fq.explicitExactDouble); fq.roundToMagnitude(-maxFrac, mc); assertEquals( diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/MurkyModifierTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/MurkyModifierTest.java index 0bc996b5a3e..e1bf13d1c9a 100644 --- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/MurkyModifierTest.java +++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/MurkyModifierTest.java @@ -6,22 +6,22 @@ import static org.junit.Assert.assertEquals; import org.junit.Test; -import com.ibm.icu.impl.number.PatternParser; +import com.ibm.icu.impl.number.PatternStringParser; import com.ibm.icu.impl.number.NumberStringBuilder; import com.ibm.icu.text.DecimalFormatSymbols; import com.ibm.icu.util.Currency; import com.ibm.icu.util.ULocale; -import newapi.MutablePatternModifier; import newapi.NumberFormatter.SignDisplay; import newapi.NumberFormatter.UnitWidth; +import newapi.impl.MutablePatternModifier; public class MurkyModifierTest { @Test public void basic() { MutablePatternModifier murky = new MutablePatternModifier(false); - murky.setPatternInfo(PatternParser.parse("a0b")); + murky.setPatternInfo(PatternStringParser.parseToPatternInfo("a0b")); murky.setPatternAttributes(SignDisplay.AUTO, false); murky.setSymbols( DecimalFormatSymbols.getInstance(ULocale.ENGLISH), @@ -41,7 +41,7 @@ public class MurkyModifierTest { assertEquals("a", getPrefix(murky)); assertEquals("b", getSuffix(murky)); - murky.setPatternInfo(PatternParser.parse("a0b;c-0d")); + murky.setPatternInfo(PatternStringParser.parseToPatternInfo("a0b;c-0d")); murky.setPatternAttributes(SignDisplay.AUTO, false); murky.setNumberProperties(false, null); assertEquals("a", getPrefix(murky)); diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/NumberFormatterTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/NumberFormatterTest.java index 460aae4c1cb..dcb273cd69b 100644 --- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/NumberFormatterTest.java +++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/NumberFormatterTest.java @@ -11,6 +11,7 @@ import java.util.Locale; import org.junit.Ignore; import org.junit.Test; +import com.ibm.icu.impl.number.PatternStringParser; import com.ibm.icu.text.DecimalFormatSymbols; import com.ibm.icu.text.NumberingSystem; import com.ibm.icu.util.Currency; @@ -30,7 +31,6 @@ import newapi.NumberFormatter; import newapi.NumberFormatter.DecimalMarkDisplay; import newapi.NumberFormatter.SignDisplay; import newapi.NumberFormatter.UnitWidth; -import newapi.NumberPropertyMapper; import newapi.Rounder; import newapi.UnlocalizedNumberFormatter; import newapi.impl.Padder; @@ -397,8 +397,11 @@ public class NumberFormatterTest { assertFormatSingle( "Currency Long Name from Pattern Syntax", - "$GBP F0 grouping=none integer-width=1- symbols=loc:en_US sign=AUTO decimal=AUTO", - NumberPropertyMapper.create("0 ¤¤¤", DecimalFormatSymbols.getInstance()).unit(GBP), + "$GBP F0 grouping=none integer-width=1- symbols=loc:en sign=AUTO decimal=AUTO", + NumberFormatter.fromDecimalFormat( + PatternStringParser.parseToProperties("0 ¤¤¤"), + DecimalFormatSymbols.getInstance(ULocale.ENGLISH), + null).unit(GBP), ULocale.ENGLISH, 1234567.89, "1234568 British pounds"); @@ -658,7 +661,7 @@ public class NumberFormatterTest { assertFormatDescending( "Rounding None", "Y", - NumberFormatter.with().rounding(Rounder.none()), + NumberFormatter.with().rounding(Rounder.unlimited()), ULocale.ENGLISH, "87,650", "8,765", @@ -1229,8 +1232,8 @@ public class NumberFormatterTest { @Test public void getPrefixSuffix() { Object[][] cases = { - { NumberFormatter.withLocale(ULocale.ENGLISH).unit(GBP).unitWidth(UnitWidth.ISO_CODE), "GBP", "", "-GBP", - "" }, + { NumberFormatter.withLocale(ULocale.ENGLISH).unit(GBP).unitWidth(UnitWidth.ISO_CODE), "GBP", "", + "-GBP", "" }, { NumberFormatter.withLocale(ULocale.ENGLISH).unit(GBP).unitWidth(UnitWidth.FULL_NAME), "", " British pounds", "-", " British pounds" } }; diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/PatternStringTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/PatternStringTest.java index 39b44f528a0..a5cd7a48c4d 100644 --- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/PatternStringTest.java +++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/PatternStringTest.java @@ -7,8 +7,9 @@ import static org.junit.Assert.fail; import org.junit.Test; -import com.ibm.icu.impl.number.PatternAndPropertyUtils; -import com.ibm.icu.impl.number.Properties; +import com.ibm.icu.impl.number.PatternStringParser; +import com.ibm.icu.impl.number.PatternStringUtils; +import com.ibm.icu.impl.number.DecimalFormatProperties; import com.ibm.icu.text.DecimalFormatSymbols; import com.ibm.icu.util.ULocale; @@ -27,8 +28,8 @@ public class PatternStringTest { String localized = "’.'ab'c'b''a'''#,##0a0b'a%'"; String toStandard = "+-'ab'c'b''a'''#,##0.0%'a%'"; - assertEquals(localized, PatternAndPropertyUtils.convertLocalized(standard, symbols, true)); - assertEquals(toStandard, PatternAndPropertyUtils.convertLocalized(localized, symbols, false)); + assertEquals(localized, PatternStringUtils.convertLocalized(standard, symbols, true)); + assertEquals(toStandard, PatternStringUtils.convertLocalized(localized, symbols, false)); } @Test @@ -60,8 +61,8 @@ public class PatternStringTest { String input = cas[0]; String output = cas[1]; - Properties properties = PatternAndPropertyUtils.parseToProperties(input); - String actual = PatternAndPropertyUtils.propertiesToString(properties); + DecimalFormatProperties properties = PatternStringParser.parseToProperties(input); + String actual = PatternStringUtils.propertiesToPatternString(properties); assertEquals( "Failed on input pattern '" + input + "', properties " + properties, output, actual); } @@ -70,27 +71,27 @@ public class PatternStringTest { @Test public void testToPatternWithProperties() { Object[][] cases = { - {new Properties().setPositivePrefix("abc"), "abc#"}, - {new Properties().setPositiveSuffix("abc"), "#abc"}, - {new Properties().setPositivePrefixPattern("abc"), "abc#"}, - {new Properties().setPositiveSuffixPattern("abc"), "#abc"}, - {new Properties().setNegativePrefix("abc"), "#;abc#"}, - {new Properties().setNegativeSuffix("abc"), "#;#abc"}, - {new Properties().setNegativePrefixPattern("abc"), "#;abc#"}, - {new Properties().setNegativeSuffixPattern("abc"), "#;#abc"}, - {new Properties().setPositivePrefix("+"), "'+'#"}, - {new Properties().setPositivePrefixPattern("+"), "+#"}, - {new Properties().setPositivePrefix("+'"), "'+'''#"}, - {new Properties().setPositivePrefix("'+"), "'''+'#"}, - {new Properties().setPositivePrefix("'"), "''#"}, - {new Properties().setPositivePrefixPattern("+''"), "+''#"}, + {new DecimalFormatProperties().setPositivePrefix("abc"), "abc#"}, + {new DecimalFormatProperties().setPositiveSuffix("abc"), "#abc"}, + {new DecimalFormatProperties().setPositivePrefixPattern("abc"), "abc#"}, + {new DecimalFormatProperties().setPositiveSuffixPattern("abc"), "#abc"}, + {new DecimalFormatProperties().setNegativePrefix("abc"), "#;abc#"}, + {new DecimalFormatProperties().setNegativeSuffix("abc"), "#;#abc"}, + {new DecimalFormatProperties().setNegativePrefixPattern("abc"), "#;abc#"}, + {new DecimalFormatProperties().setNegativeSuffixPattern("abc"), "#;#abc"}, + {new DecimalFormatProperties().setPositivePrefix("+"), "'+'#"}, + {new DecimalFormatProperties().setPositivePrefixPattern("+"), "+#"}, + {new DecimalFormatProperties().setPositivePrefix("+'"), "'+'''#"}, + {new DecimalFormatProperties().setPositivePrefix("'+"), "'''+'#"}, + {new DecimalFormatProperties().setPositivePrefix("'"), "''#"}, + {new DecimalFormatProperties().setPositivePrefixPattern("+''"), "+''#"}, }; for (Object[] cas : cases) { - Properties input = (Properties) cas[0]; + DecimalFormatProperties input = (DecimalFormatProperties) cas[0]; String output = (String) cas[1]; - String actual = PatternAndPropertyUtils.propertiesToString(input); + String actual = PatternStringUtils.propertiesToPatternString(input); assertEquals("Failed on input properties " + input, output, actual); } } @@ -103,7 +104,7 @@ public class PatternStringTest { for (String pattern : invalidPatterns) { try { - PatternAndPropertyUtils.parseToProperties(pattern); + PatternStringParser.parseToProperties(pattern); fail("Didn't throw IllegalArgumentException when parsing pattern: " + pattern); } catch (IllegalArgumentException e) { } @@ -112,8 +113,8 @@ public class PatternStringTest { @Test public void testBug13117() { - Properties expected = PatternAndPropertyUtils.parseToProperties("0"); - Properties actual = PatternAndPropertyUtils.parseToProperties("0;"); + DecimalFormatProperties expected = PatternStringParser.parseToProperties("0"); + DecimalFormatProperties actual = PatternStringParser.parseToProperties("0;"); assertEquals("Should not consume negative subpattern", expected, actual); } } diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/PropertiesTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/PropertiesTest.java index 25546fe3389..4d2df684299 100644 --- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/PropertiesTest.java +++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/number/PropertiesTest.java @@ -31,8 +31,8 @@ import org.junit.Test; import com.ibm.icu.dev.test.serializable.SerializableTestUtility; import com.ibm.icu.impl.number.Parse.GroupingMode; import com.ibm.icu.impl.number.Parse.ParseMode; -import com.ibm.icu.impl.number.PatternAndPropertyUtils; -import com.ibm.icu.impl.number.Properties; +import com.ibm.icu.impl.number.PatternStringParser; +import com.ibm.icu.impl.number.DecimalFormatProperties; import com.ibm.icu.impl.number.ThingsNeedingNewHome.PadPosition; import com.ibm.icu.text.CompactDecimalFormat.CompactStyle; import com.ibm.icu.text.CurrencyPluralInfo; @@ -47,8 +47,8 @@ public class PropertiesTest { @Test public void testBasicEquals() { - Properties p1 = new Properties(); - Properties p2 = new Properties(); + DecimalFormatProperties p1 = new DecimalFormatProperties(); + DecimalFormatProperties p2 = new DecimalFormatProperties(); assertEquals(p1, p2); p1.setPositivePrefix("abc"); @@ -61,14 +61,14 @@ public class PropertiesTest { @Test public void testFieldCoverage() { - Properties p0 = new Properties(); - Properties p1 = new Properties(); - Properties p2 = new Properties(); - Properties p3 = new Properties(); - Properties p4 = new Properties(); + DecimalFormatProperties p0 = new DecimalFormatProperties(); + DecimalFormatProperties p1 = new DecimalFormatProperties(); + DecimalFormatProperties p2 = new DecimalFormatProperties(); + DecimalFormatProperties p3 = new DecimalFormatProperties(); + DecimalFormatProperties p4 = new DecimalFormatProperties(); Set hashCodes = new HashSet(); - Field[] fields = Properties.class.getDeclaredFields(); + Field[] fields = DecimalFormatProperties.class.getDeclaredFields(); for (Field field : fields) { if (Modifier.isStatic(field.getModifiers())) { continue; @@ -81,7 +81,7 @@ public class PropertiesTest { String setterName = "set" + fieldNamePascalCase; Method getter, setter; try { - getter = Properties.class.getMethod(getterName); + getter = DecimalFormatProperties.class.getMethod(getterName); assertEquals( "Getter does not return correct type", field.getType(), getter.getReturnType()); } catch (NoSuchMethodException e) { @@ -92,10 +92,10 @@ public class PropertiesTest { continue; } try { - setter = Properties.class.getMethod(setterName, field.getType()); + setter = DecimalFormatProperties.class.getMethod(setterName, field.getType()); assertEquals( "Method " + setterName + " does not return correct type", - Properties.class, + DecimalFormatProperties.class, setter.getReturnType()); } catch (NoSuchMethodException e) { fail("Could not find method " + setterName + " for field " + field); @@ -157,7 +157,7 @@ public class PropertiesTest { hashCodes.add(p1.hashCode()); // Check for clone behavior - Properties copy = p1.clone(); + DecimalFormatProperties copy = p1.clone(); assertEquals("Field " + field + " did not get copied in clone", p1, copy); assertEquals(p1.hashCode(), copy.hashCode()); assertEquals(getter.invoke(p1), getter.invoke(copy)); @@ -307,10 +307,10 @@ public class PropertiesTest { @Test public void TestBasicSerializationRoundTrip() throws IOException, ClassNotFoundException { - Properties props0 = new Properties(); + DecimalFormatProperties props0 = new DecimalFormatProperties(); // Write values to some of the fields - PatternAndPropertyUtils.parseToExistingProperties("A-**####,#00.00#b¤", props0); + PatternStringParser.parseToExistingProperties("A-**####,#00.00#b¤", props0); // Write to byte stream ByteArrayOutputStream baos = new ByteArrayOutputStream(); @@ -324,7 +324,7 @@ public class PropertiesTest { ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes)); Object obj = ois.readObject(); ois.close(); - Properties props1 = (Properties) obj; + DecimalFormatProperties props1 = (DecimalFormatProperties) obj; // Test equality assertEquals("Did not round-trip through serialization", props0, props1); @@ -336,9 +336,9 @@ public class PropertiesTest { @Override public Object[] getTestObjects() { return new Object[] { - new Properties(), - PatternAndPropertyUtils.parseToProperties("x#,##0.00%"), - new Properties().setCompactStyle(CompactStyle.LONG).setMinimumExponentDigits(2) + new DecimalFormatProperties(), + PatternStringParser.parseToProperties("x#,##0.00%"), + new DecimalFormatProperties().setCompactStyle(CompactStyle.LONG).setMinimumExponentDigits(2) }; }