Skip to content

Commit ce93d27

Browse files
author
Justin Lu
committed
6228794: java.text.ChoiceFormat pattern behavior is not well documented.
Reviewed-by: naoto
1 parent 3b0a6d2 commit ce93d27

File tree

1 file changed

+116
-47
lines changed

1 file changed

+116
-47
lines changed

src/java.base/share/classes/java/text/ChoiceFormat.java

Lines changed: 116 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,9 @@
4444
import java.util.Arrays;
4545

4646
/**
47-
* A {@code ChoiceFormat} allows you to attach a format to a range of numbers.
48-
* It is generally used in a {@code MessageFormat} for handling plurals.
47+
* {@code ChoiceFormat} is a concrete subclass of {@code NumberFormat} that
48+
* allows you to attach a format to a range of numbers.
49+
* It is generally used in a {@link MessageFormat} for handling plurals.
4950
* The choice is specified with an ascending list of doubles, where each item
5051
* specifies a half-open interval up to the next item:
5152
* <blockquote>
@@ -68,8 +69,10 @@
6869
* {@code ChoiceFormat} doesn't implement any locale specific behavior.
6970
*
7071
* <p>
71-
* When creating a {@code ChoiceFormat}, you must specify an array of formats
72-
* and an array of limits. The length of these arrays must be the same.
72+
* A {@code ChoiceFormat} can be constructed using either an array of formats
73+
* and an array of limits or a string pattern. When constructing with
74+
* format and limit arrays, the length of these arrays must be the same.
75+
*
7376
* For example,
7477
* <ul>
7578
* <li>
@@ -83,7 +86,8 @@
8386
* </ul>
8487
*
8588
* <p>
86-
* Here is a simple example that shows formatting and parsing:
89+
* Below is an example of constructing a ChoiceFormat with arrays to format
90+
* and parse values:
8791
* <blockquote>
8892
* {@snippet lang=java :
8993
* double[] limits = {1,2,3,4,5,6,7};
@@ -97,7 +101,8 @@
97101
* }
98102
* }
99103
* </blockquote>
100-
* Here is a more complex example, with a pattern format:
104+
* For more sophisticated patterns, {@code ChoiceFormat} can be used with
105+
* {@link MessageFormat} to produce accurate forms for singular and plural:
101106
* <blockquote>
102107
* {@snippet lang=java :
103108
* double[] filelimits = {0,1,2};
@@ -114,42 +119,92 @@
114119
* }
115120
* }
116121
* </blockquote>
117-
* <p>
118-
* Specifying a pattern for ChoiceFormat objects is fairly straightforward.
119-
* For example:
122+
* Would output the following:
123+
* <blockquote>
124+
* <pre>{@code
125+
* There are no files on ADisk
126+
* There is one file on ADisk
127+
* There are 2 files on ADisk
128+
* There are 3 files on ADisk
129+
* }</pre>
130+
* </blockquote>
131+
*
132+
* <h2><a id="patterns">Patterns</a></h2>
133+
* A {@code ChoiceFormat} pattern has the following syntax:
134+
* <blockquote>
135+
* <dl>
136+
* <dt><i>Pattern:</i>
137+
* <dd>SubPattern *("|" SubPattern)
138+
* <dd><i>Note: Each additional SubPattern must have a Limit greater than the previous SubPattern's Limit</i>
139+
* </dl>
140+
*
141+
* <dl>
142+
* <dt><i>SubPattern:</i>
143+
* <dd>Limit Relation Format
144+
* </dl>
145+
*
146+
* <dl>
147+
* <dt><i>Limit:</i>
148+
* <dd>Number / "&infin;" / "-&infin;"
149+
* </dl>
150+
*
151+
* <dl>
152+
* <dt><i>Number:</i>
153+
* <dd>["-"] *(Digit) 1*(Decimal / Digit) *(Digit) [Exponent]
154+
* </dl>
155+
*
156+
* <dl>
157+
* <dt><i>Decimal:</i>
158+
* <dd>1*(Digit ".") / 1*("." Digit)
159+
* </dl>
160+
*
161+
* <dl>
162+
* <dt><i>Digit:</i>
163+
* <dd>0 - 9
164+
* </dl>
165+
*
166+
* <dl>
167+
* <dt><i>Exponent:</i>
168+
* <dd>*(Digit) Digit ExponentSymbol Digit *(Digit)
169+
* </dl>
170+
*
171+
* <dl>
172+
* <dt><i>ExponentSymbol:</i>
173+
* <dd>"e" / "E"
174+
* </dl>
175+
*
176+
* <dl>
177+
* <dt><i>Relation:</i>
178+
* <dd>"#" / "&lt;" / "&le;"
179+
* </dl>
180+
*
181+
* <dl>
182+
* <dt><i>Format:</i>
183+
* <dd>Any characters except the <i>Relation</i> symbols
184+
* </dl>
185+
*
186+
* </blockquote>
187+
*
188+
* <i>Note:The relation &le; is not equivalent to &lt;&equals;</i>
189+
*
190+
* <p>Below is an example of constructing a ChoiceFormat with a pattern:
120191
* <blockquote>
121192
* {@snippet lang=java :
122193
* ChoiceFormat fmt = new ChoiceFormat(
123194
* "-1#is negative| 0#is zero or fraction | 1#is one |1.0<is 1+ |2#is two |2<is more than 2.");
124-
* System.out.println("Formatter Pattern : " + fmt.toPattern());
125195
*
126-
* System.out.println("Format with -INF : " + fmt.format(Double.NEGATIVE_INFINITY));
127-
* System.out.println("Format with -1.0 : " + fmt.format(-1.0));
128-
* System.out.println("Format with 0 : " + fmt.format(0));
129-
* System.out.println("Format with 0.9 : " + fmt.format(0.9));
130-
* System.out.println("Format with 1.0 : " + fmt.format(1));
131-
* System.out.println("Format with 1.5 : " + fmt.format(1.5));
132-
* System.out.println("Format with 2 : " + fmt.format(2));
133-
* System.out.println("Format with 2.1 : " + fmt.format(2.1));
134-
* System.out.println("Format with NaN : " + fmt.format(Double.NaN));
135-
* System.out.println("Format with +INF : " + fmt.format(Double.POSITIVE_INFINITY));
196+
* System.out.println(fmt.format(Double.NEGATIVE_INFINITY)); // outputs "is negative"
197+
* System.out.println(fmt.format(-1.0)); // outputs "is negative"
198+
* System.out.println(fmt.format(0)); // outputs "is zero or fraction"
199+
* System.out.println(fmt.format(0.9)); // outputs "is zero or fraction"
200+
* System.out.println(fmt.format(1)); // outputs "is one"
201+
* System.out.println(fmt.format(1.5)); // outputs "is 1+"
202+
* System.out.println(fmt.format(2)); // outputs "is two"
203+
* System.out.println(fmt.format(2.1)); // outputs "is more than 2."
204+
* System.out.println(fmt.format(Double.NaN)); // outputs "is negative"
205+
* System.out.println(fmt.format(Double.POSITIVE_INFINITY)); // outputs "is more than 2."
136206
* }
137207
* </blockquote>
138-
* And the output result would be like the following:
139-
* <blockquote>
140-
* <pre>{@code
141-
* Format with -INF : is negative
142-
* Format with -1.0 : is negative
143-
* Format with 0 : is zero or fraction
144-
* Format with 0.9 : is zero or fraction
145-
* Format with 1.0 : is one
146-
* Format with 1.5 : is 1+
147-
* Format with 2 : is two
148-
* Format with 2.1 : is more than 2.
149-
* Format with NaN : is negative
150-
* Format with +INF : is more than 2.
151-
* }</pre>
152-
* </blockquote>
153208
*
154209
* <h2><a id="synchronization">Synchronization</a></h2>
155210
*
@@ -172,12 +227,16 @@ public class ChoiceFormat extends NumberFormat {
172227
private static final long serialVersionUID = 1795184449645032964L;
173228

174229
/**
175-
* Sets the pattern.
176-
* @param newPattern See the class description.
230+
* Apply the given pattern to this ChoiceFormat object. The syntax
231+
* for the ChoiceFormat pattern can be seen in the {@linkplain ##patterns
232+
* Patterns} section.
233+
*
234+
* @param newPattern a pattern string
177235
* @throws NullPointerException if {@code newPattern}
178236
* is {@code null}
179237
* @throws IllegalArgumentException if {@code newPattern}
180-
* is invalid
238+
* violates the pattern syntax
239+
* @see #ChoiceFormat(String)
181240
*/
182241
public void applyPattern(String newPattern) {
183242
StringBuilder[] segments = new StringBuilder[2];
@@ -260,9 +319,14 @@ public void applyPattern(String newPattern) {
260319
}
261320

262321
/**
263-
* Gets the pattern.
322+
* {@return a pattern {@code string} that represents the the limits and formats
323+
* of this ChoiceFormat object}
264324
*
265-
* @return the pattern string
325+
* The {@code string} returned is not guaranteed to be the same input
326+
* {@code string} passed to either {@link #applyPattern(String)} or
327+
* {@link #ChoiceFormat(String)}.
328+
*
329+
* @see #applyPattern(String)
266330
*/
267331
public String toPattern() {
268332
StringBuilder result = new StringBuilder();
@@ -312,13 +376,16 @@ public String toPattern() {
312376
}
313377

314378
/**
315-
* Constructs with limits and corresponding formats based on the pattern.
379+
* Constructs a ChoiceFormat with limits and corresponding formats
380+
* based on the pattern.
381+
* The syntax for the ChoiceFormat pattern can be seen in the {@linkplain
382+
* ##patterns Patterns} section.
316383
*
317384
* @param newPattern the new pattern string
318385
* @throws NullPointerException if {@code newPattern} is
319386
* {@code null}
320387
* @throws IllegalArgumentException if {@code newPattern}
321-
* is invalid
388+
* violates the pattern syntax
322389
* @see #applyPattern
323390
*/
324391
public ChoiceFormat(String newPattern) {
@@ -364,17 +431,15 @@ public void setChoices(double[] limits, String[] formats) {
364431
}
365432

366433
/**
367-
* Get the limits passed in the constructor.
368-
* @return the limits.
434+
* {@return the limits of this ChoiceFormat}
369435
*/
370436
public double[] getLimits() {
371437
double[] newLimits = Arrays.copyOf(choiceLimits, choiceLimits.length);
372438
return newLimits;
373439
}
374440

375441
/**
376-
* Get the formats passed in the constructor.
377-
* @return the formats.
442+
* {@return the formats of this ChoiceFormat}
378443
*/
379444
public Object[] getFormats() {
380445
Object[] newFormats = Arrays.copyOf(choiceFormats, choiceFormats.length);
@@ -390,6 +455,7 @@ public Object[] getFormats() {
390455
* the range that can be stored by double. This will never be
391456
* a practical limitation.
392457
*/
458+
@Override
393459
public StringBuffer format(long number, StringBuffer toAppendTo,
394460
FieldPosition status) {
395461
return format((double)number, toAppendTo, status);
@@ -403,7 +469,8 @@ public StringBuffer format(long number, StringBuffer toAppendTo,
403469
* @throws NullPointerException if {@code toAppendTo}
404470
* is {@code null}
405471
*/
406-
public StringBuffer format(double number, StringBuffer toAppendTo,
472+
@Override
473+
public StringBuffer format(double number, StringBuffer toAppendTo,
407474
FieldPosition status) {
408475
// find the number
409476
int i;
@@ -434,6 +501,7 @@ public StringBuffer format(double number, StringBuffer toAppendTo,
434501
* or if {@code text} is {@code null} and the list of
435502
* choice strings is not empty.
436503
*/
504+
@Override
437505
public Number parse(String text, ParsePosition status) {
438506
// find the best number (defined as the one with the longest parse)
439507
int start = status.index;
@@ -493,6 +561,7 @@ public static final double previousDouble (double d) {
493561
/**
494562
* Overrides Cloneable
495563
*/
564+
@Override
496565
public Object clone()
497566
{
498567
ChoiceFormat other = (ChoiceFormat) super.clone();

0 commit comments

Comments
 (0)