From ff8a03216deb6a0b4741e26ea7e8f4b791ab7ebf Mon Sep 17 00:00:00 2001 From: Doug Felt Date: Thu, 10 Jul 2008 18:47:56 +0000 Subject: [PATCH] ICU-5903 support pluralformat in message pattern (there are a number of whitespace changes in these files where trailing whitespace was deleted, sorry) X-SVN-Rev: 24369 --- .../dev/test/format/PluralFormatUnitTest.java | 76 ++++++--- .../dev/test/format/TestMessageFormat.java | 19 +++ icu4j/src/com/ibm/icu/text/MessageFormat.java | 147 ++++++++++-------- icu4j/src/com/ibm/icu/text/PluralFormat.java | 72 +++++---- 4 files changed, 191 insertions(+), 123 deletions(-) diff --git a/icu4j/src/com/ibm/icu/dev/test/format/PluralFormatUnitTest.java b/icu4j/src/com/ibm/icu/dev/test/format/PluralFormatUnitTest.java index 5f8b82a60e..8ea98197f6 100644 --- a/icu4j/src/com/ibm/icu/dev/test/format/PluralFormatUnitTest.java +++ b/icu4j/src/com/ibm/icu/dev/test/format/PluralFormatUnitTest.java @@ -1,6 +1,6 @@ /* ******************************************************************************* - * Copyright (C) 2007, International Business Machines Corporation and * + * Copyright (C) 2007-2008, International Business Machines Corporation and * * others. All Rights Reserved. * ******************************************************************************* */ @@ -12,6 +12,8 @@ import com.ibm.icu.dev.test.TestFmwk; import com.ibm.icu.text.*; import com.ibm.icu.util.ULocale; +import java.text.ChoiceFormat; +import java.text.Format; import java.text.ParsePosition; /** @@ -22,7 +24,7 @@ public class PluralFormatUnitTest extends TestFmwk { public static void main(String[] args) throws Exception { new PluralFormatUnitTest().run(args); } - + public void TestConstructor() { // Test correct formatting of numbers. PluralFormat plFmts[] = new PluralFormat[8]; @@ -40,7 +42,7 @@ public class PluralFormatUnitTest extends TestFmwk { PluralRules.DEFAULT, "other{#}"); plFmts[7] = new PluralFormat(ULocale.getDefault(), "other{#}"); - + // These plural formats should produce the same output as a // NumberFormat for the default locale. NumberFormat numberFmt = NumberFormat.getInstance(ULocale.getDefault()); @@ -60,7 +62,7 @@ public class PluralFormatUnitTest extends TestFmwk { } } } - + public void TestApplyPatternAndFormat() { // Create rules for testing. PluralRules oddAndEven = PluralRules.createRules("odd: n mod 2 is 1"); @@ -68,11 +70,11 @@ public class PluralFormatUnitTest extends TestFmwk { // Test full specified case for testing RuleSet PluralFormat plfOddAndEven = new PluralFormat(oddAndEven); plfOddAndEven.applyPattern("odd{# is odd.} other{# is even.}"); - + // Test fall back to other. PluralFormat plfOddOrEven = new PluralFormat(oddAndEven); plfOddOrEven.applyPattern("other{# is odd or even.}"); - + NumberFormat numberFormat = NumberFormat.getInstance(ULocale.getDefault()); for (int i = 0; i < 22; ++i) { @@ -84,7 +86,7 @@ public class PluralFormatUnitTest extends TestFmwk { : " is even."), plfOddAndEven.format(i)); } - + // Check that double definition results in an exception. try { PluralFormat plFmt = new PluralFormat(oddAndEven); @@ -103,26 +105,26 @@ public class PluralFormatUnitTest extends TestFmwk { try { PluralFormat plFmt = new PluralFormat(oddAndEven); plFmt.applyPattern("odd{foo}"); - errln("Not defining plural case other should result in an " + + errln("Not defining plural case other should result in an " + "exception but did not."); }catch (IllegalArgumentException e){} - + // Test unknown keyword. try { PluralFormat plFmt = new PluralFormat(oddAndEven); plFmt.applyPattern("otto{foo} other{bar}"); - errln("Defining a message for an unknown keyword should result in" + + errln("Defining a message for an unknown keyword should result in" + "an exception but did not."); }catch (IllegalArgumentException e){} - + // Test invalid keyword. try { PluralFormat plFmt = new PluralFormat(oddAndEven); plFmt.applyPattern("1odd{foo} other{bar}"); - errln("Defining a message for an invalid keyword should result in" + + errln("Defining a message for an invalid keyword should result in" + "an exception but did not."); }catch (IllegalArgumentException e){} - + // Test invalid syntax // -- comma between keyword{message} clauses // -- space in keywords @@ -130,7 +132,7 @@ public class PluralFormatUnitTest extends TestFmwk { try { PluralFormat plFmt = new PluralFormat(oddAndEven); plFmt.applyPattern("odd{foo},other{bar}"); - errln("Separating keyword{message} items with other characters " + + errln("Separating keyword{message} items with other characters " + "than space should provoke an exception but did not."); }catch (IllegalArgumentException e){} try { @@ -145,7 +147,7 @@ public class PluralFormatUnitTest extends TestFmwk { errln("Defining multiple messages after a keyword should provoke " + "an exception but did not."); }catch (IllegalArgumentException e){} - + // Check that nested format is preserved. { PluralFormat plFmt = new PluralFormat(oddAndEven); @@ -153,8 +155,8 @@ public class PluralFormatUnitTest extends TestFmwk { "other{The number {0, number, #.#0} is even.}"); for (int i = 1; i < 3; ++i) { assertEquals("format did not preserve a nested format string.", - ((i % 2 == 1) ? - "The number {0, number, #.#0} is odd." + ((i % 2 == 1) ? + "The number {0, number, #.#0} is odd." : "The number {0, number, #.#0} is even."), plFmt.format(i)); } @@ -167,18 +169,18 @@ public class PluralFormatUnitTest extends TestFmwk { "other{The number {#} is even.}"); for (int i = 1; i < 3; ++i) { assertEquals("format did not preserve # inside curly braces.", - ((i % 2 == 1) ? "The number {#} is odd." + ((i % 2 == 1) ? "The number {#} is odd." : "The number {#} is even."), plFmt.format(i)); } - + } } - + public void TestSetLocale() { // Create rules for testing. PluralRules oddAndEven = PluralRules.createRules("odd__: n mod 2 is 1"); - + PluralFormat plFmt = new PluralFormat(oddAndEven); plFmt.applyPattern("odd__{odd} other{even}"); plFmt.setLocale(ULocale.ENGLISH); @@ -188,7 +190,7 @@ public class PluralFormatUnitTest extends TestFmwk { assertEquals("pattern was not resetted by setLocale() call.", nrFmt.format(5), plFmt.format(5)); - + // Check that rules got updated. try { plFmt.applyPattern("odd__{odd} other{even}"); @@ -204,9 +206,8 @@ public class PluralFormatUnitTest extends TestFmwk { ((i==1) ? "one" : "not one"), plFmt.format(i)); } - } - + public void TestParse() { PluralFormat plFmt = new PluralFormat("other{test}"); try { @@ -215,7 +216,7 @@ public class PluralFormatUnitTest extends TestFmwk { "did not"); } catch (UnsupportedOperationException e) { } - + plFmt = new PluralFormat("other{test}"); try { plFmt.parseObject("test", new ParsePosition(0)); @@ -224,4 +225,29 @@ public class PluralFormatUnitTest extends TestFmwk { } catch (UnsupportedOperationException e) { } } + + public void TestPattern() { + Object[] args = { "acme", null }; + + { + PluralFormat pf = new PluralFormat(" one {one ''widget} other {# widgets} "); + String pat = pf.toPattern(); + logln("pf pattern: '" + pat + "'"); + + assertEquals("no leading spaces", "o", pat.substring(0, 1)); + assertEquals("no trailing spaces", "}", pat.substring(pat.length() - 1)); + } + + MessageFormat pfmt = new MessageFormat("The disk ''{0}'' contains {1, plural, one {one ''''{1, number, #.0}'''' widget} other {# widgets}}."); + System.out.println(); + for (int i = 0; i < 3; ++i) { + args[1] = new Integer(i); + logln(pfmt.format(args)); + } + PluralFormat pf = (PluralFormat)pfmt.getFormatsByArgumentIndex()[1]; + logln(pf.toPattern()); + logln(pfmt.toPattern()); + MessageFormat pfmt2 = new MessageFormat(pfmt.toPattern()); + assertEquals("message formats are equal", pfmt, pfmt2); + } } diff --git a/icu4j/src/com/ibm/icu/dev/test/format/TestMessageFormat.java b/icu4j/src/com/ibm/icu/dev/test/format/TestMessageFormat.java index 007128959f..adbc787bc8 100644 --- a/icu4j/src/com/ibm/icu/dev/test/format/TestMessageFormat.java +++ b/icu4j/src/com/ibm/icu/dev/test/format/TestMessageFormat.java @@ -1293,6 +1293,25 @@ public class TestMessageFormat extends com.ibm.icu.dev.test.TestFmwk { } } + // Test toPattern when there is a PluralFormat + public void testPluralFormatToPattern() { + String[] patterns = { + "Beware of vicious {0, plural, one {hamster} other {hamsters}}.", + "{0, plural, one {{0, number,C''''est #,##0.0# fichier}} other {Ce sont # fichiers}} dans la liste.", + "{0, plural, one {C''est # fichier} other {Ce sont # fichiers}} dans la liste.", + }; + + for (int i = 0; i < patterns.length; ++i) { + String pattern = patterns[i]; + MessageFormat mf = new MessageFormat(pattern); + MessageFormat mf2 = new MessageFormat(mf.toPattern()); + if (!mf.equals(mf2)) { + errln("message formats not equal for pattern:\n*** '" + pattern + "'\n*** '" + + mf.toPattern() + "'"); + } + } + } + //#if defined(FOUNDATION10) || defined(J2SE13) //#else // Test case for formatToCharacterIterator diff --git a/icu4j/src/com/ibm/icu/text/MessageFormat.java b/icu4j/src/com/ibm/icu/text/MessageFormat.java index 5671cd4084..e105da2d53 100644 --- a/icu4j/src/com/ibm/icu/text/MessageFormat.java +++ b/icu4j/src/com/ibm/icu/text/MessageFormat.java @@ -59,28 +59,28 @@ import com.ibm.icu.util.ULocale; *

* Note: * In ICU 3.8 MessageFormat supports named arguments. If a named argument - * is used, all arguments must be named. Names start with a character in - * :ID_START: and continue with characters in :ID_CONTINUE:, + * is used, all arguments must be named. Names start with a character in + * :ID_START: and continue with characters in :ID_CONTINUE:, * in particular they do not start with a digit. If named arguments * are used, {@link #usesNamedArguments()} will return true. *

- * The other new APIs supporting named arguments are + * The other new APIs supporting named arguments are * {@link #setFormatsByArgumentName(Map)}, * {@link #setFormatByArgumentName(String, Format)}, * {@link #format(Map, StringBuffer, FieldPosition)}, * {@link #format(String, Map)}, {@link #parseToMap(String, ParsePosition)}, - * and {@link #parseToMap(String)}. These APIs are all compatible + * and {@link #parseToMap(String)}. These APIs are all compatible * with patterns that do not used named arguments-- in these cases - * the keys in the input or output Maps use - * Strings that name the argument indices, e.g. "0", + * the keys in the input or output Maps use + * Strings that name the argument indices, e.g. "0", * "1", "2"... etc. *

* When named arguments are used, certain APIs on Message that take or * return arrays will throw an exception, since it is not possible to * identify positions in an array using a name. These APIs are {@link - * #setFormatsByArgumentIndex(Format[])}, {@link #getFormatsByArgumentIndex()}, - * {@link #format(Object[], StringBuffer, FieldPosition)}, - * {@link #format(String, Object[])},{@link #parse(String, ParsePosition)}, + * #setFormatsByArgumentIndex(Format[])}, {@link #getFormatsByArgumentIndex()}, + * {@link #format(Object[], StringBuffer, FieldPosition)}, + * {@link #format(String, Object[])},{@link #parse(String, ParsePosition)}, * and {@link #parse(String)}. * These APIs all have corresponding new versions as listed above. *

@@ -593,7 +593,7 @@ public class MessageFormat extends UFormat { /** * Returns a pattern representing the current state of the message format. * The string is constructed from internal information and therefore - * does not necessarily equal the previously applied pattern. + * does not necessarily equal the previously applied pattern. * * @return a pattern representing the current state of the message format * @stable ICU 3.0 @@ -652,9 +652,20 @@ public class MessageFormat extends UFormat { result.append(",choice," + ((ChoiceFormat) formats[i]).toPattern()); } else if (formats[i] instanceof PluralFormat) { - // TODO: Implement PluralFormat.toPattern(). - result.append(", plural, support for converting PluralFormat " - + "to pattern not yet available."); + String pattern = ((PluralFormat)formats[i]).toPattern(); + // TODO: PluralFormat doesn't do the single quote thing, just reapply + if (pattern.indexOf('\'') != 0) { + StringBuffer buf = new StringBuffer(); + for (int j = 0; j < pattern.length(); ++j) { + char ch = pattern.charAt(j); + if (ch == '\'') { + buf.append(ch); // double it + } + buf.append(ch); + } + pattern = buf.toString(); + } + result.append(",plural," + pattern); } else { //result.append(", unknown"); } @@ -682,10 +693,10 @@ public class MessageFormat extends UFormat { * corresponding new format is ignored. If fewer formats are provided * than needed, then only the formats for argument indices less * than newFormats.length are replaced. - * + * * This method is only supported if the format does not use * named arguments, otherwise an IllegalArgumentException is thrown. - * + * * @param newFormats * the new formats to use * @throws NullPointerException @@ -693,7 +704,7 @@ public class MessageFormat extends UFormat { * @throws IllegalArgumentException * if this formatter uses named arguments * @stable ICU 3.0 - */ + */ public void setFormatsByArgumentIndex(Format[] newFormats) { if (!argumentNamesAreNumeric) { throw new IllegalArgumentException( @@ -707,7 +718,7 @@ public class MessageFormat extends UFormat { } } } - + /** * Sets the formats to use for the values passed into * format methods or returned from parse @@ -784,10 +795,10 @@ public class MessageFormat extends UFormat { * in the pattern string, then the new format is used for all such * format elements. If the argument index is not used for any format * element in the pattern string, then the new format is ignored. - * + * * This method is only supported when exclusively numbers are used for * argument names. Otherwise an IllegalArgumentException is thrown. - * + * * @param argumentIndex * the argument index for which to use the new format * @param newFormat @@ -874,10 +885,10 @@ public class MessageFormat extends UFormat { * format element is returned in the array. If an argument index * is not used for any format element in the pattern string, then * null is returned in the array. - * + * * This method is only supported when exclusively numbers are used for * argument names. Otherwise an IllegalArgumentException is thrown. - * + * * @return the formats used for the arguments within the pattern * @throws IllegalArgumentException * if this format uses named arguments @@ -886,7 +897,7 @@ public class MessageFormat extends UFormat { public Format[] getFormatsByArgumentIndex() { if (!argumentNamesAreNumeric) { throw new IllegalArgumentException( - "This method is not available in MessageFormat objects " + + "This method is not available in MessageFormat objects " + "that use alphanumeric argument names."); } int maximumArgumentNumber = -1; @@ -904,7 +915,7 @@ public class MessageFormat extends UFormat { } // TODO: provide method public Map getFormatsByArgumentName(). // Where Map is: String argumentName --> Format format. - + /** * Gets the formats used for the format elements in the * previously set pattern string. @@ -921,7 +932,7 @@ public class MessageFormat extends UFormat { * * This method is only supported when exclusively numbers are used for * argument names. Otherwise an IllegalArgumentException is thrown. - * + * * @return the formats used for the format elements in the pattern * @stable ICU 3.0 */ @@ -991,7 +1002,7 @@ public class MessageFormat extends UFormat { * * This method is only supported when the format does not use named * arguments, otherwise an IllegalArgumentException is thrown. - * + * * @param arguments an array of objects to be formatted and substituted. * @param result where text is appended. * @param pos On input: an alignment field, if desired. @@ -1005,7 +1016,7 @@ public class MessageFormat extends UFormat { */ public final StringBuffer format(Object[] arguments, StringBuffer result, FieldPosition pos) - { + { if (!argumentNamesAreNumeric) { throw new IllegalArgumentException( "This method is not available in MessageFormat objects " + @@ -1021,7 +1032,7 @@ public class MessageFormat extends UFormat { *

* The text substituted for the individual format elements is derived from * the current subformat of the format element and the - * arguments value corresopnding to the format element's + * arguments value corresopnding to the format element's * argument name. *

* This API may be called on formats that do not use named arguments. @@ -1047,7 +1058,7 @@ public class MessageFormat extends UFormat { FieldPosition pos) { return subformat(arguments, result, pos, null); } - + /** * Creates a MessageFormat with the given pattern and uses it * to format the given arguments. This is equivalent to @@ -1102,7 +1113,7 @@ public class MessageFormat extends UFormat { * Formats a map or array of objects and appends the MessageFormat's * pattern, with format elements replaced by the formatted objects, to the * provided StringBuffer. - * This is equivalent to either of + * This is equivalent to either of *

* {@link #format(java.lang.Object[], java.lang.StringBuffer, java.text.FieldPosition) format}((Object[]) arguments, result, pos) * {@link #format(java.util.Map, java.lang.StringBuffer, java.text.FieldPosition) format}((Map) arguments, result, pos) @@ -1128,7 +1139,7 @@ public class MessageFormat extends UFormat { } else { if (!argumentNamesAreNumeric) { throw new IllegalArgumentException( - "This method is not available in MessageFormat objects " + + "This method is not available in MessageFormat objects " + "that use alphanumeric argument names."); } return subformat((Object[]) arguments, result, pos, null); @@ -1224,7 +1235,7 @@ public class MessageFormat extends UFormat { * This method is only supported with numbered arguments. If * the format pattern used named argument an * IllegalArgumentException is thrown. - * + * * @throws IllegalArgumentException if this format uses named arguments * @stable ICU 3.0 */ @@ -1242,21 +1253,21 @@ public class MessageFormat extends UFormat { maximumArgumentNumber = argumentNumber; } } - + if (objectMap == null) { return null; } - + Object[] resultArray = new Object[maximumArgumentNumber + 1]; Iterator keyIter = objectMap.keySet().iterator(); while (keyIter.hasNext()) { String key = (String) keyIter.next(); resultArray[Integer.parseInt(key)] = objectMap.get(key); } - + return resultArray; } - + /** * Parses the string, returning the results in a Map. * This is similar to the version that returns an array @@ -1286,7 +1297,7 @@ public class MessageFormat extends UFormat { // Object[] resultArray = new Object[maximumArgumentNumber + 1]; Map resultMap = new HashMap(); - + int patternOffset = 0; int sourceOffset = pos.getIndex(); ParsePosition tempStatus = new ParsePosition(0); @@ -1323,14 +1334,14 @@ public class MessageFormat extends UFormat { String strValue = source.substring(sourceOffset, next); if (!strValue.equals("{" + argumentNames[i] + "}")) resultMap.put(argumentNames[i], source.substring(sourceOffset, next)); -// resultArray[Integer.parseInt(argumentNames[i])] = +// resultArray[Integer.parseInt(argumentNames[i])] = // source.substring(sourceOffset, next); sourceOffset = next; } } else { tempStatus.setIndex(sourceOffset); resultMap.put(argumentNames[i], formats[i].parseObject(source, tempStatus)); -// resultArray[Integer.parseInt(argumentNames[i])] = +// resultArray[Integer.parseInt(argumentNames[i])] = // formats[i].parseObject(source, tempStatus); if (tempStatus.getIndex() == sourceOffset) { pos.setErrorIndex(sourceOffset); @@ -1375,7 +1386,7 @@ public class MessageFormat extends UFormat { return result; } - + /** * Parses text from the beginning of the given string to produce a map from * argument to values. The method may not use the entire text of the given string. @@ -1385,13 +1396,13 @@ public class MessageFormat extends UFormat { * * @param source A String whose beginning should be parsed. * @return A Map parsed from the string. - * @throws ParseException if the beginning of the specified string cannot + * @throws ParseException if the beginning of the specified string cannot * be parsed. * @see #parseToMap(String, ParsePosition) * @stable ICU 3.8 */ public Map parseToMap(String source) throws ParseException { - + ParsePosition pos = new ParsePosition(0); Map result = parseToMap(source, pos); if (pos.getIndex() == 0) // unchanged, returned object is null @@ -1400,7 +1411,7 @@ public class MessageFormat extends UFormat { return result; } - + /** * Parses text from a string to produce an object array or Map. *

@@ -1432,7 +1443,7 @@ public class MessageFormat extends UFormat { if (argumentNamesAreNumeric) { return parse(source, pos); } else { - return parseToMap(source, pos); + return parseToMap(source, pos); } } @@ -1492,7 +1503,7 @@ public class MessageFormat extends UFormat { * Defines constants that are used as attribute keys in the * AttributedCharacterIterator returned * from MessageFormat.formatToCharacterIterator. - * + * * @stable ICU 3.8 */ public static class Field extends Format.Field { @@ -1501,9 +1512,9 @@ public class MessageFormat extends UFormat { /** * Create a Field with the specified name. - * + * * @param name The name of the attribute - * + * * @stable ICU 3.8 */ protected Field(String name) { @@ -1512,10 +1523,10 @@ public class MessageFormat extends UFormat { /** * Resolves instances being deserialized to the predefined constants. - * + * * @return resolved MessageFormat.Field constant * @throws InvalidObjectException if the constant could not be resolved. - * + * * @stable ICU 3.8 */ protected Object readResolve() throws InvalidObjectException { @@ -1535,7 +1546,7 @@ public class MessageFormat extends UFormat { * The value associated with the key will be an Integer * indicating the index in the arguments array of the * argument from which the text was generated. - * + * * @stable ICU 3.8 */ public static final Field ARGUMENT = new Field("message argument field"); @@ -1577,7 +1588,7 @@ public class MessageFormat extends UFormat { /** * The positions where the results of formatting each argument are to be * inserted into the pattern. - * + * * @serial */ private int[] offsets = new int[INITIAL_FORMATS]; @@ -1595,14 +1606,14 @@ public class MessageFormat extends UFormat { * The argument names corresponding to each formatter. (The formatters are * stored in the order they occur in the pattern, not in the order in which * the arguments are specified.) - * + * * @serial */ private String[] argumentNames = new String[INITIAL_FORMATS]; /** * Is true iff all argument names are non-negative numbers. - * + * * @serial */ private boolean argumentNamesAreNumeric = true; @@ -1784,7 +1795,7 @@ public class MessageFormat extends UFormat { private static final String[] typeList = {"", "number", "date", "time", "choice", "spellout", "ordinal", "duration", "plural"}; - private static final int + private static final int TYPE_EMPTY = 0, TYPE_NUMBER = 1, TYPE_DATE = 2, @@ -1797,23 +1808,23 @@ public class MessageFormat extends UFormat { private static final String[] modifierList = {"", "currency", "percent", "integer"}; - + private static final int MODIFIER_EMPTY = 0, MODIFIER_CURRENCY = 1, MODIFIER_PERCENT = 2, MODIFIER_INTEGER = 3; - + private static final String[] dateModifierList = {"", "short", "medium", "long", "full"}; - + private static final int DATE_MODIFIER_EMPTY = 0, DATE_MODIFIER_SHORT = 1, DATE_MODIFIER_MEDIUM = 2, DATE_MODIFIER_LONG = 3, DATE_MODIFIER_FULL = 4; - + private void makeFormat(int position, int offsetNumber, StringBuffer[] segments) { @@ -1852,7 +1863,7 @@ public class MessageFormat extends UFormat { int argumentNumber; try { // always unlocalized! - argumentNumber = Integer.parseInt(segments[1].toString()); + argumentNumber = Integer.parseInt(segments[1].toString()); } catch (NumberFormatException e) { argumentNumber = -1; } @@ -1861,9 +1872,9 @@ public class MessageFormat extends UFormat { // to be numbers or (IDStartChars IDContChars*) strings. argumentNamesAreNumeric = argumentNumber >= 0; } - + if (argumentNamesAreNumeric && argumentNumber < 0 || - !argumentNamesAreNumeric && + !argumentNamesAreNumeric && !isAlphaIdentifier(argumentNames[offsetNumber])) { throw new IllegalArgumentException( "All argument identifiers have to be either non-negative " + @@ -1949,7 +1960,7 @@ public class MessageFormat extends UFormat { throw new IllegalArgumentException("Choice Pattern incorrect"); } break; - case TYPE_SPELLOUT: + case TYPE_SPELLOUT: { RuleBasedNumberFormat rbnf = new RuleBasedNumberFormat(ulocale, RuleBasedNumberFormat.SPELLOUT); String ruleset = segments[3].toString().trim(); @@ -1962,7 +1973,7 @@ public class MessageFormat extends UFormat { } } newFormat = rbnf; - } + } break; case TYPE_ORDINAL: { @@ -1977,7 +1988,7 @@ public class MessageFormat extends UFormat { } } newFormat = rbnf; - } + } break; case TYPE_DURATION: { @@ -2105,7 +2116,7 @@ public class MessageFormat extends UFormat { * This is a helper method for converting an object array into a map. The * key set of the map is [0, ..., array.length]. The value associated with * each key is the ith entry of the passed object array. - * + * * @throws InvalidObjectException * if the objects read from the stream is invalid. */ @@ -2118,14 +2129,14 @@ public class MessageFormat extends UFormat { } return map; } - + private boolean isAlphaIdentifier(String argument) { if (argument.length() == 0) { return false; } for (int i = 0; i < argument.length(); ++i ) { if (i == 0 && !IDStartChars.contains(argument.charAt(i)) || - i > 0 && !IDContChars.contains(argument.charAt(i))){ + i > 0 && !IDContChars.contains(argument.charAt(i))){ return false; } } @@ -2140,14 +2151,14 @@ public class MessageFormat extends UFormat { private static final int STATE_SINGLE_QUOTE = 1; private static final int STATE_IN_QUOTE = 2; private static final int STATE_MSG_ELEMENT = 3; - + private static UnicodeSet IDStartChars = new UnicodeSet("[:ID_Start:]"); private static UnicodeSet IDContChars = new UnicodeSet("[:ID_Continue:]"); /** * Convert an 'apostrophe-friendly' pattern into a standard * pattern. Standard patterns treat all apostrophes as - * quotes, which is problematic in some languages, e.g. + * quotes, which is problematic in some languages, e.g. * French, where apostrophe is commonly used. This utility * assumes that only an unpaired apostrophe immediately before * a brace is a true quote. Other unpaired apostrophes are paired, diff --git a/icu4j/src/com/ibm/icu/text/PluralFormat.java b/icu4j/src/com/ibm/icu/text/PluralFormat.java index 72d93b757f..a0b85506b6 100644 --- a/icu4j/src/com/ibm/icu/text/PluralFormat.java +++ b/icu4j/src/com/ibm/icu/text/PluralFormat.java @@ -21,7 +21,7 @@ import java.util.Set; *

* PluralFormat supports the creation of internationalized * messages with plural inflection. It is based on plural - * selection, i.e. the caller specifies messages for each + * selection, i.e. the caller specifies messages for each * plural case that can appear in the users language and the * PluralFormat selects the appropriate message based on * the number. @@ -68,7 +68,7 @@ import java.util.Set; *

Patterns and Their Interpretation
*

* The pattern text defines the message output for each plural case of the - * used locale. The pattern is a sequence of + * used locale. The pattern is a sequence of * caseKeyword{message} clauses, separated by white * space characters. Each clause assigns the message message * to the plural case identified by caseKeyword. @@ -84,9 +84,9 @@ import java.util.Set; * an IllegalArgumentException is thrown. *
* Spaces between caseKeyword and - * message will be ignored; spaces within + * message will be ignored; spaces within * message will be preserved. - *

+ *

* The message text for a particular plural case may contain other message * format patterns. PluralFormat preserves these so that you * can use the strings produced by PluralFormat with other @@ -143,7 +143,7 @@ import java.util.Set; * For more information about PluralRules, see * {@link PluralRules}. *

- * + * * @author tschumann (Tim Schumann) * @draft ICU 3.8 * @provisional This API might change or be removed in a future release. @@ -169,8 +169,8 @@ public class PluralFormat extends UFormat { /** * The format messages for each plural case. It is a mapping: - * String(plural case keyword) --> String - * (message for this plural case). + * String(plural case keyword) --> String + * (message for this plural case). */ private Map parsedValues = null; @@ -202,10 +202,10 @@ public class PluralFormat extends UFormat { public PluralFormat(ULocale ulocale) { init(null, ulocale); } - + /** * Creates a new PluralFormat for a given set of rules. - * The standard number formatting will be done using the default locale. + * The standard number formatting will be done using the default locale. * @param rules defines the behavior of the PluralFormat * object. * @draft ICU 3.8 @@ -244,7 +244,7 @@ public class PluralFormat extends UFormat { } /** - * Creates a new PluralFormat for a given pattern string and + * Creates a new PluralFormat for a given pattern string and * locale. * The locale will be used to get the set of plural rules and for * standard number formatting. @@ -262,23 +262,23 @@ public class PluralFormat extends UFormat { } /** - * Creates a new PluralFormat for a given set of rules and a + * Creates a new PluralFormat for a given set of rules and a * pattern. - * The standard number formatting will be done using the default locale. + * The standard number formatting will be done using the default locale. * @param rules defines the behavior of the PluralFormat * object. * @param pattern the pattern for this PluralFormat. * @throws IllegalArgumentException if the pattern is invalid. * @draft ICU 3.8 * @provisional This API might change or be removed in a future release. - */ + */ public PluralFormat(PluralRules rules, String pattern) { init(rules, ULocale.getDefault()); applyPattern(pattern); } - + /** - * Creates a new PluralFormat for a given set of rules, a + * Creates a new PluralFormat for a given set of rules, a * pattern and a locale. * @param ulocale the PluralFormat will be configured with * rules for this locale. This locale will also be used for standard @@ -299,10 +299,10 @@ public class PluralFormat extends UFormat { * Initializes the PluralRules object. * Postcondition:
* ulocale : is locale
- * pluralRules: if rules != null - * it's set to rules, otherwise it is the + * pluralRules: if rules != null + * it's set to rules, otherwise it is the * predefined plural rule set for the locale - * ulocale.
+ * ulocale.
* parsedValues: is null
* pattern: is null
* numberFormat: a NumberFormat for the locale @@ -322,13 +322,15 @@ public class PluralFormat extends UFormat { * The method parses the pattern and creates a map of format strings * for the plural rules. * Patterns and their interpretation are specified in the class description. - * + * * @param pttrn the pattern for this plural format. * @throws IllegalArgumentException if the pattern is invalid. * @draft ICU 3.8 * @provisional This API might change or be removed in a future release. */ public void applyPattern(String pttrn) { + pttrn = pttrn.trim(); + this.pattern = pttrn; int braceStack = 0; Set ruleNames = pluralRules.getKeywords(); @@ -413,9 +415,20 @@ public class PluralFormat extends UFormat { checkSufficientDefinition(); } + /** + * Returns the pattern for this PluralFormat. + * + * @return the pattern string + * @draft ICU 4.2 + * @provisional This API might change or be removed in a future release. + */ + public String toPattern() { + return pattern; + } + /** * Formats a plural message for a given number. - * + * * @param number a number for which the plural message should be formatted. * If no pattern has been applied to this * PluralFormat object yet, the formatted number will @@ -434,14 +447,13 @@ public class PluralFormat extends UFormat { String selectedRule = pluralRules.select(number); String selectedPattern = (String) parsedValues.get(selectedRule); if (selectedPattern == null) { // Fallback to others. - selectedPattern = + selectedPattern = (String) parsedValues.get(PluralRules.KEYWORD_OTHER); } // Get formatted number and insert it into String. // Will replace all '#' which are not inside curly braces by the // formatted number. return insertFormattedNumber(number, selectedPattern); - } /** @@ -452,10 +464,10 @@ public class PluralFormat extends UFormat { * applied to this PluralFormat object yet, the * formatted number will be returned. * Note: If this object is not an instance of Number, - * the toAppendTo will not be modified. + * the toAppendTo will not be modified. * @param toAppendTo the formatted message will be appended to this * StringBuffer. - * @param pos will be ignored by this method. + * @param pos will be ignored by this method. * @return the string buffer passed in as toAppendTo, with formatted text * appended. * @throws IllegalArgumentException if number is not an instance of Number @@ -468,7 +480,7 @@ public class PluralFormat extends UFormat { toAppendTo.append(format(((Number) number).doubleValue())); return toAppendTo; } - throw new IllegalArgumentException("'" + number + + throw new IllegalArgumentException("'" + number + "' is not a Number"); } @@ -487,7 +499,7 @@ public class PluralFormat extends UFormat { public Number parse(String text, ParsePosition parsePosition) { throw new UnsupportedOperationException(); } - + /** * This method is not yet supported by PluralFormat. * @param source the string to be parsed. @@ -564,7 +576,7 @@ public class PluralFormat extends UFormat { init(null, ULocale.getDefault()); throw new IllegalArgumentException(errorText); } - + /** * Helper method that is called during formatting. * It replaces the character '#' by the number used for plural selection in @@ -586,10 +598,10 @@ public class PluralFormat extends UFormat { int startIndex = 0; for (int i = 0; i < message.length(); ++i) { switch (message.charAt(i)) { - case '{': + case '{': ++braceStack; break; - case '}': + case '}': --braceStack; break; case '#': @@ -628,7 +640,7 @@ public class PluralFormat extends UFormat { parsedValues.equals(rhs.parsedValues) && numberFormat.equals(rhs.numberFormat); } - + /** * {@inheritDoc} * @draft ICU 3.8