157 * Choice formats are not synchronized.
158 * It is recommended to create separate format instances for each thread.
159 * If multiple threads access a format concurrently, it must be synchronized
160 * externally.
161 *
162 *
163 * @see DecimalFormat
164 * @see MessageFormat
165 * @author Mark Davis
166 * @since 1.1
167 */
168 public class ChoiceFormat extends NumberFormat {
169
170 // Proclaim serial compatibility with 1.1 FCS
171 @java.io.Serial
172 private static final long serialVersionUID = 1795184449645032964L;
173
174 /**
175 * Sets the pattern.
176 * @param newPattern See the class description.
177 * @exception NullPointerException if {@code newPattern}
178 * is {@code null}
179 */
180 public void applyPattern(String newPattern) {
181 StringBuffer[] segments = new StringBuffer[2];
182 for (int i = 0; i < segments.length; ++i) {
183 segments[i] = new StringBuffer();
184 }
185 double[] newChoiceLimits = new double[30];
186 String[] newChoiceFormats = new String[30];
187 int count = 0;
188 int part = 0;
189 double startValue = 0;
190 double oldStartValue = Double.NaN;
191 boolean inQuote = false;
192 for (int i = 0; i < newPattern.length(); ++i) {
193 char ch = newPattern.charAt(i);
194 if (ch=='\'') {
195 // Check for "''" indicating a literal quote
196 if ((i+1)<newPattern.length() && newPattern.charAt(i+1)==ch) {
197 segments[part].append(ch);
296 || text.indexOf('\u2264') >= 0
297 || text.indexOf('|') >= 0;
298 if (needQuote) result.append('\'');
299 if (text.indexOf('\'') < 0) result.append(text);
300 else {
301 for (int j=0; j<text.length(); ++j) {
302 char c = text.charAt(j);
303 result.append(c);
304 if (c == '\'') result.append(c);
305 }
306 }
307 if (needQuote) result.append('\'');
308 }
309 return result.toString();
310 }
311
312 /**
313 * Constructs with limits and corresponding formats based on the pattern.
314 *
315 * @param newPattern the new pattern string
316 * @exception NullPointerException if {@code newPattern} is
317 * {@code null}
318 * @see #applyPattern
319 */
320 public ChoiceFormat(String newPattern) {
321 applyPattern(newPattern);
322 }
323
324 /**
325 * Constructs with the limits and the corresponding formats.
326 *
327 * @param limits limits in ascending order
328 * @param formats corresponding format strings
329 * @exception NullPointerException if {@code limits} or {@code formats}
330 * is {@code null}
331 * @see #setChoices
332 */
333 public ChoiceFormat(double[] limits, String[] formats) {
334 setChoices(limits, formats);
335 }
336
337 /**
338 * Set the choices to be used in formatting.
339 * @param limits contains the top value that you want
340 * parsed with that format, and should be in ascending sorted order. When
341 * formatting X, the choice will be the i, where
342 * limit[i] ≤ X {@literal <} limit[i+1].
343 * If the limit array is not in ascending order, the results of formatting
344 * will be incorrect.
345 * @param formats are the formats you want to use for each limit.
346 * They can be either Format objects or Strings.
347 * When formatting with object Y,
348 * if the object is a NumberFormat, then ((NumberFormat) Y).format(X)
349 * is called. Otherwise Y.toString() is called.
350 * @exception NullPointerException if {@code limits} or
351 * {@code formats} is {@code null}
352 */
353 public void setChoices(double[] limits, String formats[]) {
354 if (limits.length != formats.length) {
355 throw new IllegalArgumentException(
356 "Array and limit arrays must be of the same length.");
357 }
358 choiceLimits = Arrays.copyOf(limits, limits.length);
359 choiceFormats = Arrays.copyOf(formats, formats.length);
360 }
361
362 /**
363 * Get the limits passed in the constructor.
364 * @return the limits.
365 */
366 public double[] getLimits() {
367 double[] newLimits = Arrays.copyOf(choiceLimits, choiceLimits.length);
368 return newLimits;
369 }
370
379
380 // Overrides
381
382 /**
383 * Specialization of format. This method really calls
384 * <code>format(double, StringBuffer, FieldPosition)</code>
385 * thus the range of longs that are supported is only equal to
386 * the range that can be stored by double. This will never be
387 * a practical limitation.
388 */
389 public StringBuffer format(long number, StringBuffer toAppendTo,
390 FieldPosition status) {
391 return format((double)number, toAppendTo, status);
392 }
393
394 /**
395 * Returns pattern with formatted double.
396 * @param number number to be formatted and substituted.
397 * @param toAppendTo where text is appended.
398 * @param status ignore no useful status is returned.
399 * @exception NullPointerException if {@code toAppendTo}
400 * is {@code null}
401 */
402 public StringBuffer format(double number, StringBuffer toAppendTo,
403 FieldPosition status) {
404 // find the number
405 int i;
406 for (i = 0; i < choiceLimits.length; ++i) {
407 if (!(number >= choiceLimits[i])) {
408 // same as number < choiceLimits, except catchs NaN
409 break;
410 }
411 }
412 --i;
413 if (i < 0) i = 0;
414 // return either a formatted number, or a string
415 return toAppendTo.append(choiceFormats[i]);
416 }
417
418 /**
419 * Parses a Number from the input text.
420 * @param text the source text.
421 * @param status an input-output parameter. On input, the
422 * status.index field indicates the first character of the
423 * source text that should be parsed. On exit, if no error
424 * occurred, status.index is set to the first unparsed character
425 * in the source text. On exit, if an error did occur,
426 * status.index is unchanged and status.errorIndex is set to the
427 * first index of the character that caused the parse to fail.
428 * @return A Number representing the value of the number parsed.
429 * @exception NullPointerException if {@code status} is {@code null}
430 * or if {@code text} is {@code null} and the list of
431 * choice strings is not empty.
432 */
433 public Number parse(String text, ParsePosition status) {
434 // find the best number (defined as the one with the longest parse)
435 int start = status.index;
436 int furthest = start;
437 double bestNumber = Double.NaN;
438 double tempNumber = 0.0;
439 for (int i = 0; i < choiceFormats.length; ++i) {
440 String tempString = choiceFormats[i];
441 if (text.regionMatches(start, tempString, 0, tempString.length())) {
442 status.index = start + tempString.length();
443 tempNumber = choiceLimits[i];
444 if (status.index > furthest) {
445 furthest = status.index;
446 bestNumber = tempNumber;
447 if (furthest == text.length()) break;
448 }
449 }
|
157 * Choice formats are not synchronized.
158 * It is recommended to create separate format instances for each thread.
159 * If multiple threads access a format concurrently, it must be synchronized
160 * externally.
161 *
162 *
163 * @see DecimalFormat
164 * @see MessageFormat
165 * @author Mark Davis
166 * @since 1.1
167 */
168 public class ChoiceFormat extends NumberFormat {
169
170 // Proclaim serial compatibility with 1.1 FCS
171 @java.io.Serial
172 private static final long serialVersionUID = 1795184449645032964L;
173
174 /**
175 * Sets the pattern.
176 * @param newPattern See the class description.
177 * @throws NullPointerException if {@code newPattern}
178 * is {@code null}
179 */
180 public void applyPattern(String newPattern) {
181 StringBuffer[] segments = new StringBuffer[2];
182 for (int i = 0; i < segments.length; ++i) {
183 segments[i] = new StringBuffer();
184 }
185 double[] newChoiceLimits = new double[30];
186 String[] newChoiceFormats = new String[30];
187 int count = 0;
188 int part = 0;
189 double startValue = 0;
190 double oldStartValue = Double.NaN;
191 boolean inQuote = false;
192 for (int i = 0; i < newPattern.length(); ++i) {
193 char ch = newPattern.charAt(i);
194 if (ch=='\'') {
195 // Check for "''" indicating a literal quote
196 if ((i+1)<newPattern.length() && newPattern.charAt(i+1)==ch) {
197 segments[part].append(ch);
296 || text.indexOf('\u2264') >= 0
297 || text.indexOf('|') >= 0;
298 if (needQuote) result.append('\'');
299 if (text.indexOf('\'') < 0) result.append(text);
300 else {
301 for (int j=0; j<text.length(); ++j) {
302 char c = text.charAt(j);
303 result.append(c);
304 if (c == '\'') result.append(c);
305 }
306 }
307 if (needQuote) result.append('\'');
308 }
309 return result.toString();
310 }
311
312 /**
313 * Constructs with limits and corresponding formats based on the pattern.
314 *
315 * @param newPattern the new pattern string
316 * @throws NullPointerException if {@code newPattern} is
317 * {@code null}
318 * @see #applyPattern
319 */
320 public ChoiceFormat(String newPattern) {
321 applyPattern(newPattern);
322 }
323
324 /**
325 * Constructs with the limits and the corresponding formats.
326 *
327 * @param limits limits in ascending order
328 * @param formats corresponding format strings
329 * @throws NullPointerException if {@code limits} or {@code formats}
330 * is {@code null}
331 * @see #setChoices
332 */
333 public ChoiceFormat(double[] limits, String[] formats) {
334 setChoices(limits, formats);
335 }
336
337 /**
338 * Set the choices to be used in formatting.
339 * @param limits contains the top value that you want
340 * parsed with that format, and should be in ascending sorted order. When
341 * formatting X, the choice will be the i, where
342 * limit[i] ≤ X {@literal <} limit[i+1].
343 * If the limit array is not in ascending order, the results of formatting
344 * will be incorrect.
345 * @param formats are the formats you want to use for each limit.
346 * They can be either Format objects or Strings.
347 * When formatting with object Y,
348 * if the object is a NumberFormat, then ((NumberFormat) Y).format(X)
349 * is called. Otherwise Y.toString() is called.
350 * @throws NullPointerException if {@code limits} or
351 * {@code formats} is {@code null}
352 */
353 public void setChoices(double[] limits, String formats[]) {
354 if (limits.length != formats.length) {
355 throw new IllegalArgumentException(
356 "Array and limit arrays must be of the same length.");
357 }
358 choiceLimits = Arrays.copyOf(limits, limits.length);
359 choiceFormats = Arrays.copyOf(formats, formats.length);
360 }
361
362 /**
363 * Get the limits passed in the constructor.
364 * @return the limits.
365 */
366 public double[] getLimits() {
367 double[] newLimits = Arrays.copyOf(choiceLimits, choiceLimits.length);
368 return newLimits;
369 }
370
379
380 // Overrides
381
382 /**
383 * Specialization of format. This method really calls
384 * <code>format(double, StringBuffer, FieldPosition)</code>
385 * thus the range of longs that are supported is only equal to
386 * the range that can be stored by double. This will never be
387 * a practical limitation.
388 */
389 public StringBuffer format(long number, StringBuffer toAppendTo,
390 FieldPosition status) {
391 return format((double)number, toAppendTo, status);
392 }
393
394 /**
395 * Returns pattern with formatted double.
396 * @param number number to be formatted and substituted.
397 * @param toAppendTo where text is appended.
398 * @param status ignore no useful status is returned.
399 * @throws NullPointerException if {@code toAppendTo}
400 * is {@code null}
401 */
402 public StringBuffer format(double number, StringBuffer toAppendTo,
403 FieldPosition status) {
404 // find the number
405 int i;
406 for (i = 0; i < choiceLimits.length; ++i) {
407 if (!(number >= choiceLimits[i])) {
408 // same as number < choiceLimits, except catchs NaN
409 break;
410 }
411 }
412 --i;
413 if (i < 0) i = 0;
414 // return either a formatted number, or a string
415 return toAppendTo.append(choiceFormats[i]);
416 }
417
418 /**
419 * Parses a Number from the input text.
420 * @param text the source text.
421 * @param status an input-output parameter. On input, the
422 * status.index field indicates the first character of the
423 * source text that should be parsed. On exit, if no error
424 * occurred, status.index is set to the first unparsed character
425 * in the source text. On exit, if an error did occur,
426 * status.index is unchanged and status.errorIndex is set to the
427 * first index of the character that caused the parse to fail.
428 * @return A Number representing the value of the number parsed.
429 * @throws NullPointerException if {@code status} is {@code null}
430 * or if {@code text} is {@code null} and the list of
431 * choice strings is not empty.
432 */
433 public Number parse(String text, ParsePosition status) {
434 // find the best number (defined as the one with the longest parse)
435 int start = status.index;
436 int furthest = start;
437 double bestNumber = Double.NaN;
438 double tempNumber = 0.0;
439 for (int i = 0; i < choiceFormats.length; ++i) {
440 String tempString = choiceFormats[i];
441 if (text.regionMatches(start, tempString, 0, tempString.length())) {
442 status.index = start + tempString.length();
443 tempNumber = choiceLimits[i];
444 if (status.index > furthest) {
445 furthest = status.index;
446 bestNumber = tempNumber;
447 if (furthest == text.length()) break;
448 }
449 }
|