ICU-13644 Minor refactoring changes in ICU4J.
X-SVN-Rev: 41129
This commit is contained in:
parent
c940df09e7
commit
369f3484d8
@ -16,7 +16,6 @@ import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
|
||||
import com.ibm.icu.impl.number.Padder.PadPosition;
|
||||
import com.ibm.icu.impl.number.parse.NumberParserImpl.ParseMode;
|
||||
import com.ibm.icu.text.CompactDecimalFormat.CompactStyle;
|
||||
import com.ibm.icu.text.CurrencyPluralInfo;
|
||||
import com.ibm.icu.text.PluralRules;
|
||||
@ -30,6 +29,40 @@ public class DecimalFormatProperties implements Cloneable, Serializable {
|
||||
/** Auto-generated. */
|
||||
private static final long serialVersionUID = 4095518955889349243L;
|
||||
|
||||
/** Controls the set of rules for parsing a string from the old DecimalFormat API. */
|
||||
public static enum ParseMode {
|
||||
/**
|
||||
* Lenient mode should be used if you want to accept malformed user input. It will use heuristics
|
||||
* to attempt to parse through typographical errors in the string.
|
||||
*/
|
||||
LENIENT,
|
||||
|
||||
/**
|
||||
* Strict mode should be used if you want to require that the input is well-formed. More
|
||||
* specifically, it differs from lenient mode in the following ways:
|
||||
*
|
||||
* <ul>
|
||||
* <li>Grouping widths must match the grouping settings. For example, "12,3,45" will fail if the
|
||||
* grouping width is 3, as in the pattern "#,##0".
|
||||
* <li>The string must contain a complete prefix and suffix. For example, if the pattern is
|
||||
* "{#};(#)", then "{123}" or "(123)" would match, but "{123", "123}", and "123" would all fail.
|
||||
* (The latter strings would be accepted in lenient mode.)
|
||||
* <li>Whitespace may not appear at arbitrary places in the string. In lenient mode, whitespace
|
||||
* is allowed to occur arbitrarily before and after prefixes and exponent separators.
|
||||
* <li>Leading grouping separators are not allowed, as in ",123".
|
||||
* <li>Minus and plus signs can only appear if specified in the pattern. In lenient mode, a plus
|
||||
* or minus sign can always precede a number.
|
||||
* <li>The set of characters that can be interpreted as a decimal or grouping separator is
|
||||
* smaller.
|
||||
* <li><strong>If currency parsing is enabled,</strong> currencies must only appear where
|
||||
* specified in either the current pattern string or in a valid pattern string for the current
|
||||
* locale. For example, if the pattern is "¤0.00", then "$1.23" would match, but "1.23$" would
|
||||
* fail to match.
|
||||
* </ul>
|
||||
*/
|
||||
STRICT,
|
||||
}
|
||||
|
||||
// The setters in this class should NOT have any side-effects or perform any validation. It is
|
||||
// up to the consumer of the property bag to deal with property validation.
|
||||
|
||||
@ -44,7 +77,7 @@ public class DecimalFormatProperties implements Cloneable, Serializable {
|
||||
/| or #equals(), but it will NOT catch if you forget to add it to #hashCode(). |/
|
||||
/+--------------------------------------------------------------------------------------------*/
|
||||
|
||||
private transient Map<String, Map<String, String>> compactCustomData;
|
||||
private transient Map<String, Map<String, String>> compactCustomData; // ICU4J-only
|
||||
private transient CompactStyle compactStyle;
|
||||
private transient Currency currency;
|
||||
private transient CurrencyPluralInfo currencyPluralInfo;
|
||||
@ -55,7 +88,7 @@ public class DecimalFormatProperties implements Cloneable, Serializable {
|
||||
private transient int formatWidth;
|
||||
private transient int groupingSize;
|
||||
private transient int magnitudeMultiplier;
|
||||
private transient MathContext mathContext;
|
||||
private transient MathContext mathContext; // ICU4J-only
|
||||
private transient int maximumFractionDigits;
|
||||
private transient int maximumIntegerDigits;
|
||||
private transient int maximumSignificantDigits;
|
||||
|
@ -11,6 +11,7 @@ import com.ibm.icu.impl.StringSegment;
|
||||
import com.ibm.icu.impl.number.AffixPatternProvider;
|
||||
import com.ibm.icu.impl.number.CustomSymbolCurrency;
|
||||
import com.ibm.icu.impl.number.DecimalFormatProperties;
|
||||
import com.ibm.icu.impl.number.DecimalFormatProperties.ParseMode;
|
||||
import com.ibm.icu.impl.number.Grouper;
|
||||
import com.ibm.icu.impl.number.PatternStringParser;
|
||||
import com.ibm.icu.impl.number.PatternStringParser.ParsedPatternInfo;
|
||||
@ -31,45 +32,10 @@ import com.ibm.icu.util.ULocale;
|
||||
*/
|
||||
public class NumberParserImpl {
|
||||
|
||||
// TODO: Find a better place for this enum.
|
||||
/** Controls the set of rules for parsing a string. */
|
||||
public static enum ParseMode {
|
||||
/**
|
||||
* Lenient mode should be used if you want to accept malformed user input. It will use heuristics
|
||||
* to attempt to parse through typographical errors in the string.
|
||||
*/
|
||||
LENIENT,
|
||||
|
||||
/**
|
||||
* Strict mode should be used if you want to require that the input is well-formed. More
|
||||
* specifically, it differs from lenient mode in the following ways:
|
||||
*
|
||||
* <ul>
|
||||
* <li>Grouping widths must match the grouping settings. For example, "12,3,45" will fail if the
|
||||
* grouping width is 3, as in the pattern "#,##0".
|
||||
* <li>The string must contain a complete prefix and suffix. For example, if the pattern is
|
||||
* "{#};(#)", then "{123}" or "(123)" would match, but "{123", "123}", and "123" would all fail.
|
||||
* (The latter strings would be accepted in lenient mode.)
|
||||
* <li>Whitespace may not appear at arbitrary places in the string. In lenient mode, whitespace
|
||||
* is allowed to occur arbitrarily before and after prefixes and exponent separators.
|
||||
* <li>Leading grouping separators are not allowed, as in ",123".
|
||||
* <li>Minus and plus signs can only appear if specified in the pattern. In lenient mode, a plus
|
||||
* or minus sign can always precede a number.
|
||||
* <li>The set of characters that can be interpreted as a decimal or grouping separator is
|
||||
* smaller.
|
||||
* <li><strong>If currency parsing is enabled,</strong> currencies must only appear where
|
||||
* specified in either the current pattern string or in a valid pattern string for the current
|
||||
* locale. For example, if the pattern is "¤0.00", then "$1.23" would match, but "1.23$" would
|
||||
* fail to match.
|
||||
* </ul>
|
||||
*/
|
||||
STRICT,
|
||||
}
|
||||
|
||||
public static NumberParserImpl createSimpleParser(
|
||||
ULocale locale,
|
||||
String pattern,
|
||||
int parseFlags) {
|
||||
/**
|
||||
* Creates a parser with most default options. Used for testing, not production.
|
||||
*/
|
||||
public static NumberParserImpl createSimpleParser(ULocale locale, String pattern, int parseFlags) {
|
||||
|
||||
NumberParserImpl parser = new NumberParserImpl(parseFlags);
|
||||
DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(locale);
|
||||
@ -97,12 +63,15 @@ public class NumberParserImpl {
|
||||
parser.addMatcher(PaddingMatcher.getInstance("@"));
|
||||
parser.addMatcher(ScientificMatcher.getInstance(symbols, grouper));
|
||||
parser.addMatcher(CurrencyNamesMatcher.getInstance(locale));
|
||||
parser.addMatcher(new RequireNumberMatcher());
|
||||
parser.addMatcher(new RequireNumberValidator());
|
||||
|
||||
parser.freeze();
|
||||
return parser;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the string without returning a NumberParserImpl. Used for testing, not production.
|
||||
*/
|
||||
public static Number parseStatic(
|
||||
String input,
|
||||
ParsePosition ppos,
|
||||
@ -120,6 +89,9 @@ public class NumberParserImpl {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the string without returning a NumberParserImpl. Used for testing, not production.
|
||||
*/
|
||||
public static CurrencyAmount parseStaticCurrency(
|
||||
String input,
|
||||
ParsePosition ppos,
|
||||
@ -130,16 +102,8 @@ public class NumberParserImpl {
|
||||
parser.parse(input, true, result);
|
||||
if (result.success()) {
|
||||
ppos.setIndex(result.charEnd);
|
||||
// TODO: Clean this up
|
||||
Currency currency;
|
||||
if (result.currencyCode != null) {
|
||||
currency = Currency.getInstance(result.currencyCode);
|
||||
} else {
|
||||
assert 0 != (result.flags & ParsedNumber.FLAG_HAS_DEFAULT_CURRENCY);
|
||||
currency = CustomSymbolCurrency
|
||||
.resolve(properties.getCurrency(), symbols.getULocale(), symbols);
|
||||
}
|
||||
return new CurrencyAmount(result.getNumber(), currency);
|
||||
assert result.currencyCode != null;
|
||||
return new CurrencyAmount(result.getNumber(), Currency.getInstance(result.currencyCode));
|
||||
} else {
|
||||
ppos.setErrorIndex(result.charEnd);
|
||||
return null;
|
||||
@ -152,6 +116,20 @@ public class NumberParserImpl {
|
||||
return createParserFromProperties(properties, symbols, false, optimize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a parser from the given DecimalFormatProperties. This is the endpoint used by
|
||||
* DecimalFormat in production code.
|
||||
*
|
||||
* @param properties
|
||||
* The property bag.
|
||||
* @param symbols
|
||||
* The locale's symbols.
|
||||
* @param parseCurrency
|
||||
* True to force a currency match and use monetary separators; false otherwise.
|
||||
* @param optimize
|
||||
* True to construct the lead-chars; false to disable.
|
||||
* @return An immutable parser object.
|
||||
*/
|
||||
public static NumberParserImpl createParserFromProperties(
|
||||
DecimalFormatProperties properties,
|
||||
DecimalFormatSymbols symbols,
|
||||
@ -244,20 +222,20 @@ public class NumberParserImpl {
|
||||
/// VALIDATORS ///
|
||||
//////////////////
|
||||
|
||||
parser.addMatcher(new RequireNumberMatcher());
|
||||
parser.addMatcher(new RequireNumberValidator());
|
||||
if (isStrict) {
|
||||
parser.addMatcher(new RequireAffixMatcher());
|
||||
parser.addMatcher(new RequireAffixValidator());
|
||||
}
|
||||
if (isStrict && properties.getMinimumExponentDigits() > 0) {
|
||||
parser.addMatcher(new RequireExponentMatcher());
|
||||
parser.addMatcher(new RequireExponentValidator());
|
||||
}
|
||||
if (parseCurrency) {
|
||||
parser.addMatcher(new RequireCurrencyMatcher());
|
||||
parser.addMatcher(new RequireCurrencyValidator());
|
||||
}
|
||||
if (properties.getDecimalPatternMatchRequired()) {
|
||||
boolean patternHasDecimalSeparator = properties.getDecimalSeparatorAlwaysShown()
|
||||
|| properties.getMaximumFractionDigits() != 0;
|
||||
parser.addMatcher(RequireDecimalSeparatorMatcher.getInstance(patternHasDecimalSeparator));
|
||||
parser.addMatcher(RequireDecimalSeparatorValidator.getInstance(patternHasDecimalSeparator));
|
||||
}
|
||||
if (properties.getMultiplier() != null) {
|
||||
// We need to use a math context in order to prevent non-terminating decimal expansions.
|
||||
|
@ -52,7 +52,7 @@ public class ParsedNumber {
|
||||
public static final int FLAG_PERCENT = 0x0002;
|
||||
public static final int FLAG_PERMILLE = 0x0004;
|
||||
public static final int FLAG_HAS_EXPONENT = 0x0008;
|
||||
public static final int FLAG_HAS_DEFAULT_CURRENCY = 0x0010;
|
||||
// public static final int FLAG_HAS_DEFAULT_CURRENCY = 0x0010; // no longer used
|
||||
public static final int FLAG_HAS_DECIMAL_SEPARATOR = 0x0020;
|
||||
public static final int FLAG_NAN = 0x0040;
|
||||
public static final int FLAG_INFINITY = 0x0080;
|
||||
|
@ -21,7 +21,7 @@ public class ParsingUtils {
|
||||
public static final int PARSE_FLAG_USE_FULL_AFFIXES = 0x0100;
|
||||
public static final int PARSE_FLAG_EXACT_AFFIX = 0x0200;
|
||||
public static final int PARSE_FLAG_PLUS_SIGN_ALLOWED = 0x0400;
|
||||
public static final int PARSE_FLAG_OPTIMIZE = 0x1000;
|
||||
public static final int PARSE_FLAG_OPTIMIZE = 0x0800;
|
||||
|
||||
public static void putLeadCodePoints(UnicodeSet input, UnicodeSet output) {
|
||||
for (EntryRange range : input.ranges()) {
|
||||
|
@ -6,7 +6,7 @@ package com.ibm.icu.impl.number.parse;
|
||||
* @author sffc
|
||||
*
|
||||
*/
|
||||
public class RequireAffixMatcher extends ValidationMatcher {
|
||||
public class RequireAffixValidator extends ValidationMatcher {
|
||||
|
||||
@Override
|
||||
public void postProcess(ParsedNumber result) {
|
@ -6,11 +6,11 @@ package com.ibm.icu.impl.number.parse;
|
||||
* @author sffc
|
||||
*
|
||||
*/
|
||||
public class RequireCurrencyMatcher extends ValidationMatcher {
|
||||
public class RequireCurrencyValidator extends ValidationMatcher {
|
||||
|
||||
@Override
|
||||
public void postProcess(ParsedNumber result) {
|
||||
if (result.currencyCode == null && 0 == (result.flags & ParsedNumber.FLAG_HAS_DEFAULT_CURRENCY)) {
|
||||
if (result.currencyCode == null) {
|
||||
result.flags |= ParsedNumber.FLAG_FAIL;
|
||||
}
|
||||
}
|
@ -6,18 +6,18 @@ package com.ibm.icu.impl.number.parse;
|
||||
* @author sffc
|
||||
*
|
||||
*/
|
||||
public class RequireDecimalSeparatorMatcher extends ValidationMatcher {
|
||||
public class RequireDecimalSeparatorValidator extends ValidationMatcher {
|
||||
|
||||
private static final RequireDecimalSeparatorMatcher A = new RequireDecimalSeparatorMatcher(true);
|
||||
private static final RequireDecimalSeparatorMatcher B = new RequireDecimalSeparatorMatcher(false);
|
||||
private static final RequireDecimalSeparatorValidator A = new RequireDecimalSeparatorValidator(true);
|
||||
private static final RequireDecimalSeparatorValidator B = new RequireDecimalSeparatorValidator(false);
|
||||
|
||||
private final boolean patternHasDecimalSeparator;
|
||||
|
||||
public static RequireDecimalSeparatorMatcher getInstance(boolean patternHasDecimalSeparator) {
|
||||
public static RequireDecimalSeparatorValidator getInstance(boolean patternHasDecimalSeparator) {
|
||||
return patternHasDecimalSeparator ? A : B;
|
||||
}
|
||||
|
||||
private RequireDecimalSeparatorMatcher(boolean patternHasDecimalSeparator) {
|
||||
private RequireDecimalSeparatorValidator(boolean patternHasDecimalSeparator) {
|
||||
this.patternHasDecimalSeparator = patternHasDecimalSeparator;
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ package com.ibm.icu.impl.number.parse;
|
||||
* @author sffc
|
||||
*
|
||||
*/
|
||||
public class RequireExponentMatcher extends ValidationMatcher {
|
||||
public class RequireExponentValidator extends ValidationMatcher {
|
||||
|
||||
@Override
|
||||
public void postProcess(ParsedNumber result) {
|
@ -6,7 +6,7 @@ package com.ibm.icu.impl.number.parse;
|
||||
* @author sffc
|
||||
*
|
||||
*/
|
||||
public class RequireNumberMatcher extends ValidationMatcher {
|
||||
public class RequireNumberValidator extends ValidationMatcher {
|
||||
|
||||
@Override
|
||||
public void postProcess(ParsedNumber result) {
|
@ -14,11 +14,11 @@ import java.text.ParsePosition;
|
||||
|
||||
import com.ibm.icu.impl.number.AffixUtils;
|
||||
import com.ibm.icu.impl.number.DecimalFormatProperties;
|
||||
import com.ibm.icu.impl.number.DecimalFormatProperties.ParseMode;
|
||||
import com.ibm.icu.impl.number.Padder.PadPosition;
|
||||
import com.ibm.icu.impl.number.PatternStringParser;
|
||||
import com.ibm.icu.impl.number.PatternStringUtils;
|
||||
import com.ibm.icu.impl.number.parse.NumberParserImpl;
|
||||
import com.ibm.icu.impl.number.parse.NumberParserImpl.ParseMode;
|
||||
import com.ibm.icu.impl.number.parse.ParsedNumber;
|
||||
import com.ibm.icu.lang.UCharacter;
|
||||
import com.ibm.icu.math.BigDecimal;
|
||||
|
Loading…
Reference in New Issue
Block a user