From 2e76b9935762db197997e441419d3c576c385aa9 Mon Sep 17 00:00:00 2001 From: George Rhoten Date: Mon, 11 Aug 2014 21:04:48 +0000 Subject: [PATCH] ICU-11057 Performance improvements and general cleanup for RBNF X-SVN-Rev: 36137 --- .../core/src/com/ibm/icu/text/NFRule.java | 158 ++- .../core/src/com/ibm/icu/text/NFRuleSet.java | 168 ++-- .../src/com/ibm/icu/text/NFSubstitution.java | 164 ++-- .../ibm/icu/text/RuleBasedNumberFormat.java | 74 +- .../com/ibm/icu/dev/test/format/RbnfTest.java | 918 +++++++++--------- 5 files changed, 735 insertions(+), 747 deletions(-) diff --git a/icu4j/main/classes/core/src/com/ibm/icu/text/NFRule.java b/icu4j/main/classes/core/src/com/ibm/icu/text/NFRule.java index d177adbd899..db8b56e91ef 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/text/NFRule.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/text/NFRule.java @@ -1,11 +1,12 @@ /* ******************************************************************************* - * Copyright (C) 1996-2011, International Business Machines Corporation and * + * Copyright (C) 1996-2014, International Business Machines Corporation and * * others. All Rights Reserved. * ******************************************************************************* */ package com.ibm.icu.text; +import java.lang.String; import java.text.ParsePosition; import com.ibm.icu.impl.PatternProps; @@ -56,7 +57,7 @@ final class NFRule { private int radix = 10; /** - * The rule's exponent (the radx rased to the power of the exponsnt + * The rule's exponent (the radix raised to the power of the exponent * equals the rule's divisor) */ private short exponent = 0; @@ -83,7 +84,7 @@ final class NFRule { /** * The RuleBasedNumberFormat that owns this rule */ - private RuleBasedNumberFormat formatter = null; + private final RuleBasedNumberFormat formatter; //----------------------------------------------------------------------- // construction @@ -106,7 +107,7 @@ final class NFRule { // we know we're making at least one rule, so go ahead and // new it up and initialize its basevalue and divisor // (this also strips the rule descriptor, if any, off the - // descripton string) + // description string) NFRule rule1 = new NFRule(ownersOwner); description = rule1.parseRuleDescriptor(description); @@ -121,11 +122,12 @@ final class NFRule { // rule text and substitutions, and return that rule if (brack1 == -1 || brack2 == -1 || brack1 > brack2 || rule1.getBaseValue() == PROPER_FRACTION_RULE - || rule1.getBaseValue() == NEGATIVE_NUMBER_RULE) { - rule1.ruleText = description; - rule1.extractSubstitutions(owner, predecessor, ownersOwner); + || rule1.getBaseValue() == NEGATIVE_NUMBER_RULE) + { + rule1.extractSubstitutions(owner, description, predecessor); return rule1; - } else { + } + else { // if the description does contain a matched pair of brackets, // then it's really shorthand for two rules (with one exception) NFRule rule2 = null; @@ -137,7 +139,8 @@ final class NFRule { if ((rule1.baseValue > 0 && rule1.baseValue % (Math.pow(rule1.radix, rule1.exponent)) == 0) || rule1.baseValue == IMPROPER_FRACTION_RULE - || rule1.baseValue == MASTER_RULE) { + || rule1.baseValue == MASTER_RULE) + { // if it passes that test, new up the second rule. If the // rule set both rules will belong to is a fraction rule @@ -151,18 +154,16 @@ final class NFRule { ++rule1.baseValue; } } - - // if the description began with "x.x" and contains bracketed - // text, it describes both the improper fraction rule and - // the proper fraction rule else if (rule1.baseValue == IMPROPER_FRACTION_RULE) { + // if the description began with "x.x" and contains bracketed + // text, it describes both the improper fraction rule and + // the proper fraction rule rule2.baseValue = PROPER_FRACTION_RULE; } - - // if the description began with "x.0" and contains bracketed - // text, it describes both the master rule and the - // improper fraction rule else if (rule1.baseValue == MASTER_RULE) { + // if the description began with "x.0" and contains bracketed + // text, it describes both the master rule and the + // improper fraction rule rule2.baseValue = rule1.baseValue; rule1.baseValue = IMPROPER_FRACTION_RULE; } @@ -172,14 +173,13 @@ final class NFRule { rule2.radix = rule1.radix; rule2.exponent = rule1.exponent; - // rule2's rule text omits the stuff in brackets: initalize + // rule2's rule text omits the stuff in brackets: initialize // its rule text and substitutions accordingly sbuf.append(description.substring(0, brack1)); if (brack2 + 1 < description.length()) { sbuf.append(description.substring(brack2 + 1)); } - rule2.ruleText = sbuf.toString(); - rule2.extractSubstitutions(owner, predecessor, ownersOwner); + rule2.extractSubstitutions(owner, sbuf.toString(), predecessor); } // rule1's text includes the text in the brackets but omits @@ -191,8 +191,7 @@ final class NFRule { if (brack2 + 1 < description.length()) { sbuf.append(description.substring(brack2 + 1)); } - rule1.ruleText = sbuf.toString(); - rule1.extractSubstitutions(owner, predecessor, ownersOwner); + rule1.extractSubstitutions(owner, sbuf.toString(), predecessor); // if we only have one rule, return it; if we have two, return // a two-element array containing them (notice that rule2 goes @@ -225,7 +224,7 @@ final class NFRule { * @param description The rule's description * @return If "description" included a rule descriptor, this is * "description" with the descriptor and any trailing whitespace - * stripped off. Otherwise; it's "descriptor" unchangd. + * stripped off. Otherwise; it's "descriptor" unchanged. */ private String parseRuleDescriptor(String description) { String descriptor; @@ -242,13 +241,14 @@ final class NFRule { // description descriptor = description.substring(0, p); ++p; - while (p < description.length() && PatternProps.isWhiteSpace(description.charAt(p))) + while (p < description.length() && PatternProps.isWhiteSpace(description.charAt(p))) { ++p; + } description = description.substring(p); // check first to see if the rule descriptor matches the token // for one of the special rules. If it does, set the base - // value to the correct identfier value + // value to the correct identifier value if (descriptor.equals("-x")) { setBaseValue(NEGATIVE_NUMBER_RULE); } @@ -261,13 +261,12 @@ final class NFRule { else if (descriptor.equals("x.0")) { setBaseValue(MASTER_RULE); } - - // if the rule descriptor begins with a digit, it's a descriptor - // for a normal rule else if (descriptor.charAt(0) >= '0' && descriptor.charAt(0) <= '9') { - StringBuilder tempValue = new StringBuilder(); + // if the rule descriptor begins with a digit, it's a descriptor + // for a normal rule + long tempValue = 0; + char c = 0; p = 0; - char c = ' '; // begin parsing the descriptor: copy digits // into "tempValue", skip periods, commas, and spaces, @@ -276,50 +275,44 @@ final class NFRule { while (p < descriptor.length()) { c = descriptor.charAt(p); if (c >= '0' && c <= '9') { - tempValue.append(c); + tempValue = tempValue * 10 + (c - '0'); } else if (c == '/' || c == '>') { break; } - else if (PatternProps.isWhiteSpace(c) || c == ',' || c == '.') { - } - else { - throw new IllegalArgumentException("Illegal character in rule descriptor"); + else if (!PatternProps.isWhiteSpace(c) && c != ',' && c != '.') { + throw new IllegalArgumentException("Illegal character " + c + " in rule descriptor"); } ++p; } - // tempValue now contains a string representation of the - // rule's base value with the punctuation stripped out. - // Set the rule's base value accordingly - setBaseValue(Long.parseLong(tempValue.toString())); + // Set the rule's base value according to what we parsed + setBaseValue(tempValue); // if we stopped the previous loop on a slash, we're // now parsing the rule's radix. Again, accumulate digits // in tempValue, skip punctuation, stop on a > mark, and // throw an exception on anything else if (c == '/') { - tempValue.setLength(0); + tempValue = 0; ++p; while (p < descriptor.length()) { c = descriptor.charAt(p); if (c >= '0' && c <= '9') { - tempValue.append(c); + tempValue = tempValue * 10 + (c - '0'); } else if (c == '>') { break; } - else if (PatternProps.isWhiteSpace(c) || c == ',' || c == '.') { - } - else { - throw new IllegalArgumentException("Illegal character is rule descriptor"); + else if (!PatternProps.isWhiteSpace(c) && c != ',' && c != '.') { + throw new IllegalArgumentException("Illegal character " + c + " in rule descriptor"); } ++p; } - // tempValue now contain's the rule's radix. Set it + // tempValue now contains the rule's radix. Set it // accordingly, and recalculate the rule's exponent - radix = Integer.parseInt(tempValue.toString()); + radix = (int)tempValue; if (radix == 0) { throw new IllegalArgumentException("Rule can't have radix of 0"); } @@ -363,15 +356,22 @@ final class NFRule { * from the rule's rule text. * @param owner The rule set containing this rule * @param predecessor The rule preseding this one in "owners" rule list - * @param ownersOwner The RuleBasedFormat that owns this rule + * @param ruleText The rule text */ private void extractSubstitutions(NFRuleSet owner, - NFRule predecessor, - RuleBasedNumberFormat ownersOwner) { - sub1 = extractSubstitution(owner, predecessor, ownersOwner); - sub2 = extractSubstitution(owner, predecessor, ownersOwner); + String ruleText, + NFRule predecessor) { + this.ruleText = ruleText; + sub1 = extractSubstitution(owner, predecessor); + sub2 = extractSubstitution(owner, predecessor); } + private static final String[] RULE_PREFIXES = new String[] { + "<<", "<%", "<#", "<0", + ">>", ">%", ">#", ">0", + "=%", "=#", "=0" + }; + /** * Searches the rule's rule text for the first substitution token, * creates a substitution based on it, and removes the token from @@ -379,39 +379,35 @@ final class NFRule { * @param owner The rule set containing this rule * @param predecessor The rule preceding this one in the rule set's * rule list - * @param ownersOwner The RuleBasedNumberFormat that owns this rule * @return The newly-created substitution. This is never null; if * the rule text doesn't contain any substitution tokens, this will * be a NullSubstitution. */ private NFSubstitution extractSubstitution(NFRuleSet owner, - NFRule predecessor, - RuleBasedNumberFormat ownersOwner) { - NFSubstitution result = null; + NFRule predecessor) { + NFSubstitution result; int subStart; int subEnd; // search the rule's rule text for the first two characters of // a substitution token - subStart = indexOfAny(new String[] { "<<", "<%", "<#", "<0", - ">>", ">%", ">#", ">0", - "=%", "=#", "=0" } ); + subStart = indexOfAny(ruleText, RULE_PREFIXES); // if we didn't find one, create a null substitution positioned // at the end of the rule text if (subStart == -1) { return NFSubstitution.makeSubstitution(ruleText.length(), this, predecessor, - owner, ownersOwner, ""); + owner, this.formatter, ""); } // special-case the ">>>" token, since searching for the > at the // end will actually find the > in the middle if (ruleText.substring(subStart).startsWith(">>>")) { subEnd = subStart + 2; - + } + else { // otherwise the substitution token ends with the same character // it began with - } else { char c = ruleText.charAt(subStart); subEnd = ruleText.indexOf(c, subStart + 1); // special case for '<%foo<<' @@ -429,14 +425,14 @@ final class NFRule { // at the end of the rule if (subEnd == -1) { return NFSubstitution.makeSubstitution(ruleText.length(), this, predecessor, - owner, ownersOwner, ""); + owner, this.formatter, ""); } // if we get here, we have a real substitution token (or at least // some text bounded by substitution token characters). Use // makeSubstitution() to create the right kind of substitution result = NFSubstitution.makeSubstitution(subStart, this, predecessor, owner, - ownersOwner, ruleText.substring(subStart, subEnd + 1)); + this.formatter, ruleText.substring(subStart, subEnd + 1)); // remove the substitution from the rule text ruleText = ruleText.substring(0, subStart) + ruleText.substring(subEnd + 1); @@ -450,7 +446,7 @@ final class NFRule { * constructed. It should not be used at any other time. * @param newBaseValue The new base value for the rule. */ - public final void setBaseValue(long newBaseValue) { + final void setBaseValue(long newBaseValue) { // set the base value baseValue = newBaseValue; @@ -473,10 +469,10 @@ final class NFRule { if (sub2 != null) { sub2.setDivisor(radix, exponent); } - + } + else { // if this is a special rule, its radix and exponent are basically // ignored. Set them to "safe" default values - } else { radix = 10; exponent = 0; } @@ -515,13 +511,15 @@ final class NFRule { * _any_ of the strings in "strings"). If none of the strings in * "strings" is found in the rule's rule text, returns -1. */ - private int indexOfAny(String[] strings) { - int pos; + private static int indexOfAny(String ruleText, String[] strings) { int result = -1; - for (int i = 0; i < strings.length; i++) { - pos = ruleText.indexOf(strings[i]); - if (pos != -1 && (result == -1 || pos < result)) { - result = pos; + if (!ruleText.isEmpty()) { + int pos; + for (String string : strings) { + pos = ruleText.indexOf(string); + if (pos != -1 && (result == -1 || pos < result)) { + result = pos; + } } } return result; @@ -587,8 +585,7 @@ final class NFRule { else { result.append(String.valueOf(baseValue)); if (radix != 10) { - result.append('/'); - result.append(String.valueOf(radix)); + result.append('/').append(radix); } int numCarets = expectedExponent() - exponent; for (int i = 0; i < numCarets; i++) @@ -707,11 +704,8 @@ final class NFRule { // a modulus substitution, its base value isn't an even multiple // of 100, and the value we're trying to format _is_ an even // multiple of 100. This is called the "rollback rule." - if ((sub1.isModulusSubstitution()) || (sub2.isModulusSubstitution())) { - return (number % Math.pow(radix, exponent)) == 0 - && (baseValue % Math.pow(radix, exponent)) != 0; - } - return false; + return ((sub1.isModulusSubstitution()) || (sub2.isModulusSubstitution())) + && (number % Math.pow(radix, exponent)) == 0 && (baseValue % Math.pow(radix, exponent)) != 0; } //----------------------------------------------------------------------- @@ -1056,7 +1050,7 @@ final class NFRule { RbnfLenientScanner scanner = formatter.getLenientScanner(); if (scanner != null) { - return scanner.prefixLength(str, prefix); + return scanner.prefixLength(str, prefix); } // go through all this grief if we're in lenient-parse mode @@ -1323,7 +1317,7 @@ final class NFRule { } RbnfLenientScanner scanner = formatter.getLenientScanner(); if (scanner != null) { - return scanner.allIgnorable(str); + return scanner.allIgnorable(str); } return false; diff --git a/icu4j/main/classes/core/src/com/ibm/icu/text/NFRuleSet.java b/icu4j/main/classes/core/src/com/ibm/icu/text/NFRuleSet.java index 32ea6769577..4b0fb968c95 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/text/NFRuleSet.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/text/NFRuleSet.java @@ -1,6 +1,6 @@ /* ******************************************************************************* - * Copyright (C) 1996-2012, International Business Machines Corporation and * + * Copyright (C) 1996-2014, International Business Machines Corporation and * * others. All Rights Reserved. * ******************************************************************************* */ @@ -57,20 +57,20 @@ final class NFRuleSet { * behavior than a regular rule set. */ private boolean isFractionRuleSet = false; - + /** - * True if the rule set is parseable. + * True if the rule set is parseable. */ private boolean isParseable = true; - + /** * Used to limit recursion for bad rule sets. */ private int recursionCount = 0; /** - * Limit of recursion. - */ + * Limit of recursion. + */ private static final int RECURSION_LIMIT = 50; //----------------------------------------------------------------------- @@ -88,9 +88,9 @@ final class NFRuleSet { public NFRuleSet(String[] descriptions, int index) throws IllegalArgumentException { String description = descriptions[index]; - if (description.length() == 0) { - throw new IllegalArgumentException("Empty rule set description"); - } + if (description.length() == 0) { + throw new IllegalArgumentException("Empty rule set description"); + } // if the description begins with a rule set name (the rule set // name can be omitted in formatter descriptions that consist @@ -100,18 +100,18 @@ final class NFRuleSet { int pos = description.indexOf(':'); if (pos == -1) { throw new IllegalArgumentException("Rule set name doesn't end in colon"); - } else { + } + else { name = description.substring(0, pos); - while (pos < description.length() && PatternProps.isWhiteSpace(description. - charAt(++pos))) { + while (pos < description.length() && PatternProps.isWhiteSpace(description.charAt(++pos))) { } description = description.substring(pos); descriptions[index] = description; } - - // if the description doesn't begin with a rule set name, its - // name is "%default" - } else { + } + else { + // if the description doesn't begin with a rule set name, its + // name is "%default" name = "%default"; } @@ -123,7 +123,7 @@ final class NFRuleSet { name = name.substring(0,name.length()-8); // Remove the @noparse from the name isParseable = false; } - + // all of the other members of NFRuleSet are initialized // by parseRules() } @@ -169,19 +169,19 @@ final class NFRuleSet { // we keep track of the rule before the one we're currently working // on solely to support >>> substitutions NFRule predecessor = null; - for (int i = 0; i < ruleDescriptions.size(); i++) { + for (String ruleDescription : ruleDescriptions) { // makeRules (a factory method on NFRule) will return either // a single rule or an array of rules. Either way, add them // to our rule vector - Object temp = NFRule.makeRules(ruleDescriptions.get(i), - this, predecessor, owner); + Object temp = NFRule.makeRules(ruleDescription, + this, predecessor, owner); if (temp instanceof NFRule) { - tempRules.add((NFRule)temp); - predecessor = (NFRule)temp; + tempRules.add((NFRule) temp); + predecessor = (NFRule) temp; } else if (temp instanceof NFRule[]) { - NFRule[] rulesToAdd = (NFRule[])temp; + NFRule[] rulesToAdd = (NFRule[]) temp; for (int j = 0; j < rulesToAdd.length; j++) { tempRules.add(rulesToAdd[j]); @@ -200,7 +200,7 @@ final class NFRuleSet { // (this isn't a for loop because we might be deleting items from // the vector-- we want to make sure we only increment i when - // we _didn't_ delete aything from the vector) + // we _didn't_ delete anything from the vector) int i = 0; while (i < tempRules.size()) { NFRule rule = tempRules.get(i); @@ -252,8 +252,8 @@ final class NFRuleSet { // the default base value for the next rule default: if (rule.getBaseValue() < defaultBaseValue) { - throw new IllegalArgumentException("Rules are not in order, base: " + - rule.getBaseValue() + " < " + defaultBaseValue); + throw new IllegalArgumentException("Rules are not in order, base: " + + rule.getBaseValue() + " < " + defaultBaseValue); } defaultBaseValue = rule.getBaseValue(); if (!isFractionRuleSet) { @@ -300,13 +300,13 @@ final class NFRuleSet { NFRuleSet that2 = (NFRuleSet)that; if (!name.equals(that2.name) - || !Utility.objectEquals(negativeNumberRule, that2.negativeNumberRule) - || !Utility.objectEquals(fractionRules[0], that2.fractionRules[0]) - || !Utility.objectEquals(fractionRules[1], that2.fractionRules[1]) - || !Utility.objectEquals(fractionRules[2], that2.fractionRules[2]) - || rules.length != that2.rules.length - || isFractionRuleSet != that2.isFractionRuleSet) { - + || !Utility.objectEquals(negativeNumberRule, that2.negativeNumberRule) + || !Utility.objectEquals(fractionRules[0], that2.fractionRules[0]) + || !Utility.objectEquals(fractionRules[1], that2.fractionRules[1]) + || !Utility.objectEquals(fractionRules[2], that2.fractionRules[2]) + || rules.length != that2.rules.length + || isFractionRuleSet != that2.isFractionRuleSet) + { return false; } @@ -317,11 +317,11 @@ final class NFRuleSet { } } - // ...and if we make it here, tney're equal + // ...and if we make it here, they're equal return true; } } - + public int hashCode() { assert false : "hashCode not designed"; return 42; @@ -338,25 +338,25 @@ final class NFRuleSet { StringBuilder result = new StringBuilder(); // the rule set name goes first... - result.append(name + ":\n"); + result.append(name).append(":\n"); // followed by the regular rules... for (int i = 0; i < rules.length; i++) { - result.append(" " + rules[i].toString() + "\n"); + result.append(" ").append(rules[i].toString()).append("\n"); } // followed by the special rules (if they exist) if (negativeNumberRule != null) { - result.append(" " + negativeNumberRule.toString() + "\n"); + result.append(" ").append(negativeNumberRule.toString()).append("\n"); } if (fractionRules[0] != null) { - result.append(" " + fractionRules[0].toString() + "\n"); + result.append(" ").append(fractionRules[0].toString()).append("\n"); } if (fractionRules[1] != null) { - result.append(" " + fractionRules[1].toString() + "\n"); + result.append(" ").append(fractionRules[1].toString()).append("\n"); } if (fractionRules[2] != null) { - result.append(" " + fractionRules[2].toString() + "\n"); + result.append(" ").append(fractionRules[2].toString()).append("\n"); } return result.toString(); @@ -441,7 +441,7 @@ final class NFRuleSet { } /** - * Selects an apropriate rule for formatting the number. + * Selects an appropriate rule for formatting the number. * @param number The number being formatted. * @return The rule that should be used to format it */ @@ -480,9 +480,9 @@ final class NFRuleSet { if (fractionRules[2] != null) { return fractionRules[2]; - // and if we haven't yet returned a rule, use findNormalRule() - // to find the applicable rule } else { + // and if we haven't yet returned a rule, use findNormalRule() + // to find the applicable rule return findNormalRule(Math.round(number)); } } @@ -535,40 +535,40 @@ final class NFRuleSet { // the next rule's base value) int lo = 0; int hi = rules.length; - if (hi > 0) { - while (lo < hi) { - int mid = (lo + hi) >>> 1; - if (rules[mid].getBaseValue() == number) { - return rules[mid]; - } - else if (rules[mid].getBaseValue() > number) { - hi = mid; - } - else { - lo = mid + 1; - } - } - if (hi == 0) { // bad rule set - throw new IllegalStateException("The rule set " + name + " cannot format the value " + number); - } - NFRule result = rules[hi - 1]; - - // use shouldRollBack() to see whether we need to invoke the - // rollback rule (see shouldRollBack()'s documentation for - // an explanation of the rollback rule). If we do, roll back - // one rule and return that one instead of the one we'd normally - // return - if (result.shouldRollBack(number)) { - if (hi == 1) { // bad rule set - throw new IllegalStateException("The rule set " + name + " cannot roll back from the rule '" + + if (hi > 0) { + while (lo < hi) { + int mid = (lo + hi) >>> 1; + if (rules[mid].getBaseValue() == number) { + return rules[mid]; + } + else if (rules[mid].getBaseValue() > number) { + hi = mid; + } + else { + lo = mid + 1; + } + } + if (hi == 0) { // bad rule set + throw new IllegalStateException("The rule set " + name + " cannot format the value " + number); + } + NFRule result = rules[hi - 1]; + + // use shouldRollBack() to see whether we need to invoke the + // rollback rule (see shouldRollBack()'s documentation for + // an explanation of the rollback rule). If we do, roll back + // one rule and return that one instead of the one we'd normally + // return + if (result.shouldRollBack(number)) { + if (hi == 1) { // bad rule set + throw new IllegalStateException("The rule set " + name + " cannot roll back from the rule '" + result + "'"); + } + result = rules[hi - 2]; + } + return result; } - result = rules[hi - 2]; - } - return result; - } - // else use the master rule - return fractionRules[2]; + // else use the master rule + return fractionRules[2]; } /** @@ -609,8 +609,8 @@ final class NFRuleSet { for (int i = 0; i < rules.length; i++) { // "numerator" is the numerator of the fraction is the // denominator is the LCD. The numerator if the the rule's - // base value is the denomiator is "numerator" times the - // base value divided bythe LCD. Here we check to see if + // base value is the denominator is "numerator" times the + // base value divided by the LCD. Here we check to see if // that's an integer, and if not, how close it is to being // an integer. tempDifference = numerator * rules[i].getBaseValue() % leastCommonMultiple; @@ -639,7 +639,7 @@ final class NFRuleSet { // value, then the first one (the one we found above) is used if // the numerator of the fraction is 1 and the second one is used if // the numerator of the fraction is anything else (this lets us - // do things like "one third"/"two thirds" without haveing to define + // do things like "one third"/"two thirds" without having to define // a whole bunch of extra rule sets) if (winner + 1 < rules.length && rules[winner + 1].getBaseValue() == rules[winner].getBaseValue()) { @@ -700,7 +700,7 @@ final class NFRuleSet { /** * Parses a string. Matches the string to be parsed against each * of its rules (with a base value less than upperBound) and returns - * the value produced by the rule that matched the most charcters + * the value produced by the rule that matched the most characters * in the source string. * @param text The string to parse * @param parsePosition The initial position is ignored and assumed @@ -732,7 +732,7 @@ final class NFRuleSet { return result; } - // start by trying the nehative number rule (if there is one) + // start by trying the negative number rule (if there is one) if (negativeNumberRule != null) { tempResult = negativeNumberRule.doParse(text, parsePosition, false, upperBound); if (parsePosition.getIndex() > highWaterMark.getIndex()) { @@ -764,7 +764,7 @@ final class NFRuleSet { // finally, go through the regular rules one at a time. We start // at the end of the list because we want to try matching the most - // sigificant rule first (this helps ensure that we parse + // significant rule first (this helps ensure that we parse // "five thousand three hundred six" as // "(five thousand) (three hundred) (six)" rather than // "((five thousand three) hundred) (six)"). Skip rules whose @@ -788,9 +788,9 @@ final class NFRuleSet { parsePosition.setIndex(0); } - // finally, update the parse postion we were passed to point to the + // finally, update the parse position we were passed to point to the // first character we didn't use, and return the result that - // cporresponds to that string of characters + // corresponds to that string of characters parsePosition.setIndex(highWaterMark.getIndex()); // commented out because the error-index API on ParsePosition isn't there in 1.1.x // if (parsePosition.getIndex() == 0) { 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 b5b39dc2731..8af12ff23a2 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 @@ -1,6 +1,6 @@ /* ******************************************************************************* - * Copyright (C) 1996-2011, International Business Machines Corporation and * + * Copyright (C) 1996-2014, International Business Machines Corporation and * * others. All Rights Reserved. * ******************************************************************************* */ @@ -26,24 +26,24 @@ abstract class NFSubstitution { /** * The substitution's position in the rule text of the rule that owns it */ - int pos; + final int pos; /** * The rule set this substitution uses to format its result, or null. * (Either this or numberFormat has to be non-null.) */ - NFRuleSet ruleSet = null; + final NFRuleSet ruleSet; /** * The DecimalFormat this substitution uses to format its result, * or null. (Either this or ruleSet has to be non-null.) */ - DecimalFormat numberFormat = null; - + final DecimalFormat numberFormat; + /** * Link to the RBNF so that we can access its decimalFormat if need be. */ - RuleBasedNumberFormat rbnf = null; + final RuleBasedNumberFormat rbnf; //----------------------------------------------------------------------- // construction @@ -73,7 +73,7 @@ abstract class NFSubstitution { NFRuleSet ruleSet, RuleBasedNumberFormat formatter, String description) { - // if the description is empty, return a NummSubstitution + // if the description is empty, return a NullSubstitution if (description.length() == 0) { return new NullSubstitution(pos, ruleSet, formatter, description); } @@ -197,36 +197,34 @@ abstract class NFSubstitution { // format its result if (description.length() == 0) { this.ruleSet = ruleSet; + this.numberFormat = null; } - - // if the description contains a rule set name, that's the rule - // set we use to format the result: get a reference to the - // names rule set else if (description.charAt(0) == '%') { + // if the description contains a rule set name, that's the rule + // set we use to format the result: get a reference to the + // names rule set this.ruleSet = formatter.findRuleSet(description); + this.numberFormat = null; } - - // if the description begins with 0 or #, treat it as a - // DecimalFormat pattern, and initialize a DecimalFormat with - // that pattern (then set it to use the DecimalFormatSymbols - // belonging to our formatter) else if (description.charAt(0) == '#' || description.charAt(0) == '0') { - this.numberFormat = new DecimalFormat(description); - this.numberFormat.setDecimalFormatSymbols(formatter.getDecimalFormatSymbols()); + // if the description begins with 0 or #, treat it as a + // DecimalFormat pattern, and initialize a DecimalFormat with + // that pattern (then set it to use the DecimalFormatSymbols + // belonging to our formatter) + this.ruleSet = null; + this.numberFormat = new DecimalFormat(description, formatter.getDecimalFormatSymbols()); } - - // if the description is ">>>", this substitution bypasses the - // usual rule-search process and always uses the rule that precedes - // it in its own rule set's rule list (this is used for place-value - // notations: formats where you want to see a particular part of - // a number even when it's 0) else if (description.charAt(0) == '>') { + // if the description is ">>>", this substitution bypasses the + // usual rule-search process and always uses the rule that precedes + // it in its own rule set's rule list (this is used for place-value + // notations: formats where you want to see a particular part of + // a number even when it's 0) this.ruleSet = ruleSet; // was null, thai rules added to control space this.numberFormat = null; } - - // and of the description is none of these things, it's a syntax error else { + // and of the description is none of these things, it's a syntax error throw new IllegalArgumentException("Illegal substitution syntax"); } } @@ -264,7 +262,7 @@ abstract class NFSubstitution { NFSubstitution that2 = (NFSubstitution)that; return pos == that2.pos - && (ruleSet == null ? that2.ruleSet == null : true) // can't compare tree structure, no .equals or recurse + && (ruleSet != null || that2.ruleSet == null) // can't compare tree structure, no .equals or recurse && (numberFormat == null ? (that2.numberFormat == null) : numberFormat.equals(that2.numberFormat)); } return false; @@ -405,7 +403,7 @@ abstract class NFSubstitution { * lower than this are considered * @param lenientParse If true and matching against rules fails, * the substitution will also try matching the text against - * numerals using a default-costructed NumberFormat. If false, + * numerals using a default-constructed NumberFormat. If false, * no extra work is done. (This value is false whenever the * formatter isn't in lenient-parse mode, but is also false * under some conditions even when the formatter _is_ in @@ -472,7 +470,7 @@ abstract class NFSubstitution { // substitution results. For a rule in a fraction rule set, // it's the numerator substitution's result divided by // the rule's base value. Results from same-value substitutions - // propagate back upard, and null substitutions don't affect + // propagate back upward, and null substitutions don't affect // the result. result = composeRuleValue(result, baseValue); if (result == (long)result) { @@ -607,7 +605,7 @@ class SameValueSubstitution extends NFSubstitution { * Returns newRuleValue and ignores oldRuleValue. (The value we got * matching the substitution supersedes the value of the rule * that owns the substitution.) - * @param newRuleValue The value resulting from matching the substituion + * @param newRuleValue The value resulting from matching the substitution * @param oldRuleValue The value of the rule containing the * substitution. * @return newRuleValue @@ -667,9 +665,9 @@ class MultiplierSubstitution extends NFSubstitution { * also maintains its own copy of its rule's divisor. * @param pos The substitution's position in its rule's rule text * @param divisor The owning rule's divisor - * @ruleSet The ruleSet this substitution uses to format its result - * @formatter The formatter that owns this substitution - * @description The description describing this substitution + * @param ruleSet The ruleSet this substitution uses to format its result + * @param formatter The formatter that owns this substitution + * @param description The description describing this substitution */ MultiplierSubstitution(int pos, double divisor, @@ -825,7 +823,7 @@ class ModulusSubstitution extends NFSubstitution { //----------------------------------------------------------------------- /** - * Constructs a ModulusSubstution. In addition to the inherited + * Constructs a ModulusSubstitution. In addition to the inherited * members, a ModulusSubstitution keeps track of the divisor of the * rule that owns it, and may also keep a reference to the rule * that precedes the rule containing this substitution in the rule @@ -850,12 +848,12 @@ class ModulusSubstitution extends NFSubstitution { // we keep a copy of the divisor this.divisor = divisor; - if (divisor == 0) { // this will cause recursion - throw new IllegalStateException("Substitution with bad divisor (" + divisor + ") "+ description.substring(0, pos) + - " | " + description.substring(pos)); - } + if (divisor == 0) { // this will cause recursion + throw new IllegalStateException("Substitution with bad divisor (" + divisor + ") "+ description.substring(0, pos) + + " | " + description.substring(pos)); + } - // the >>> token doesn't alter how this substituion calculates the + // the >>> token doesn't alter how this substitution calculates the // values it uses for formatting and parsing, but it changes // what's done with that value after it's obtained: >>> short- // circuits the rule-search process and goes straight to the @@ -870,15 +868,15 @@ class ModulusSubstitution extends NFSubstitution { /** * Makes the substitution's divisor conform to that of the rule * that owns it. Used when the divisor is determined after creation. - * @param radix The radix of the divsor. + * @param radix The radix of the divisor. * @param exponent The exponent of the divisor. */ public void setDivisor(int radix, int exponent) { divisor = Math.pow(radix, exponent); - if (divisor == 0) { // this will cause recursion - throw new IllegalStateException("Substitution with bad divisor"); - } + if (divisor == 0) { // this will cause recursion + throw new IllegalStateException("Substitution with bad divisor"); + } } //----------------------------------------------------------------------- @@ -914,7 +912,7 @@ class ModulusSubstitution extends NFSubstitution { * If this is a >>> substitution, use ruleToUse to fill in * the substitution. Otherwise, just use the superclass function. * @param number The number being formatted - * @toInsertInto The string to insert the result of this substitution + * @param toInsertInto The string to insert the result of this substitution * into * @param position The position of the rule text in toInsertInto */ @@ -937,7 +935,7 @@ class ModulusSubstitution extends NFSubstitution { * If this is a >>> substitution, use ruleToUse to fill in * the substitution. Otherwise, just use the superclass function. * @param number The number being formatted - * @toInsertInto The string to insert the result of this substitution + * @param toInsertInto The string to insert the result of this substitution * into * @param position The position of the rule text in toInsertInto */ @@ -1022,7 +1020,7 @@ class ModulusSubstitution extends NFSubstitution { * Returns the highest multiple of the rule's divisor that its less * than or equal to oldRuleValue, plus newRuleValue. (The result * is the sum of the result of parsing the substitution plus the - * base valueof the rule containing the substitution, but if the + * base value of the rule containing the substitution, but if the * owning rule's base value isn't an even multiple of its divisor, * we have to round it down to a multiple of the divisor, or we * get unwanted digits in the result.) @@ -1038,7 +1036,7 @@ class ModulusSubstitution extends NFSubstitution { /** * Sets the upper bound down to the owning rule's divisor * @param oldUpperBound Ignored - * @return The owning rule's dvisor + * @return The owning rule's divisor */ public double calcUpperBound(double oldUpperBound) { return divisor; @@ -1240,11 +1238,11 @@ class FractionalPartSubstitution extends NFSubstitution { } else { // int numberToFormat = (int)Math.round(transformNumber(number) * Math.pow( // 10, MAXDECIMALDIGITS)); -// long numberToFormat = (long)Math.round(transformNumber(number) * Math.pow(10, MAXDECIMALDIGITS)); +// long numberToFormat = (long)Math.round(transformNumber(number) * Math.pow(10, MAXDECIMALDIGITS)); - // just print to string and then use that - DigitList dl = new DigitList(); - dl.set(number, 20, true); + // just print to string and then use that + DigitList dl = new DigitList(); + dl.set(number, 20, true); // this flag keeps us from formatting trailing zeros. It starts // out false because we're pulling from the right, and switches @@ -1266,26 +1264,26 @@ class FractionalPartSubstitution extends NFSubstitution { // numberToFormat /= 10; // } - boolean pad = false; - while (dl.count > Math.max(0, dl.decimalAt)) { - if (pad && useSpaces) { - toInsertInto.insert(position + pos, ' '); - } else { - pad = true; - } - ruleSet.format(dl.digits[--dl.count] - '0', toInsertInto, position + pos); - } - while (dl.decimalAt < 0) { - if (pad && useSpaces) { - toInsertInto.insert(position + pos, ' '); - } else { - pad = true; - } - ruleSet.format(0, toInsertInto, position + pos); - ++dl.decimalAt; + boolean pad = false; + while (dl.count > Math.max(0, dl.decimalAt)) { + if (pad && useSpaces) { + toInsertInto.insert(position + pos, ' '); + } else { + pad = true; + } + ruleSet.format(dl.digits[--dl.count] - '0', toInsertInto, position + pos); + } + while (dl.decimalAt < 0) { + if (pad && useSpaces) { + toInsertInto.insert(position + pos, ' '); + } else { + pad = true; + } + ruleSet.format(0, toInsertInto, position + pos); + ++dl.decimalAt; + } } } - } /** * Returns the fractional part of the number, which will always be @@ -1332,16 +1330,16 @@ class FractionalPartSubstitution extends NFSubstitution { // doParse() if (!byDigits) { return super.doParse(text, parsePosition, baseValue, 0, lenientParse); - - // if we ARE in byDigits mode, parse the text one digit at a time - // using this substitution's owning rule set (we do this by setting - // upperBound to 10 when calling doParse() ) until we reach - // nonmatching text - } else { + } + else { + // if we ARE in byDigits mode, parse the text one digit at a time + // using this substitution's owning rule set (we do this by setting + // upperBound to 10 when calling doParse() ) until we reach + // nonmatching text String workText = text; ParsePosition workPos = new ParsePosition(1); double result = 0; - int digit; + int digit; // double p10 = 0.1; // while (workText.length() > 0 && workPos.getIndex() != 0) { @@ -1364,7 +1362,7 @@ class FractionalPartSubstitution extends NFSubstitution { // } - DigitList dl = new DigitList(); + DigitList dl = new DigitList(); while (workText.length() > 0 && workPos.getIndex() != 0) { workPos.setIndex(0); digit = ruleSet.parse(workText, workPos, 10).intValue(); @@ -1376,7 +1374,7 @@ class FractionalPartSubstitution extends NFSubstitution { } if (workPos.getIndex() != 0) { - dl.append('0'+digit); + dl.append('0'+digit); parsePosition.setIndex(parsePosition.getIndex() + workPos.getIndex()); workText = workText.substring(workPos.getIndex()); @@ -1386,7 +1384,7 @@ class FractionalPartSubstitution extends NFSubstitution { } } } - result = dl.count == 0 ? 0 : dl.getDouble(); + result = dl.count == 0 ? 0 : dl.getDouble(); result = composeRuleValue(result, baseValue); return new Double(result); @@ -1430,7 +1428,7 @@ class FractionalPartSubstitution extends NFSubstitution { /** * A substitution that formats the absolute value of the number. - * This substition is represented by >> in a negative-number rule. + * This substitution is represented by >> in a negative-number rule. */ class AbsoluteValueSubstitution extends NFSubstitution { //----------------------------------------------------------------------- @@ -1475,7 +1473,7 @@ class AbsoluteValueSubstitution extends NFSubstitution { //----------------------------------------------------------------------- /** - * Returns the addtive inverse of the result of parsing the + * Returns the additive inverse of the result of parsing the * substitution (this supersedes the earlier partial result) * @param newRuleValue The result of parsing the substitution * @param oldRuleValue The partial parse result prior to calling @@ -1539,7 +1537,7 @@ class NumeratorSubstitution extends NFSubstitution { //----------------------------------------------------------------------- /** - * Constructs a NumberatorSubstitution. In addition to the inherited + * Constructs a NumeratorSubstitution. In addition to the inherited * fields, a NumeratorSubstitution keeps track of a denominator, which * is merely the base value of the rule that owns it. */ @@ -1734,7 +1732,7 @@ class NumeratorSubstitution extends NFSubstitution { } /** - * Sets the uper bound down to this rule's base value + * Sets the upper bound down to this rule's base value * @param oldUpperBound Ignored * @return The base value of the rule owning this substitution */ diff --git a/icu4j/main/classes/core/src/com/ibm/icu/text/RuleBasedNumberFormat.java b/icu4j/main/classes/core/src/com/ibm/icu/text/RuleBasedNumberFormat.java index 7950eaae0f1..6ad0477ef66 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/text/RuleBasedNumberFormat.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/text/RuleBasedNumberFormat.java @@ -68,7 +68,7 @@ import com.ibm.icu.util.UResourceBundleIterator; *

In these rules, the base value is spelled out explicitly and set off from the * rule's output text with a colon. The rules are in a sorted list, and a rule is applicable * to all numbers from its own base value to one less than the next rule's base value. The - * ">>" token is called a substitution and tells the fomatter to + * ">>" token is called a substitution and tells the formatter to * isolate the number's ones digit, format it using this same set of rules, and place the * result at the position of the ">>" token. Text in brackets is omitted if * the number being formatted is an even multiple of 10 (the hyphen is a literal hyphen; 24 @@ -212,7 +212,7 @@ import com.ibm.icu.util.UResourceBundleIterator; * bv: * bv specifies the rule's base value. bv is a decimal * number expressed using ASCII digits. bv may contain spaces, period, and commas, - * which are irgnored. The rule's divisor is the highest power of 10 less than or equal to + * which are ignored. The rule's divisor is the highest power of 10 less than or equal to * the base value. * * @@ -712,7 +712,7 @@ public class RuleBasedNumberFormat extends NumberFormat { * See the class documentation for a complete explanation of the description * syntax. * @param localizations a list of localizations for the rule set names in the description. - * @param locale A ulocale that governs which characters are used for + * @param locale A ULocale that governs which characters are used for * formatting values in numerals, and determines which characters are equivalent in * lenient parsing. * @stable ICU 3.2 @@ -724,7 +724,7 @@ public class RuleBasedNumberFormat extends NumberFormat { /** * Creates a RuleBasedNumberFormat from a predefined description. The selector - * code choosed among three possible predefined formats: spellout, ordinal, + * code chooses among three possible predefined formats: spellout, ordinal, * and duration. * @param locale The locale for the formatter. * @param format A selector code specifying which kind of formatter to create for that @@ -740,7 +740,7 @@ public class RuleBasedNumberFormat extends NumberFormat { /** * Creates a RuleBasedNumberFormat from a predefined description. The selector - * code choosed among three possible predefined formats: spellout, ordinal, + * code chooses among three possible predefined formats: spellout, ordinal, * and duration. * @param locale The locale for the formatter. * @param format A selector code specifying which kind of formatter to create for that @@ -764,24 +764,18 @@ public class RuleBasedNumberFormat extends NumberFormat { ULocale uloc = bundle.getULocale(); setLocale(uloc, uloc); - String description = ""; + StringBuilder description = new StringBuilder(); String[][] localizations = null; try { - // For backwards compatability - If we have a pre-4.2 style RBNF resource, attempt to read it. - description = bundle.getString(rulenames[format-1]); - } - catch (MissingResourceException e) { - try { - ICUResourceBundle rules = bundle.getWithFallback("RBNFRules/"+rulenames[format-1]); - UResourceBundleIterator it = rules.getIterator(); - while (it.hasNext()) { - description = description.concat(it.nextString()); - } - } - catch (MissingResourceException e1) { + ICUResourceBundle rules = bundle.getWithFallback("RBNFRules/"+rulenames[format-1]); + UResourceBundleIterator it = rules.getIterator(); + while (it.hasNext()) { + description.append(it.nextString()); } } + catch (MissingResourceException e1) { + } try { UResourceBundle locb = bundle.get(locnames[format-1]); @@ -794,7 +788,7 @@ public class RuleBasedNumberFormat extends NumberFormat { // might have description and no localizations, or no description... } - init(description, localizations); + init(description.toString(), localizations); } @@ -810,7 +804,7 @@ public class RuleBasedNumberFormat extends NumberFormat { * default FORMAT locale. * @param format A selector code specifying which kind of formatter to create. * There are three legal values: SPELLOUT, which creates a formatter that spells - * out a value in words in the default locale's langyage, ORDINAL, which attaches + * out a value in words in the default locale's language, ORDINAL, which attaches * an ordinal suffix from the default locale's language to a numeral, and * DURATION, which formats a duration in seconds as hours, minutes, and seconds. * or NUMBERING_SYSTEM, which is used for alternate numbering systems such as Hebrew. @@ -961,7 +955,7 @@ public class RuleBasedNumberFormat extends NumberFormat { /** * Return a list of locales for which there are locale-specific display names * for the rule sets in this formatter. If there are no localized display names, return null. - * @return an array of the ulocales for which there is rule set display name information + * @return an array of the ULocales for which there is rule set display name information * @stable ICU 3.2 */ public ULocale[] getRuleSetDisplayNameLocales() { @@ -1187,7 +1181,7 @@ public class RuleBasedNumberFormat extends NumberFormat { } /** - * Parses the specfied string, beginning at the specified position, according + * Parses the specified string, beginning at the specified position, according * to this formatter's rules. This will match the string against all of the * formatter's public rule sets and return the value corresponding to the longest * parseable substring. This function's behavior is affected by the lenient @@ -1555,7 +1549,7 @@ public class RuleBasedNumberFormat extends NumberFormat { // check to see if there's a set of lenient-parse rules. If there // is, pull them out into our temporary holding place for them, - // and delete them from the description before the real desciption- + // and delete them from the description before the real description- // parsing code sees them lenientParseRules = extractSpecial(descBuf, "%%lenient-parse:"); @@ -1571,7 +1565,7 @@ public class RuleBasedNumberFormat extends NumberFormat { } ++numRuleSets; - // our rule list is an array of the apprpriate size + // our rule list is an array of the appropriate size ruleSets = new NFRuleSet[numRuleSets]; // divide up the descriptions into individual rule-set descriptions @@ -1597,7 +1591,7 @@ public class RuleBasedNumberFormat extends NumberFormat { // now we can take note of the formatter's default rule set, which // is the last public rule set in the description (it's the last // rather than the first so that a user can create a new formatter - // from an existing formatter and change its default bevhaior just + // from an existing formatter and change its default behavior just // by appending more rule sets to the end) // {dlf} Initialization of a fraction rule set requires the default rule @@ -1630,7 +1624,7 @@ public class RuleBasedNumberFormat extends NumberFormat { } // finally, we can go back through the temporary descriptions - // list and finish seting up the substructure + // list and finish setting up the substructure for (int i = 0; i < ruleSets.length; i++) { ruleSets[i].parseRules(ruleSetDescriptions[i], this); } @@ -1730,43 +1724,43 @@ public class RuleBasedNumberFormat extends NumberFormat { // since we don't have a method that deletes characters (why?!!) // create a new StringBuffer to copy the text into StringBuilder result = new StringBuilder(); + int descriptionLength = description.length(); // iterate through the characters... int start = 0; - while (start != -1 && start < description.length()) { + while (start < descriptionLength) { // seek to the first non-whitespace character... - while (start < description.length() - && PatternProps.isWhiteSpace(description.charAt(start))) { + while (start < descriptionLength + && PatternProps.isWhiteSpace(description.charAt(start))) + { ++start; } //if the first non-whitespace character is semicolon, skip it and continue - if (start < description.length() && description.charAt(start) == ';') { + if (start < descriptionLength && description.charAt(start) == ';') { start += 1; continue; } // locate the next semicolon in the text and copy the text from // our current position up to that semicolon into the result - int p; - p = description.indexOf(';', start); + int p = description.indexOf(';', start); if (p == -1) { // or if we don't find a semicolon, just copy the rest of // the string into the result result.append(description.substring(start)); - start = -1; + break; } - else if (p < description.length()) { + else if (p < descriptionLength) { result.append(description.substring(start, p + 1)); start = p + 1; } - - // when we get here, we've seeked off the end of the sring, and - // we terminate the loop (we continue until *start* is -1 rather - // than until *p* is -1, because otherwise we'd miss the last - // rule in the description) else { - start = -1; + // when we get here, we've seeked off the end of the string, and + // we terminate the loop (we continue until *start* is -1 rather + // than until *p* is -1, because otherwise we'd miss the last + // rule in the description) + break; } } return result; diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/RbnfTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/RbnfTest.java index 5b7094adc18..22ca2e8ae3e 100644 --- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/RbnfTest.java +++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/RbnfTest.java @@ -7,15 +7,15 @@ package com.ibm.icu.dev.test.format; import java.math.BigInteger; -import java.text.DecimalFormat; -import java.text.NumberFormat; import java.text.ParseException; import java.util.Locale; import java.util.Random; import com.ibm.icu.dev.test.TestFmwk; +import com.ibm.icu.text.DecimalFormat; import com.ibm.icu.text.DecimalFormatSymbols; import com.ibm.icu.text.DisplayContext; +import com.ibm.icu.text.NumberFormat; import com.ibm.icu.text.RuleBasedNumberFormat; import com.ibm.icu.util.ULocale; @@ -37,7 +37,7 @@ public class RbnfTest extends TestFmwk { } } - static String fracRules = + static String fracRules = "%main:\n" + // this rule formats the number if it's 1 or more. It formats // the integral part using a DecimalFormat ("#,##0" puts @@ -70,7 +70,7 @@ public class RbnfTest extends TestFmwk { static { // mondo hack - char[] fracRulesArr = fracRules.toCharArray(); + char[] fracRulesArr = fracRules.toCharArray(); int len = fracRulesArr.length; int change = 2; for (int i = 0; i < len; ++i) { @@ -89,7 +89,7 @@ public class RbnfTest extends TestFmwk { } } } - fracRules = new String(fracRulesArr); + fracRules = new String(fracRulesArr); } static final String durationInSecondsRules = @@ -246,34 +246,34 @@ public class RbnfTest extends TestFmwk { public void TestUndefinedSpellout() { Locale greek = new Locale("el", "", ""); RuleBasedNumberFormat[] formatters = { - new RuleBasedNumberFormat(greek, RuleBasedNumberFormat.SPELLOUT), - new RuleBasedNumberFormat(greek, RuleBasedNumberFormat.ORDINAL), - new RuleBasedNumberFormat(greek, RuleBasedNumberFormat.DURATION), + new RuleBasedNumberFormat(greek, RuleBasedNumberFormat.SPELLOUT), + new RuleBasedNumberFormat(greek, RuleBasedNumberFormat.ORDINAL), + new RuleBasedNumberFormat(greek, RuleBasedNumberFormat.DURATION), }; String[] data = { - "0", - "1", - "15", - "20", - "23", - "73", - "88", - "100", - "106", - "127", - "200", - "579", - "1,000", - "2,000", - "3,004", - "4,567", - "15,943", - "105,000", - "2,345,678", - "-36", - "-36.91215", - "234.56789" + "0", + "1", + "15", + "20", + "23", + "73", + "88", + "100", + "106", + "127", + "200", + "579", + "1,000", + "2,000", + "3,004", + "4,567", + "15,943", + "105,000", + "2,345,678", + "-36", + "-36.91215", + "234.56789" }; NumberFormat decFormat = NumberFormat.getInstance(Locale.US); @@ -296,30 +296,29 @@ public class RbnfTest extends TestFmwk { * Perform a simple spot check on the English spellout rules */ public void TestEnglishSpellout() { - RuleBasedNumberFormat formatter - = new RuleBasedNumberFormat(Locale.US, - RuleBasedNumberFormat.SPELLOUT); + RuleBasedNumberFormat formatter = new RuleBasedNumberFormat(Locale.US, + RuleBasedNumberFormat.SPELLOUT); String[][] testData = { - { "1", "one" }, - { "15", "fifteen" }, - { "20", "twenty" }, - { "23", "twenty-three" }, - { "73", "seventy-three" }, - { "88", "eighty-eight" }, - { "100", "one hundred" }, - { "106", "one hundred six" }, - { "127", "one hundred twenty-seven" }, - { "200", "two hundred" }, - { "579", "five hundred seventy-nine" }, - { "1,000", "one thousand" }, - { "2,000", "two thousand" }, - { "3,004", "three thousand four" }, - { "4,567", "four thousand five hundred sixty-seven" }, - { "15,943", "fifteen thousand nine hundred forty-three" }, - { "2,345,678", "two million three hundred forty-five " - + "thousand six hundred seventy-eight" }, - { "-36", "minus thirty-six" }, - { "234.567", "two hundred thirty-four point five six seven" } + { "1", "one" }, + { "15", "fifteen" }, + { "20", "twenty" }, + { "23", "twenty-three" }, + { "73", "seventy-three" }, + { "88", "eighty-eight" }, + { "100", "one hundred" }, + { "106", "one hundred six" }, + { "127", "one hundred twenty-seven" }, + { "200", "two hundred" }, + { "579", "five hundred seventy-nine" }, + { "1,000", "one thousand" }, + { "2,000", "two thousand" }, + { "3,004", "three thousand four" }, + { "4,567", "four thousand five hundred sixty-seven" }, + { "15,943", "fifteen thousand nine hundred forty-three" }, + { "2,345,678", "two million three hundred forty-five " + + "thousand six hundred seventy-eight" }, + { "-36", "minus thirty-six" }, + { "234.567", "two hundred thirty-four point five six seven" } }; doTest(formatter, testData, true); @@ -329,27 +328,26 @@ public class RbnfTest extends TestFmwk { * Perform a simple spot check on the English ordinal-abbreviation rules */ public void TestOrdinalAbbreviations() { - RuleBasedNumberFormat formatter - = new RuleBasedNumberFormat(Locale.US, - RuleBasedNumberFormat.ORDINAL); + RuleBasedNumberFormat formatter= new RuleBasedNumberFormat(Locale.US, + RuleBasedNumberFormat.ORDINAL); String[][] testData = { - { "1", "1st" }, - { "2", "2nd" }, - { "3", "3rd" }, - { "4", "4th" }, - { "7", "7th" }, - { "10", "10th" }, - { "11", "11th" }, - { "13", "13th" }, - { "20", "20th" }, - { "21", "21st" }, - { "22", "22nd" }, - { "23", "23rd" }, - { "24", "24th" }, - { "33", "33rd" }, - { "102", "102nd" }, - { "312", "312th" }, - { "12,345", "12,345th" } + { "1", "1st" }, + { "2", "2nd" }, + { "3", "3rd" }, + { "4", "4th" }, + { "7", "7th" }, + { "10", "10th" }, + { "11", "11th" }, + { "13", "13th" }, + { "20", "20th" }, + { "21", "21st" }, + { "22", "22nd" }, + { "23", "23rd" }, + { "24", "24th" }, + { "33", "33rd" }, + { "102", "102nd" }, + { "312", "312th" }, + { "12,345", "12,345th" } }; doTest(formatter, testData, false); @@ -359,21 +357,20 @@ public class RbnfTest extends TestFmwk { * Perform a simple spot check on the duration-formatting rules */ public void TestDurations() { - RuleBasedNumberFormat formatter - = new RuleBasedNumberFormat(Locale.US, - RuleBasedNumberFormat.DURATION); + RuleBasedNumberFormat formatter = new RuleBasedNumberFormat(Locale.US, + RuleBasedNumberFormat.DURATION); String[][] testData = { - { "3,600", "1:00:00" }, //move me and I fail - { "0", "0 sec." }, - { "1", "1 sec." }, - { "24", "24 sec." }, - { "60", "1:00" }, - { "73", "1:13" }, - { "145", "2:25" }, - { "666", "11:06" }, - // { "3,600", "1:00:00" }, - { "3,740", "1:02:20" }, - { "10,293", "2:51:33" } + { "3,600", "1:00:00" }, //move me and I fail + { "0", "0 sec." }, + { "1", "1 sec." }, + { "24", "24 sec." }, + { "60", "1:00" }, + { "73", "1:13" }, + { "145", "2:25" }, + { "666", "11:06" }, + // { "3,600", "1:00:00" }, + { "3,740", "1:02:20" }, + { "10,293", "2:51:33" } }; doTest(formatter, testData, true); @@ -383,32 +380,31 @@ public class RbnfTest extends TestFmwk { * Perform a simple spot check on the Spanish spellout rules */ public void TestSpanishSpellout() { - RuleBasedNumberFormat formatter - = new RuleBasedNumberFormat(new Locale("es", "es", - ""), RuleBasedNumberFormat.SPELLOUT); + RuleBasedNumberFormat formatter = new RuleBasedNumberFormat(new Locale("es", "es", + ""), RuleBasedNumberFormat.SPELLOUT); String[][] testData = { - { "1", "uno" }, - { "6", "seis" }, - { "16", "diecis\u00e9is" }, - { "20", "veinte" }, - { "24", "veinticuatro" }, - { "26", "veintis\u00e9is" }, - { "73", "setenta y tres" }, - { "88", "ochenta y ocho" }, - { "100", "cien" }, - { "106", "ciento seis" }, - { "127", "ciento veintisiete" }, - { "200", "doscientos" }, - { "579", "quinientos setenta y nueve" }, - { "1,000", "mil" }, - { "2,000", "dos mil" }, - { "3,004", "tres mil cuatro" }, - { "4,567", "cuatro mil quinientos sesenta y siete" }, - { "15,943", "quince mil novecientos cuarenta y tres" }, - { "2,345,678", "dos millones trescientos cuarenta y cinco mil " - + "seiscientos setenta y ocho"}, - { "-36", "menos treinta y seis" }, - { "234.567", "doscientos treinta y cuatro coma cinco seis siete" } + { "1", "uno" }, + { "6", "seis" }, + { "16", "diecis\u00e9is" }, + { "20", "veinte" }, + { "24", "veinticuatro" }, + { "26", "veintis\u00e9is" }, + { "73", "setenta y tres" }, + { "88", "ochenta y ocho" }, + { "100", "cien" }, + { "106", "ciento seis" }, + { "127", "ciento veintisiete" }, + { "200", "doscientos" }, + { "579", "quinientos setenta y nueve" }, + { "1,000", "mil" }, + { "2,000", "dos mil" }, + { "3,004", "tres mil cuatro" }, + { "4,567", "cuatro mil quinientos sesenta y siete" }, + { "15,943", "quince mil novecientos cuarenta y tres" }, + { "2,345,678", "dos millones trescientos cuarenta y cinco mil " + + "seiscientos setenta y ocho"}, + { "-36", "menos treinta y seis" }, + { "234.567", "doscientos treinta y cuatro coma cinco seis siete" } }; doTest(formatter, testData, true); @@ -418,37 +414,36 @@ public class RbnfTest extends TestFmwk { * Perform a simple spot check on the French spellout rules */ public void TestFrenchSpellout() { - RuleBasedNumberFormat formatter - = new RuleBasedNumberFormat(Locale.FRANCE, - RuleBasedNumberFormat.SPELLOUT); + RuleBasedNumberFormat formatter = new RuleBasedNumberFormat(Locale.FRANCE, + RuleBasedNumberFormat.SPELLOUT); String[][] testData = { - { "1", "un" }, - { "15", "quinze" }, - { "20", "vingt" }, - { "21", "vingt-et-un" }, - { "23", "vingt-trois" }, - { "62", "soixante-deux" }, - { "70", "soixante-dix" }, - { "71", "soixante-et-onze" }, - { "73", "soixante-treize" }, - { "80", "quatre-vingts" }, - { "88", "quatre-vingt-huit" }, - { "100", "cent" }, - { "106", "cent six" }, - { "127", "cent vingt-sept" }, - { "200", "deux cents" }, - { "579", "cinq cent soixante-dix-neuf" }, - { "1,000", "mille" }, - { "1,123", "mille cent vingt-trois" }, - { "1,594", "mille cinq cent quatre-vingt-quatorze" }, - { "2,000", "deux mille" }, - { "3,004", "trois mille quatre" }, - { "4,567", "quatre mille cinq cent soixante-sept" }, - { "15,943", "quinze mille neuf cent quarante-trois" }, - { "2,345,678", "deux millions trois cent quarante-cinq mille " - + "six cent soixante-dix-huit" }, - { "-36", "moins trente-six" }, - { "234.567", "deux cent trente-quatre virgule cinq six sept" } + { "1", "un" }, + { "15", "quinze" }, + { "20", "vingt" }, + { "21", "vingt-et-un" }, + { "23", "vingt-trois" }, + { "62", "soixante-deux" }, + { "70", "soixante-dix" }, + { "71", "soixante-et-onze" }, + { "73", "soixante-treize" }, + { "80", "quatre-vingts" }, + { "88", "quatre-vingt-huit" }, + { "100", "cent" }, + { "106", "cent six" }, + { "127", "cent vingt-sept" }, + { "200", "deux cents" }, + { "579", "cinq cent soixante-dix-neuf" }, + { "1,000", "mille" }, + { "1,123", "mille cent vingt-trois" }, + { "1,594", "mille cinq cent quatre-vingt-quatorze" }, + { "2,000", "deux mille" }, + { "3,004", "trois mille quatre" }, + { "4,567", "quatre mille cinq cent soixante-sept" }, + { "15,943", "quinze mille neuf cent quarante-trois" }, + { "2,345,678", "deux millions trois cent quarante-cinq mille " + + "six cent soixante-dix-huit" }, + { "-36", "moins trente-six" }, + { "234.567", "deux cent trente-quatre virgule cinq six sept" } }; doTest(formatter, testData, true); @@ -458,37 +453,36 @@ public class RbnfTest extends TestFmwk { * Perform a simple spot check on the Swiss French spellout rules */ public void TestSwissFrenchSpellout() { - RuleBasedNumberFormat formatter - = new RuleBasedNumberFormat(new Locale("fr", "CH", - ""), RuleBasedNumberFormat.SPELLOUT); + RuleBasedNumberFormat formatter = new RuleBasedNumberFormat(new Locale("fr", "CH"), + RuleBasedNumberFormat.SPELLOUT); String[][] testData = { - { "1", "un" }, - { "15", "quinze" }, - { "20", "vingt" }, - { "21", "vingt-et-un" }, - { "23", "vingt-trois" }, - { "62", "soixante-deux" }, - { "70", "septante" }, - { "71", "septante-et-un" }, - { "73", "septante-trois" }, - { "80", "huitante" }, - { "88", "huitante-huit" }, - { "100", "cent" }, - { "106", "cent six" }, - { "127", "cent vingt-sept" }, - { "200", "deux cents" }, - { "579", "cinq cent septante-neuf" }, - { "1,000", "mille" }, - { "1,123", "mille cent vingt-trois" }, - { "1,594", "mille cinq cent nonante-quatre" }, - { "2,000", "deux mille" }, - { "3,004", "trois mille quatre" }, - { "4,567", "quatre mille cinq cent soixante-sept" }, - { "15,943", "quinze mille neuf cent quarante-trois" }, - { "2,345,678", "deux millions trois cent quarante-cinq mille " - + "six cent septante-huit" }, - { "-36", "moins trente-six" }, - { "234.567", "deux cent trente-quatre virgule cinq six sept" } + { "1", "un" }, + { "15", "quinze" }, + { "20", "vingt" }, + { "21", "vingt-et-un" }, + { "23", "vingt-trois" }, + { "62", "soixante-deux" }, + { "70", "septante" }, + { "71", "septante-et-un" }, + { "73", "septante-trois" }, + { "80", "huitante" }, + { "88", "huitante-huit" }, + { "100", "cent" }, + { "106", "cent six" }, + { "127", "cent vingt-sept" }, + { "200", "deux cents" }, + { "579", "cinq cent septante-neuf" }, + { "1,000", "mille" }, + { "1,123", "mille cent vingt-trois" }, + { "1,594", "mille cinq cent nonante-quatre" }, + { "2,000", "deux mille" }, + { "3,004", "trois mille quatre" }, + { "4,567", "quatre mille cinq cent soixante-sept" }, + { "15,943", "quinze mille neuf cent quarante-trois" }, + { "2,345,678", "deux millions trois cent quarante-cinq mille " + + "six cent septante-huit" }, + { "-36", "moins trente-six" }, + { "234.567", "deux cent trente-quatre virgule cinq six sept" } }; doTest(formatter, testData, true); @@ -498,30 +492,29 @@ public class RbnfTest extends TestFmwk { * Perform a simple spot check on the Italian spellout rules */ public void TestItalianSpellout() { - RuleBasedNumberFormat formatter - = new RuleBasedNumberFormat(Locale.ITALIAN, - RuleBasedNumberFormat.SPELLOUT); + RuleBasedNumberFormat formatter = new RuleBasedNumberFormat(Locale.ITALIAN, + RuleBasedNumberFormat.SPELLOUT); String[][] testData = { - { "1", "uno" }, - { "15", "quindici" }, - { "20", "venti" }, - { "23", "venti\u00ADtr\u00E9" }, - { "73", "settanta\u00ADtr\u00E9" }, - { "88", "ottant\u00ADotto" }, - { "100", "cento" }, - { "106", "cento\u00ADsei" }, - { "108", "cent\u00ADotto" }, - { "127", "cento\u00ADventi\u00ADsette" }, - { "181", "cent\u00ADottant\u00ADuno" }, - { "200", "due\u00ADcento" }, - { "579", "cinque\u00ADcento\u00ADsettanta\u00ADnove" }, - { "1,000", "mille" }, - { "2,000", "due\u00ADmila" }, - { "3,004", "tre\u00ADmila\u00ADquattro" }, - { "4,567", "quattro\u00ADmila\u00ADcinque\u00ADcento\u00ADsessanta\u00ADsette" }, - { "15,943", "quindici\u00ADmila\u00ADnove\u00ADcento\u00ADquaranta\u00ADtr\u00E9" }, - { "-36", "meno trenta\u00ADsei" }, - { "234.567", "due\u00ADcento\u00ADtrenta\u00ADquattro virgola cinque sei sette" } + { "1", "uno" }, + { "15", "quindici" }, + { "20", "venti" }, + { "23", "venti\u00ADtr\u00E9" }, + { "73", "settanta\u00ADtr\u00E9" }, + { "88", "ottant\u00ADotto" }, + { "100", "cento" }, + { "106", "cento\u00ADsei" }, + { "108", "cent\u00ADotto" }, + { "127", "cento\u00ADventi\u00ADsette" }, + { "181", "cent\u00ADottant\u00ADuno" }, + { "200", "due\u00ADcento" }, + { "579", "cinque\u00ADcento\u00ADsettanta\u00ADnove" }, + { "1,000", "mille" }, + { "2,000", "due\u00ADmila" }, + { "3,004", "tre\u00ADmila\u00ADquattro" }, + { "4,567", "quattro\u00ADmila\u00ADcinque\u00ADcento\u00ADsessanta\u00ADsette" }, + { "15,943", "quindici\u00ADmila\u00ADnove\u00ADcento\u00ADquaranta\u00ADtr\u00E9" }, + { "-36", "meno trenta\u00ADsei" }, + { "234.567", "due\u00ADcento\u00ADtrenta\u00ADquattro virgola cinque sei sette" } }; doTest(formatter, testData, true); @@ -531,28 +524,27 @@ public class RbnfTest extends TestFmwk { * Perform a simple spot check on the German spellout rules */ public void TestGermanSpellout() { - RuleBasedNumberFormat formatter - = new RuleBasedNumberFormat(Locale.GERMANY, - RuleBasedNumberFormat.SPELLOUT); + RuleBasedNumberFormat formatter = new RuleBasedNumberFormat(Locale.GERMANY, + RuleBasedNumberFormat.SPELLOUT); String[][] testData = { - { "1", "eins" }, - { "15", "f\u00fcnfzehn" }, - { "20", "zwanzig" }, - { "23", "drei\u00ADund\u00ADzwanzig" }, - { "73", "drei\u00ADund\u00ADsiebzig" }, - { "88", "acht\u00ADund\u00ADachtzig" }, - { "100", "ein\u00ADhundert" }, - { "106", "ein\u00ADhundert\u00ADsechs" }, - { "127", "ein\u00ADhundert\u00ADsieben\u00ADund\u00ADzwanzig" }, - { "200", "zwei\u00ADhundert" }, - { "579", "f\u00fcnf\u00ADhundert\u00ADneun\u00ADund\u00ADsiebzig" }, - { "1,000", "ein\u00ADtausend" }, - { "2,000", "zwei\u00ADtausend" }, - { "3,004", "drei\u00ADtausend\u00ADvier" }, - { "4,567", "vier\u00ADtausend\u00ADf\u00fcnf\u00ADhundert\u00ADsieben\u00ADund\u00ADsechzig" }, - { "15,943", "f\u00fcnfzehn\u00ADtausend\u00ADneun\u00ADhundert\u00ADdrei\u00ADund\u00ADvierzig" }, - { "2,345,678", "zwei Millionen drei\u00ADhundert\u00ADf\u00fcnf\u00ADund\u00ADvierzig\u00ADtausend\u00AD" - + "sechs\u00ADhundert\u00ADacht\u00ADund\u00ADsiebzig" } + { "1", "eins" }, + { "15", "f\u00fcnfzehn" }, + { "20", "zwanzig" }, + { "23", "drei\u00ADund\u00ADzwanzig" }, + { "73", "drei\u00ADund\u00ADsiebzig" }, + { "88", "acht\u00ADund\u00ADachtzig" }, + { "100", "ein\u00ADhundert" }, + { "106", "ein\u00ADhundert\u00ADsechs" }, + { "127", "ein\u00ADhundert\u00ADsieben\u00ADund\u00ADzwanzig" }, + { "200", "zwei\u00ADhundert" }, + { "579", "f\u00fcnf\u00ADhundert\u00ADneun\u00ADund\u00ADsiebzig" }, + { "1,000", "ein\u00ADtausend" }, + { "2,000", "zwei\u00ADtausend" }, + { "3,004", "drei\u00ADtausend\u00ADvier" }, + { "4,567", "vier\u00ADtausend\u00ADf\u00fcnf\u00ADhundert\u00ADsieben\u00ADund\u00ADsechzig" }, + { "15,943", "f\u00fcnfzehn\u00ADtausend\u00ADneun\u00ADhundert\u00ADdrei\u00ADund\u00ADvierzig" }, + { "2,345,678", "zwei Millionen drei\u00ADhundert\u00ADf\u00fcnf\u00ADund\u00ADvierzig\u00ADtausend\u00AD" + + "sechs\u00ADhundert\u00ADacht\u00ADund\u00ADsiebzig" } }; doTest(formatter, testData, true); @@ -562,59 +554,90 @@ public class RbnfTest extends TestFmwk { * Perform a simple spot check on the Thai spellout rules */ public void TestThaiSpellout() { - RuleBasedNumberFormat formatter - = new RuleBasedNumberFormat(new Locale("th", "TH", ""), - RuleBasedNumberFormat.SPELLOUT); + RuleBasedNumberFormat formatter = new RuleBasedNumberFormat(new Locale("th", "TH"), + RuleBasedNumberFormat.SPELLOUT); String[][] testData = { - { "0", "\u0e28\u0e39\u0e19\u0e22\u0e4c" }, - { "1", "\u0e2b\u0e19\u0e36\u0e48\u0e07" }, - { "10", "\u0e2a\u0e34\u0e1a" }, - { "11", "\u0e2a\u0e34\u0e1a\u200b\u0e40\u0e2d\u0e47\u0e14" }, - { "21", "\u0e22\u0e35\u0e48\u200b\u0e2a\u0e34\u0e1a\u200b\u0e40\u0e2d\u0e47\u0e14" }, - { "101", "\u0e2b\u0e19\u0e36\u0e48\u0e07\u200b\u0e23\u0e49\u0e2d\u0e22\u200b\u0e2b\u0e19\u0e36\u0e48\u0e07" }, - { "1.234", "\u0e2b\u0e19\u0e36\u0e48\u0e07\u200b\u0e08\u0e38\u0e14\u200b\u0e2a\u0e2d\u0e07\u0e2a\u0e32\u0e21\u0e2a\u0e35\u0e48" }, - { "21.45", "\u0e22\u0e35\u0e48\u200b\u0e2a\u0e34\u0e1a\u200b\u0e40\u0e2d\u0e47\u0e14\u200b\u0e08\u0e38\u0e14\u200b\u0e2a\u0e35\u0e48\u0e2b\u0e49\u0e32" }, - { "22.45", "\u0e22\u0e35\u0e48\u200b\u0e2a\u0e34\u0e1a\u200b\u0e2a\u0e2d\u0e07\u200b\u0e08\u0e38\u0e14\u200b\u0e2a\u0e35\u0e48\u0e2b\u0e49\u0e32" }, - { "23.45", "\u0e22\u0e35\u0e48\u200b\u0e2a\u0e34\u0e1a\u200b\u0e2a\u0e32\u0e21\u200b\u0e08\u0e38\u0e14\u200b\u0e2a\u0e35\u0e48\u0e2b\u0e49\u0e32" }, - { "123.45", "\u0e2b\u0e19\u0e36\u0e48\u0e07\u200b\u0e23\u0e49\u0e2d\u0e22\u200b\u0e22\u0e35\u0e48\u200b\u0e2a\u0e34\u0e1a\u200b\u0e2a\u0e32\u0e21\u200b\u0e08\u0e38\u0e14\u200b\u0e2a\u0e35\u0e48\u0e2b\u0e49\u0e32" }, - { "12,345.678", "\u0E2B\u0E19\u0E36\u0E48\u0E07\u200b\u0E2B\u0E21\u0E37\u0E48\u0E19\u200b\u0E2A\u0E2D\u0E07\u200b\u0E1E\u0E31\u0E19\u200b\u0E2A\u0E32\u0E21\u200b\u0E23\u0E49\u0E2D\u0E22\u200b\u0E2A\u0E35\u0E48\u200b\u0E2A\u0E34\u0E1A\u200b\u0E2B\u0E49\u0E32\u200b\u0E08\u0E38\u0E14\u200b\u0E2B\u0E01\u0E40\u0E08\u0E47\u0E14\u0E41\u0E1B\u0E14" }, + { "0", "\u0e28\u0e39\u0e19\u0e22\u0e4c" }, + { "1", "\u0e2b\u0e19\u0e36\u0e48\u0e07" }, + { "10", "\u0e2a\u0e34\u0e1a" }, + { "11", "\u0e2a\u0e34\u0e1a\u200b\u0e40\u0e2d\u0e47\u0e14" }, + { "21", "\u0e22\u0e35\u0e48\u200b\u0e2a\u0e34\u0e1a\u200b\u0e40\u0e2d\u0e47\u0e14" }, + { "101", "\u0e2b\u0e19\u0e36\u0e48\u0e07\u200b\u0e23\u0e49\u0e2d\u0e22\u200b\u0e2b\u0e19\u0e36\u0e48\u0e07" }, + { "1.234", "\u0e2b\u0e19\u0e36\u0e48\u0e07\u200b\u0e08\u0e38\u0e14\u200b\u0e2a\u0e2d\u0e07\u0e2a\u0e32\u0e21\u0e2a\u0e35\u0e48" }, + { "21.45", "\u0e22\u0e35\u0e48\u200b\u0e2a\u0e34\u0e1a\u200b\u0e40\u0e2d\u0e47\u0e14\u200b\u0e08\u0e38\u0e14\u200b\u0e2a\u0e35\u0e48\u0e2b\u0e49\u0e32" }, + { "22.45", "\u0e22\u0e35\u0e48\u200b\u0e2a\u0e34\u0e1a\u200b\u0e2a\u0e2d\u0e07\u200b\u0e08\u0e38\u0e14\u200b\u0e2a\u0e35\u0e48\u0e2b\u0e49\u0e32" }, + { "23.45", "\u0e22\u0e35\u0e48\u200b\u0e2a\u0e34\u0e1a\u200b\u0e2a\u0e32\u0e21\u200b\u0e08\u0e38\u0e14\u200b\u0e2a\u0e35\u0e48\u0e2b\u0e49\u0e32" }, + { "123.45", "\u0e2b\u0e19\u0e36\u0e48\u0e07\u200b\u0e23\u0e49\u0e2d\u0e22\u200b\u0e22\u0e35\u0e48\u200b\u0e2a\u0e34\u0e1a\u200b\u0e2a\u0e32\u0e21\u200b\u0e08\u0e38\u0e14\u200b\u0e2a\u0e35\u0e48\u0e2b\u0e49\u0e32" }, + { "12,345.678", "\u0E2B\u0E19\u0E36\u0E48\u0E07\u200b\u0E2B\u0E21\u0E37\u0E48\u0E19\u200b\u0E2A\u0E2D\u0E07\u200b\u0E1E\u0E31\u0E19\u200b\u0E2A\u0E32\u0E21\u200b\u0E23\u0E49\u0E2D\u0E22\u200b\u0E2A\u0E35\u0E48\u200b\u0E2A\u0E34\u0E1A\u200b\u0E2B\u0E49\u0E32\u200b\u0E08\u0E38\u0E14\u200b\u0E2B\u0E01\u0E40\u0E08\u0E47\u0E14\u0E41\u0E1B\u0E14" }, }; doTest(formatter, testData, true); } - public void TestFractionalRuleSet() { - +// /** +// * Perform a simple spot check on the ordinal spellout rules +// */ +// public void TestOrdinalSpellout() { +// String rules = "%%digits-ordinal-indicator:" +// + "0=1: th;" +// + "1=1: st;" +// + "2=1: nd;" +// + "3=1: rd;" +// + "4=1: th;" +// + "20=1: >>;" +// + "100=1: >>;" +// + "%digits-ordinal:" +// + "-x: −>>;" +// + "0: =#,##0==%%digits-ordinal-indicator=;"; +// RuleBasedNumberFormat formatter = new RuleBasedNumberFormat(rules); +// String[][] testData = { +// { "1", "1st" }, +// { "2", "2nd" }, +// { "3", "3rd" }, +// { "4", "4th" }, +// { "11", "11th" }, +// { "12", "12th" }, +// { "13", "13th" }, +// { "14", "14th" }, +// { "21", "21st" }, +// { "22", "22nd" }, +// { "23", "23rd" }, +// { "24", "24th" }, +// }; +// +// doTest(formatter, testData, true); +// } - RuleBasedNumberFormat formatter = - new RuleBasedNumberFormat(fracRules, Locale.ENGLISH); + public void TestFractionalRuleSet() { + RuleBasedNumberFormat formatter = new RuleBasedNumberFormat(fracRules, + Locale.ENGLISH); String[][] testData = { - { "0", "0" }, - { "1", "1" }, - { "10", "10" }, - { ".1", "1/10" }, - { ".11", "1/9" }, - { ".125", "1/8" }, - { ".1428", "1/7" }, - { ".1667", "1/6" }, - { ".2", "1/5" }, - { ".25", "1/4" }, - { ".333", "1/3" }, - { ".5", "1/2" }, - { "1.1", "1 1/10" }, - { "2.11", "2 1/9" }, - { "3.125", "3 1/8" }, - { "4.1428", "4 1/7" }, - { "5.1667", "5 1/6" }, - { "6.2", "6 1/5" }, - { "7.25", "7 1/4" }, - { "8.333", "8 1/3" }, - { "9.5", "9 1/2" }, - { ".2222", "2/9" }, - { ".4444", "4/9" }, - { ".5555", "5/9" }, - { "1.2856", "1 2/7" } + { "0", "0" }, + { "1", "1" }, + { "10", "10" }, + { ".1", "1/10" }, + { ".11", "1/9" }, + { ".125", "1/8" }, + { ".1428", "1/7" }, + { ".1667", "1/6" }, + { ".2", "1/5" }, + { ".25", "1/4" }, + { ".333", "1/3" }, + { ".5", "1/2" }, + { "1.1", "1 1/10" }, + { "2.11", "2 1/9" }, + { "3.125", "3 1/8" }, + { "4.1428", "4 1/7" }, + { "5.1667", "5 1/6" }, + { "6.2", "6 1/5" }, + { "7.25", "7 1/4" }, + { "8.333", "8 1/3" }, + { "9.5", "9 1/2" }, + { ".2222", "2/9" }, + { ".4444", "4/9" }, + { ".5555", "5/9" }, + { "1.2856", "1 2/7" } }; doTest(formatter, testData, false); // exact values aren't parsable from fractions } @@ -622,39 +645,40 @@ public class RbnfTest extends TestFmwk { public void TestSwedishSpellout() { Locale locale = new Locale("sv", "", ""); - RuleBasedNumberFormat formatter = new RuleBasedNumberFormat(locale, RuleBasedNumberFormat.SPELLOUT); + RuleBasedNumberFormat formatter = new RuleBasedNumberFormat(locale, + RuleBasedNumberFormat.SPELLOUT); String[][] testDataDefault = { - { "101", "ett\u00ADhundra\u00ADett" }, - { "123", "ett\u00ADhundra\u00ADtjugo\u00ADtre" }, - { "1,001", "et\u00ADtusen ett" }, - { "1,100", "et\u00ADtusen ett\u00ADhundra" }, - { "1,101", "et\u00ADtusen ett\u00ADhundra\u00ADett" }, - { "1,234", "et\u00ADtusen tv\u00e5\u00ADhundra\u00ADtrettio\u00ADfyra" }, - { "10,001", "tio\u00ADtusen ett" }, - { "11,000", "elva\u00ADtusen" }, - { "12,000", "tolv\u00ADtusen" }, - { "20,000", "tjugo\u00ADtusen" }, - { "21,000", "tjugo\u00ADet\u00ADtusen" }, - { "21,001", "tjugo\u00ADet\u00ADtusen ett" }, - { "200,000", "tv\u00e5\u00ADhundra\u00ADtusen" }, - { "201,000", "tv\u00e5\u00ADhundra\u00ADet\u00ADtusen" }, - { "200,200", "tv\u00e5\u00ADhundra\u00ADtusen tv\u00e5\u00ADhundra" }, - { "2,002,000", "tv\u00e5 miljoner tv\u00e5\u00ADtusen" }, - { "12,345,678", "tolv miljoner tre\u00ADhundra\u00ADfyrtio\u00ADfem\u00ADtusen sex\u00ADhundra\u00ADsjuttio\u00AD\u00e5tta" }, - { "123,456.789", "ett\u00ADhundra\u00ADtjugo\u00ADtre\u00ADtusen fyra\u00ADhundra\u00ADfemtio\u00ADsex komma sju \u00e5tta nio" }, - { "-12,345.678", "minus tolv\u00ADtusen tre\u00ADhundra\u00ADfyrtio\u00ADfem komma sex sju \u00e5tta" }, + { "101", "ett\u00ADhundra\u00ADett" }, + { "123", "ett\u00ADhundra\u00ADtjugo\u00ADtre" }, + { "1,001", "et\u00ADtusen ett" }, + { "1,100", "et\u00ADtusen ett\u00ADhundra" }, + { "1,101", "et\u00ADtusen ett\u00ADhundra\u00ADett" }, + { "1,234", "et\u00ADtusen tv\u00e5\u00ADhundra\u00ADtrettio\u00ADfyra" }, + { "10,001", "tio\u00ADtusen ett" }, + { "11,000", "elva\u00ADtusen" }, + { "12,000", "tolv\u00ADtusen" }, + { "20,000", "tjugo\u00ADtusen" }, + { "21,000", "tjugo\u00ADet\u00ADtusen" }, + { "21,001", "tjugo\u00ADet\u00ADtusen ett" }, + { "200,000", "tv\u00e5\u00ADhundra\u00ADtusen" }, + { "201,000", "tv\u00e5\u00ADhundra\u00ADet\u00ADtusen" }, + { "200,200", "tv\u00e5\u00ADhundra\u00ADtusen tv\u00e5\u00ADhundra" }, + { "2,002,000", "tv\u00e5 miljoner tv\u00e5\u00ADtusen" }, + { "12,345,678", "tolv miljoner tre\u00ADhundra\u00ADfyrtio\u00ADfem\u00ADtusen sex\u00ADhundra\u00ADsjuttio\u00AD\u00e5tta" }, + { "123,456.789", "ett\u00ADhundra\u00ADtjugo\u00ADtre\u00ADtusen fyra\u00ADhundra\u00ADfemtio\u00ADsex komma sju \u00e5tta nio" }, + { "-12,345.678", "minus tolv\u00ADtusen tre\u00ADhundra\u00ADfyrtio\u00ADfem komma sex sju \u00e5tta" }, }; logln("testing default rules"); doTest(formatter, testDataDefault, true); String[][] testDataNeutrum = { - { "101", "ett\u00adhundra\u00adett" }, - { "1,001", "et\u00adtusen ett" }, - { "1,101", "et\u00adtusen ett\u00adhundra\u00adett" }, - { "10,001", "tio\u00adtusen ett" }, - { "21,001", "tjugo\u00adet\u00adtusen ett" } + { "101", "ett\u00adhundra\u00adett" }, + { "1,001", "et\u00adtusen ett" }, + { "1,101", "et\u00adtusen ett\u00adhundra\u00adett" }, + { "10,001", "tio\u00adtusen ett" }, + { "21,001", "tjugo\u00adet\u00adtusen ett" } }; formatter.setDefaultRuleSet("%spellout-cardinal-neuter"); @@ -662,14 +686,14 @@ public class RbnfTest extends TestFmwk { doTest(formatter, testDataNeutrum, true); String[][] testDataYear = { - { "101", "ett\u00adhundra\u00adett" }, - { "900", "nio\u00adhundra" }, - { "1,001", "et\u00adtusen ett" }, - { "1,100", "elva\u00adhundra" }, - { "1,101", "elva\u00adhundra\u00adett" }, - { "1,234", "tolv\u00adhundra\u00adtrettio\u00adfyra" }, - { "2,001", "tjugo\u00adhundra\u00adett" }, - { "10,001", "tio\u00adtusen ett" } + { "101", "ett\u00adhundra\u00adett" }, + { "900", "nio\u00adhundra" }, + { "1,001", "et\u00adtusen ett" }, + { "1,100", "elva\u00adhundra" }, + { "1,101", "elva\u00adhundra\u00adett" }, + { "1,234", "tolv\u00adhundra\u00adtrettio\u00adfyra" }, + { "2,001", "tjugo\u00adhundra\u00adett" }, + { "10,001", "tio\u00adtusen ett" } }; formatter.setDefaultRuleSet("%spellout-numbering-year"); @@ -691,7 +715,7 @@ public class RbnfTest extends TestFmwk { } public void TestTrailingSemicolon() { - String thaiRules = + String thaiRules = "%default:\n" + " -x: \u0e25\u0e1a>>;\n" + " x.x: <<\u0e08\u0e38\u0e14>>>;\n" + @@ -723,76 +747,74 @@ public class RbnfTest extends TestFmwk { " \u0e40\u0e2d\u0e47\u0e14;\n" + " =%default=;\n ; ;; "; - RuleBasedNumberFormat formatter - = new RuleBasedNumberFormat(thaiRules, new Locale("th", "TH", "")); + RuleBasedNumberFormat formatter = new RuleBasedNumberFormat(thaiRules, new Locale("th", "TH", "")); String[][] testData = { - { "0", "\u0e28\u0e39\u0e19\u0e22\u0e4c" }, - { "1", "\u0e2b\u0e19\u0e36\u0e48\u0e07" }, - { "123.45", "\u0e2b\u0e19\u0e36\u0e48\u0e07\u0e23\u0e49\u0e2d\u0e22\u0e22\u0e35\u0e48\u0e2a\u0e34\u0e1a\u0e2a\u0e32\u0e21\u0e08\u0e38\u0e14\u0e2a\u0e35\u0e48\u0e2b\u0e49\u0e32" } + { "0", "\u0e28\u0e39\u0e19\u0e22\u0e4c" }, + { "1", "\u0e2b\u0e19\u0e36\u0e48\u0e07" }, + { "123.45", "\u0e2b\u0e19\u0e36\u0e48\u0e07\u0e23\u0e49\u0e2d\u0e22\u0e22\u0e35\u0e48\u0e2a\u0e34\u0e1a\u0e2a\u0e32\u0e21\u0e08\u0e38\u0e14\u0e2a\u0e35\u0e48\u0e2b\u0e49\u0e32" } }; - + doTest(formatter, testData, true); } public void TestSmallValues() { - String[][] testData = { - { "0.001", "zero point zero zero one" }, - { "0.0001", "zero point zero zero zero one" }, - { "0.00001", "zero point zero zero zero zero one" }, - { "0.000001", "zero point zero zero zero zero zero one" }, - { "0.0000001", "zero point zero zero zero zero zero zero one" }, - { "0.00000001", "zero point zero zero zero zero zero zero zero one" }, - { "0.000000001", "zero point zero zero zero zero zero zero zero zero one" }, - { "0.0000000001", "zero point zero zero zero zero zero zero zero zero zero one" }, - { "0.00000000001", "zero point zero zero zero zero zero zero zero zero zero zero one" }, - { "0.000000000001", "zero point zero zero zero zero zero zero zero zero zero zero zero one" }, - { "0.0000000000001", "zero point zero zero zero zero zero zero zero zero zero zero zero zero one" }, - { "0.00000000000001", "zero point zero zero zero zero zero zero zero zero zero zero zero zero zero one" }, - { "0.000000000000001", "zero point zero zero zero zero zero zero zero zero zero zero zero zero zero zero one" }, - { "10,000,000.001", "ten million point zero zero one" }, - { "10,000,000.0001", "ten million point zero zero zero one" }, - { "10,000,000.00001", "ten million point zero zero zero zero one" }, - { "10,000,000.000001", "ten million point zero zero zero zero zero one" }, - { "10,000,000.0000001", "ten million point zero zero zero zero zero zero one" }, - { "10,000,000.00000001", "ten million point zero zero zero zero zero zero zero one" }, - { "10,000,000.000000002", "ten million point zero zero zero zero zero zero zero zero two" }, - { "10,000,000", "ten million" }, - { "1,234,567,890.0987654", "one billion two hundred thirty-four million five hundred sixty-seven thousand eight hundred ninety point zero nine eight seven six five four" }, - { "123,456,789.9876543", "one hundred twenty-three million four hundred fifty-six thousand seven hundred eighty-nine point nine eight seven six five four three" }, - { "12,345,678.87654321", "twelve million three hundred forty-five thousand six hundred seventy-eight point eight seven six five four three two one" }, - { "1,234,567.7654321", "one million two hundred thirty-four thousand five hundred sixty-seven point seven six five four three two one" }, - { "123,456.654321", "one hundred twenty-three thousand four hundred fifty-six point six five four three two one" }, - { "12,345.54321", "twelve thousand three hundred forty-five point five four three two one" }, - { "1,234.4321", "one thousand two hundred thirty-four point four three two one" }, - { "123.321", "one hundred twenty-three point three two one" }, - { "0.0000000011754944", "zero point zero zero zero zero zero zero zero zero one one seven five four nine four four" }, - { "0.000001175494351", "zero point zero zero zero zero zero one one seven five four nine four three five one" }, - }; - - RuleBasedNumberFormat formatter - = new RuleBasedNumberFormat(Locale.US, RuleBasedNumberFormat.SPELLOUT); - doTest(formatter, testData, true); + String[][] testData = { + { "0.001", "zero point zero zero one" }, + { "0.0001", "zero point zero zero zero one" }, + { "0.00001", "zero point zero zero zero zero one" }, + { "0.000001", "zero point zero zero zero zero zero one" }, + { "0.0000001", "zero point zero zero zero zero zero zero one" }, + { "0.00000001", "zero point zero zero zero zero zero zero zero one" }, + { "0.000000001", "zero point zero zero zero zero zero zero zero zero one" }, + { "0.0000000001", "zero point zero zero zero zero zero zero zero zero zero one" }, + { "0.00000000001", "zero point zero zero zero zero zero zero zero zero zero zero one" }, + { "0.000000000001", "zero point zero zero zero zero zero zero zero zero zero zero zero one" }, + { "0.0000000000001", "zero point zero zero zero zero zero zero zero zero zero zero zero zero one" }, + { "0.00000000000001", "zero point zero zero zero zero zero zero zero zero zero zero zero zero zero one" }, + { "0.000000000000001", "zero point zero zero zero zero zero zero zero zero zero zero zero zero zero zero one" }, + { "10,000,000.001", "ten million point zero zero one" }, + { "10,000,000.0001", "ten million point zero zero zero one" }, + { "10,000,000.00001", "ten million point zero zero zero zero one" }, + { "10,000,000.000001", "ten million point zero zero zero zero zero one" }, + { "10,000,000.0000001", "ten million point zero zero zero zero zero zero one" }, + { "10,000,000.00000001", "ten million point zero zero zero zero zero zero zero one" }, + { "10,000,000.000000002", "ten million point zero zero zero zero zero zero zero zero two" }, + { "10,000,000", "ten million" }, + { "1,234,567,890.0987654", "one billion two hundred thirty-four million five hundred sixty-seven thousand eight hundred ninety point zero nine eight seven six five four" }, + { "123,456,789.9876543", "one hundred twenty-three million four hundred fifty-six thousand seven hundred eighty-nine point nine eight seven six five four three" }, + { "12,345,678.87654321", "twelve million three hundred forty-five thousand six hundred seventy-eight point eight seven six five four three two one" }, + { "1,234,567.7654321", "one million two hundred thirty-four thousand five hundred sixty-seven point seven six five four three two one" }, + { "123,456.654321", "one hundred twenty-three thousand four hundred fifty-six point six five four three two one" }, + { "12,345.54321", "twelve thousand three hundred forty-five point five four three two one" }, + { "1,234.4321", "one thousand two hundred thirty-four point four three two one" }, + { "123.321", "one hundred twenty-three point three two one" }, + { "0.0000000011754944", "zero point zero zero zero zero zero zero zero zero one one seven five four nine four four" }, + { "0.000001175494351", "zero point zero zero zero zero zero one one seven five four nine four three five one" }, + }; + + RuleBasedNumberFormat formatter = new RuleBasedNumberFormat(Locale.US, RuleBasedNumberFormat.SPELLOUT); + doTest(formatter, testData, true); } public void TestRuleSetDisplayName() { ULocale.setDefault(ULocale.US); String[][] localizations = new String[][] { /* public rule sets*/ - {"%simplified", "%default", "%ordinal"}, + {"%simplified", "%default", "%ordinal"}, /* display names in "en_US" locale*/ - {"en_US", "Simplified", "Default", "Ordinal"}, + {"en_US", "Simplified", "Default", "Ordinal"}, /* display names in "zh_Hans" locale*/ - {"zh_Hans", "\u7B80\u5316", "\u7F3A\u7701", "\u5E8F\u5217"}, + {"zh_Hans", "\u7B80\u5316", "\u7F3A\u7701", "\u5E8F\u5217"}, /* display names in a fake locale*/ - {"foo_Bar_BAZ", "Simplified", "Default", "Ordinal"} + {"foo_Bar_BAZ", "Simplified", "Default", "Ordinal"} }; - + //Construct RuleBasedNumberFormat by rule sets and localizations list RuleBasedNumberFormat formatter - = new RuleBasedNumberFormat(ukEnglish, localizations, ULocale.US); + = new RuleBasedNumberFormat(ukEnglish, localizations, ULocale.US); RuleBasedNumberFormat f2= new RuleBasedNumberFormat(ukEnglish, localizations); - assertTrue("Check the two formatters' equality", formatter.equals(f2)); + assertTrue("Check the two formatters' equality", formatter.equals(f2)); //get displayName by name String[] ruleSetNames = formatter.getRuleSetNames(); @@ -803,121 +825,100 @@ public class RbnfTest extends TestFmwk { String RSName_loc = formatter.getRuleSetDisplayName(ruleSetNames[i], ULocale.CHINA); assertEquals("Display name in Chinese", localizations[2][i+1], RSName_loc); } - + // getDefaultRuleSetName String defaultRS = formatter.getDefaultRuleSetName(); //you know that the default rule set is %simplified according to rule sets string ukEnglish assertEquals("getDefaultRuleSetName", "%simplified", defaultRS); - + //get locales of localizations ULocale[] locales = formatter.getRuleSetDisplayNameLocales(); for (int i=0; i " + s); - if (testParse) { - // We do not validate the result in this test case, - // because there are cases which do not round trip by design. - try { - // non-lenient parse - fmt.setLenientParseMode(false); - Number num = fmt.parse(s); - logln(loc.getName() + names[j] + "success parse: " + s + " -> " + num); - } catch (ParseException pe) { - String msg = loc.getName() + names[j] + "ERROR:" + pe.getMessage(); - logln(msg); - if (errors == null) { - errors = new StringBuffer(); - } - errors.append("\n" + msg); + try { + // RBNF parse is extremely slow when lenient option is enabled. + // non-lenient parse + fmt.setLenientParseMode(false); + Number num = fmt.parse(s); + logln(loc.getName() + names[j] + "success parse: " + s + " -> " + num); + if (j != 0) { + // TODO: Fix the ordinal rules. + continue; + } + if (n != num.doubleValue()) { + errors.append("\n" + loc + names[j] + "got " + num + " expected " + n); } + } catch (ParseException pe) { + String msg = loc.getName() + names[j] + "ERROR:" + pe.getMessage(); + logln(msg); + errors.append("\n" + msg); } } } } - if (errors != null) { - //TODO: We need to fix parse problems - see #6895 / #6896 - //errln(errors.toString()); - logln(errors.toString()); + if (errors.length() > 0) { + errln(errors.toString()); } } void doTest(RuleBasedNumberFormat formatter, String[][] testData, boolean testParsing) { - // NumberFormat decFmt = NumberFormat.getInstance(Locale.US); - NumberFormat decFmt = new DecimalFormat("#,###.################"); + // NumberFormat decFmt = NumberFormat.getInstance(Locale.US); + NumberFormat decFmt = new DecimalFormat("#,###.################"); try { for (int i = 0; i < testData.length; i++) { String number = testData[i][0]; @@ -928,17 +929,17 @@ public class RbnfTest extends TestFmwk { if (!actualWords.equals(expectedWords)) { errln("Spot check format failed: for " + number + ", expected\n " - + expectedWords + ", but got\n " + - actualWords); + + expectedWords + ", but got\n " + + actualWords); } else if (testParsing) { String actualNumber = decFmt.format(formatter - .parse(actualWords)); + .parse(actualWords)); if (!actualNumber.equals(number)) { errln("Spot check parse failed: for " + actualWords + - ", expected " + number + ", but got " + - actualNumber); + ", expected " + number + ", but got " + + actualNumber); } } } @@ -950,7 +951,7 @@ public class RbnfTest extends TestFmwk { } /** - * Spellout rules for U.K. English. + * Spellout rules for U.K. English. * I borrow the rule sets for TestRuleSetDisplayName() */ public static final String ukEnglish = @@ -1026,26 +1027,27 @@ public class RbnfTest extends TestFmwk { + " 1,000,000: , =%default=;" + "%%lenient-parse:\n" + " & ' ' , ',' ;\n"; - + /* Tests the method * public boolean equals(Object that) */ public void TestEquals(){ // Tests when "if (!(that instanceof RuleBasedNumberFormat))" is true RuleBasedNumberFormat rbnf = new RuleBasedNumberFormat("dummy"); - if( rbnf.equals(new String("dummy")) != false || - rbnf.equals(new Character('a')) != false || - rbnf.equals(new Object()) != false || - rbnf.equals(-1) != false || - rbnf.equals(0) != false || - rbnf.equals(1) != false || - rbnf.equals(-1.0) != false || - rbnf.equals(0.0) != false || - rbnf.equals(1.0) != false){ + if (rbnf.equals(new String("dummy")) != false || + rbnf.equals(new Character('a')) != false || + rbnf.equals(new Object()) != false || + rbnf.equals(-1) != false || + rbnf.equals(0) != false || + rbnf.equals(1) != false || + rbnf.equals(-1.0) != false || + rbnf.equals(0.0) != false || + rbnf.equals(1.0) != false) + { errln("RuleBasedNumberFormat.equals(Object that) was suppose to " + "be false for an invalid object."); } - + // Tests when // "if (!locale.equals(that2.locale) || lenientParse != that2.lenientParse)" // is true @@ -1053,56 +1055,56 @@ public class RbnfTest extends TestFmwk { RuleBasedNumberFormat rbnf2 = new RuleBasedNumberFormat("dummy", new Locale("jp")); RuleBasedNumberFormat rbnf3 = new RuleBasedNumberFormat("dummy", new Locale("sp")); RuleBasedNumberFormat rbnf4 = new RuleBasedNumberFormat("dummy", new Locale("fr")); - + if(rbnf1.equals(rbnf2) != false || rbnf1.equals(rbnf3) != false || rbnf1.equals(rbnf4) != false || rbnf2.equals(rbnf3) != false || rbnf2.equals(rbnf4) != false || rbnf3.equals(rbnf4) != false){ errln("RuleBasedNumberFormat.equals(Object that) was suppose to " + - "be false for an invalid object."); + "be false for an invalid object."); } - + if(rbnf1.equals(rbnf1) == false){ errln("RuleBasedNumberFormat.equals(Object that) was not suppose to " + - "be false for an invalid object."); + "be false for an invalid object."); } - + if(rbnf2.equals(rbnf2) == false){ errln("RuleBasedNumberFormat.equals(Object that) was not suppose to " + - "be false for an invalid object."); + "be false for an invalid object."); } - + if(rbnf3.equals(rbnf3) == false){ errln("RuleBasedNumberFormat.equals(Object that) was not suppose to " + - "be false for an invalid object."); + "be false for an invalid object."); } - + if(rbnf4.equals(rbnf4) == false){ errln("RuleBasedNumberFormat.equals(Object that) was not suppose to " + - "be false for an invalid object."); + "be false for an invalid object."); } - + RuleBasedNumberFormat rbnf5 = new RuleBasedNumberFormat("dummy", new Locale("en")); RuleBasedNumberFormat rbnf6 = new RuleBasedNumberFormat("dummy", new Locale("en")); - + if(rbnf5.equals(rbnf6) == false){ errln("RuleBasedNumberFormat.equals(Object that) was not suppose to " + - "be false for an invalid object."); + "be false for an invalid object."); } rbnf6.setLenientParseMode(true); - + if(rbnf5.equals(rbnf6) != false){ errln("RuleBasedNumberFormat.equals(Object that) was suppose to " + - "be false for an invalid object."); + "be false for an invalid object."); } // Tests when "if (!ruleSets[i].equals(that2.ruleSets[i]))" is true RuleBasedNumberFormat rbnf7 = new RuleBasedNumberFormat("not_dummy", new Locale("en")); if(rbnf5.equals(rbnf7) != false){ errln("RuleBasedNumberFormat.equals(Object that) was suppose to " + - "be false for an invalid object."); + "be false for an invalid object."); } } - + /* Tests the method * public ULocale[] getRuleSetDisplayNameLocales() */ @@ -1112,10 +1114,10 @@ public class RbnfTest extends TestFmwk { rbnf.getRuleSetDisplayNameLocales(); if(rbnf.getRuleSetDisplayNameLocales() != null){ errln("RuleBasedNumberFormat.getRuleDisplayNameLocales() was suppose to " + - "return null."); + "return null."); } } - + /* Tests the method * private String[] getNameListForLocale(ULocale loc) * public String[] getRuleSetDisplayNames(ULocale loc) @@ -1139,23 +1141,23 @@ public class RbnfTest extends TestFmwk { public void TestGetRulesSetDisplayName(){ RuleBasedNumberFormat rbnf = new RuleBasedNumberFormat("dummy"); //rbnf.getRuleSetDisplayName("dummy", new ULocale("en_US")); - + // Tests when "if (names != null) " is true // Tests when the method throws an exception try{ rbnf.getRuleSetDisplayName("", new ULocale("en_US")); errln("RuleBasedNumberFormat.getRuleSetDisplayName(String ruleSetName, ULocale loc) " + - "was suppose to have an exception."); + "was suppose to have an exception."); } catch(Exception e){} - + try{ rbnf.getRuleSetDisplayName("dummy", new ULocale("en_US")); errln("RuleBasedNumberFormat.getRuleSetDisplayName(String ruleSetName, ULocale loc) " + - "was suppose to have an exception."); + "was suppose to have an exception."); } catch(Exception e){} } - + /* Test the method * public void process(StringBuffer buf, NFRuleSet ruleSet) */ @@ -1262,7 +1264,7 @@ public class RbnfTest extends TestFmwk { + " 60/60: <00<>>;\n" + " 3600/60: <#,##0<:>>>;\n" + "%%post-process:com.ibm.icu.text.RBNFChinesePostProcessor\n"; - + RuleBasedNumberFormat rbnf = new RuleBasedNumberFormat(ruleWithChinese, ULocale.CHINESE); String[] ruleNames = rbnf.getRuleSetNames(); try{ @@ -1279,7 +1281,7 @@ public class RbnfTest extends TestFmwk { } } } - + public void TestSetDecimalFormatSymbols() { RuleBasedNumberFormat rbnf = new RuleBasedNumberFormat(Locale.ENGLISH, RuleBasedNumberFormat.ORDINAL); @@ -1303,7 +1305,7 @@ public class RbnfTest extends TestFmwk { errln("Format Error - Got: " + result + " Expected: " + expected[1]); } } - + public void TestContext() { class TextContextItem { public String locale; @@ -1311,7 +1313,7 @@ public class RbnfTest extends TestFmwk { public DisplayContext context; public double value; public String expectedResult; - // Simple constructor + // Simple constructor public TextContextItem(String loc, int fmt, DisplayContext ctxt, double val, String expRes) { locale = loc; format = fmt; @@ -1321,14 +1323,14 @@ public class RbnfTest extends TestFmwk { } }; final TextContextItem[] items = { - new TextContextItem( "sv", RuleBasedNumberFormat.SPELLOUT, DisplayContext.CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, 123.45, "ett\u00ADhundra\u00ADtjugo\u00ADtre komma fyra fem" ), - new TextContextItem( "sv", RuleBasedNumberFormat.SPELLOUT, DisplayContext.CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, 123.45, "Ett\u00ADhundra\u00ADtjugo\u00ADtre komma fyra fem" ), - new TextContextItem( "sv", RuleBasedNumberFormat.SPELLOUT, DisplayContext.CAPITALIZATION_FOR_UI_LIST_OR_MENU, 123.45, "ett\u00ADhundra\u00ADtjugo\u00ADtre komma fyra fem" ), - new TextContextItem( "sv", RuleBasedNumberFormat.SPELLOUT, DisplayContext.CAPITALIZATION_FOR_STANDALONE, 123.45, "ett\u00ADhundra\u00ADtjugo\u00ADtre komma fyra fem" ), - new TextContextItem( "en", RuleBasedNumberFormat.SPELLOUT, DisplayContext.CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, 123.45, "one hundred twenty-three point four five" ), - new TextContextItem( "en", RuleBasedNumberFormat.SPELLOUT, DisplayContext.CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, 123.45, "One hundred twenty-three point four five" ), - new TextContextItem( "en", RuleBasedNumberFormat.SPELLOUT, DisplayContext.CAPITALIZATION_FOR_UI_LIST_OR_MENU, 123.45, "One hundred twenty-three point four five" ), - new TextContextItem( "en", RuleBasedNumberFormat.SPELLOUT, DisplayContext.CAPITALIZATION_FOR_STANDALONE, 123.45, "One hundred twenty-three point four five" ), + new TextContextItem( "sv", RuleBasedNumberFormat.SPELLOUT, DisplayContext.CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, 123.45, "ett\u00ADhundra\u00ADtjugo\u00ADtre komma fyra fem" ), + new TextContextItem( "sv", RuleBasedNumberFormat.SPELLOUT, DisplayContext.CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, 123.45, "Ett\u00ADhundra\u00ADtjugo\u00ADtre komma fyra fem" ), + new TextContextItem( "sv", RuleBasedNumberFormat.SPELLOUT, DisplayContext.CAPITALIZATION_FOR_UI_LIST_OR_MENU, 123.45, "ett\u00ADhundra\u00ADtjugo\u00ADtre komma fyra fem" ), + new TextContextItem( "sv", RuleBasedNumberFormat.SPELLOUT, DisplayContext.CAPITALIZATION_FOR_STANDALONE, 123.45, "ett\u00ADhundra\u00ADtjugo\u00ADtre komma fyra fem" ), + new TextContextItem( "en", RuleBasedNumberFormat.SPELLOUT, DisplayContext.CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, 123.45, "one hundred twenty-three point four five" ), + new TextContextItem( "en", RuleBasedNumberFormat.SPELLOUT, DisplayContext.CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, 123.45, "One hundred twenty-three point four five" ), + new TextContextItem( "en", RuleBasedNumberFormat.SPELLOUT, DisplayContext.CAPITALIZATION_FOR_UI_LIST_OR_MENU, 123.45, "One hundred twenty-three point four five" ), + new TextContextItem( "en", RuleBasedNumberFormat.SPELLOUT, DisplayContext.CAPITALIZATION_FOR_STANDALONE, 123.45, "One hundred twenty-three point four five" ), }; for (TextContextItem item: items) { ULocale locale = new ULocale(item.locale); -- 2.40.0