jdk/src/share/classes/java/text/ChoiceFormat.java
changeset 19054 a64012cb49d6
parent 18156 edb590d448c5
child 21278 ef8a3a2a72f2
equal deleted inserted replaced
19053:69648476a89e 19054:a64012cb49d6
     1 /*
     1 /*
     2  * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    48  * It is generally used in a <code>MessageFormat</code> for handling plurals.
    48  * It is generally used in a <code>MessageFormat</code> for handling plurals.
    49  * The choice is specified with an ascending list of doubles, where each item
    49  * The choice is specified with an ascending list of doubles, where each item
    50  * specifies a half-open interval up to the next item:
    50  * specifies a half-open interval up to the next item:
    51  * <blockquote>
    51  * <blockquote>
    52  * <pre>
    52  * <pre>
    53  * X matches j if and only if limit[j] &lt;= X &lt; limit[j+1]
    53  * X matches j if and only if limit[j] &le; X &lt; limit[j+1]
    54  * </pre>
    54  * </pre>
    55  * </blockquote>
    55  * </blockquote>
    56  * If there is no match, then either the first or last index is used, depending
    56  * If there is no match, then either the first or last index is used, depending
    57  * on whether the number (X) is too low or too high.  If the limit array is not
    57  * on whether the number (X) is too low or too high.  If the limit array is not
    58  * in ascending order, the results of formatting will be incorrect.  ChoiceFormat
    58  * in ascending order, the results of formatting will be incorrect.  ChoiceFormat
    83  * </ul>
    83  * </ul>
    84  *
    84  *
    85  * <p>
    85  * <p>
    86  * Here is a simple example that shows formatting and parsing:
    86  * Here is a simple example that shows formatting and parsing:
    87  * <blockquote>
    87  * <blockquote>
    88  * <pre>
    88  * <pre>{@code
    89  * double[] limits = {1,2,3,4,5,6,7};
    89  * double[] limits = {1,2,3,4,5,6,7};
    90  * String[] dayOfWeekNames = {"Sun","Mon","Tue","Wed","Thur","Fri","Sat"};
    90  * String[] dayOfWeekNames = {"Sun","Mon","Tue","Wed","Thur","Fri","Sat"};
    91  * ChoiceFormat form = new ChoiceFormat(limits, dayOfWeekNames);
    91  * ChoiceFormat form = new ChoiceFormat(limits, dayOfWeekNames);
    92  * ParsePosition status = new ParsePosition(0);
    92  * ParsePosition status = new ParsePosition(0);
    93  * for (double i = 0.0; i &lt;= 8.0; ++i) {
    93  * for (double i = 0.0; i <= 8.0; ++i) {
    94  *     status.setIndex(0);
    94  *     status.setIndex(0);
    95  *     System.out.println(i + " -&gt; " + form.format(i) + " -&gt; "
    95  *     System.out.println(i + " -> " + form.format(i) + " -> "
    96  *                              + form.parse(form.format(i),status));
    96  *                              + form.parse(form.format(i),status));
    97  * }
    97  * }
    98  * </pre>
    98  * }</pre>
    99  * </blockquote>
    99  * </blockquote>
   100  * Here is a more complex example, with a pattern format:
   100  * Here is a more complex example, with a pattern format:
   101  * <blockquote>
   101  * <blockquote>
   102  * <pre>
   102  * <pre>{@code
   103  * double[] filelimits = {0,1,2};
   103  * double[] filelimits = {0,1,2};
   104  * String[] filepart = {"are no files","is one file","are {2} files"};
   104  * String[] filepart = {"are no files","is one file","are {2} files"};
   105  * ChoiceFormat fileform = new ChoiceFormat(filelimits, filepart);
   105  * ChoiceFormat fileform = new ChoiceFormat(filelimits, filepart);
   106  * Format[] testFormats = {fileform, null, NumberFormat.getInstance()};
   106  * Format[] testFormats = {fileform, null, NumberFormat.getInstance()};
   107  * MessageFormat pattform = new MessageFormat("There {0} on {1}");
   107  * MessageFormat pattform = new MessageFormat("There {0} on {1}");
   108  * pattform.setFormats(testFormats);
   108  * pattform.setFormats(testFormats);
   109  * Object[] testArgs = {null, "ADisk", null};
   109  * Object[] testArgs = {null, "ADisk", null};
   110  * for (int i = 0; i &lt; 4; ++i) {
   110  * for (int i = 0; i < 4; ++i) {
   111  *     testArgs[0] = new Integer(i);
   111  *     testArgs[0] = new Integer(i);
   112  *     testArgs[2] = testArgs[0];
   112  *     testArgs[2] = testArgs[0];
   113  *     System.out.println(pattform.format(testArgs));
   113  *     System.out.println(pattform.format(testArgs));
   114  * }
   114  * }
   115  * </pre>
   115  * }</pre>
   116  * </blockquote>
   116  * </blockquote>
   117  * <p>
   117  * <p>
   118  * Specifying a pattern for ChoiceFormat objects is fairly straightforward.
   118  * Specifying a pattern for ChoiceFormat objects is fairly straightforward.
   119  * For example:
   119  * For example:
   120  * <blockquote>
   120  * <blockquote>
   121  * <pre>
   121  * <pre>{@code
   122  * ChoiceFormat fmt = new ChoiceFormat(
   122  * ChoiceFormat fmt = new ChoiceFormat(
   123  *      "-1#is negative| 0#is zero or fraction | 1#is one |1.0&lt;is 1+ |2#is two |2&lt;is more than 2.");
   123  *      "-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());
   124  * System.out.println("Formatter Pattern : " + fmt.toPattern());
   125  *
   125  *
   126  * System.out.println("Format with -INF : " + fmt.format(Double.NEGATIVE_INFINITY));
   126  * System.out.println("Format with -INF : " + fmt.format(Double.NEGATIVE_INFINITY));
   127  * System.out.println("Format with -1.0 : " + fmt.format(-1.0));
   127  * System.out.println("Format with -1.0 : " + fmt.format(-1.0));
   128  * System.out.println("Format with 0 : " + fmt.format(0));
   128  * System.out.println("Format with 0 : " + fmt.format(0));
   131  * System.out.println("Format with 1.5 : " + fmt.format(1.5));
   131  * System.out.println("Format with 1.5 : " + fmt.format(1.5));
   132  * System.out.println("Format with 2 : " + fmt.format(2));
   132  * System.out.println("Format with 2 : " + fmt.format(2));
   133  * System.out.println("Format with 2.1 : " + fmt.format(2.1));
   133  * System.out.println("Format with 2.1 : " + fmt.format(2.1));
   134  * System.out.println("Format with NaN : " + fmt.format(Double.NaN));
   134  * System.out.println("Format with NaN : " + fmt.format(Double.NaN));
   135  * System.out.println("Format with +INF : " + fmt.format(Double.POSITIVE_INFINITY));
   135  * System.out.println("Format with +INF : " + fmt.format(Double.POSITIVE_INFINITY));
   136  * </pre>
   136  * }</pre>
   137  * </blockquote>
   137  * </blockquote>
   138  * And the output result would be like the following:
   138  * And the output result would be like the following:
   139  * <blockquote>
   139  * <blockquote>
   140  * <pre>
   140  * <pre>{@code
   141  *   Format with -INF : is negative
   141  * Format with -INF : is negative
   142  *   Format with -1.0 : is negative
   142  * Format with -1.0 : is negative
   143  *   Format with 0 : is zero or fraction
   143  * Format with 0 : is zero or fraction
   144  *   Format with 0.9 : is zero or fraction
   144  * Format with 0.9 : is zero or fraction
   145  *   Format with 1.0 : is one
   145  * Format with 1.0 : is one
   146  *   Format with 1.5 : is 1+
   146  * Format with 1.5 : is 1+
   147  *   Format with 2 : is two
   147  * Format with 2 : is two
   148  *   Format with 2.1 : is more than 2.
   148  * Format with 2.1 : is more than 2.
   149  *   Format with NaN : is negative
   149  * Format with NaN : is negative
   150  *   Format with +INF : is more than 2.
   150  * Format with +INF : is more than 2.
   151  * </pre>
   151  * }</pre>
   152  * </blockquote>
   152  * </blockquote>
   153  *
   153  *
   154  * <h4><a name="synchronization">Synchronization</a></h4>
   154  * <h3><a name="synchronization">Synchronization</a></h3>
   155  *
   155  *
   156  * <p>
   156  * <p>
   157  * Choice formats are not synchronized.
   157  * Choice formats are not synchronized.
   158  * It is recommended to create separate format instances for each thread.
   158  * It is recommended to create separate format instances for each thread.
   159  * If multiple threads access a format concurrently, it must be synchronized
   159  * If multiple threads access a format concurrently, it must be synchronized
   253         System.arraycopy(newChoiceFormats, 0, choiceFormats, 0, count);
   253         System.arraycopy(newChoiceFormats, 0, choiceFormats, 0, count);
   254     }
   254     }
   255 
   255 
   256     /**
   256     /**
   257      * Gets the pattern.
   257      * Gets the pattern.
       
   258      *
       
   259      * @return the pattern string
   258      */
   260      */
   259     public String toPattern() {
   261     public String toPattern() {
   260         StringBuffer result = new StringBuffer();
   262         StringBuffer result = new StringBuffer();
   261         for (int i = 0; i < choiceLimits.length; ++i) {
   263         for (int i = 0; i < choiceLimits.length; ++i) {
   262             if (i != 0) {
   264             if (i != 0) {
   303         return result.toString();
   305         return result.toString();
   304     }
   306     }
   305 
   307 
   306     /**
   308     /**
   307      * Constructs with limits and corresponding formats based on the pattern.
   309      * Constructs with limits and corresponding formats based on the pattern.
       
   310      *
       
   311      * @param newPattern the new pattern string
   308      * @see #applyPattern
   312      * @see #applyPattern
   309      */
   313      */
   310     public ChoiceFormat(String newPattern)  {
   314     public ChoiceFormat(String newPattern)  {
   311         applyPattern(newPattern);
   315         applyPattern(newPattern);
   312     }
   316     }
   313 
   317 
   314     /**
   318     /**
   315      * Constructs with the limits and the corresponding formats.
   319      * Constructs with the limits and the corresponding formats.
       
   320      *
       
   321      * @param limits limits in ascending order
       
   322      * @param formats corresponding format strings
   316      * @see #setChoices
   323      * @see #setChoices
   317      */
   324      */
   318     public ChoiceFormat(double[] limits, String[] formats) {
   325     public ChoiceFormat(double[] limits, String[] formats) {
   319         setChoices(limits, formats);
   326         setChoices(limits, formats);
   320     }
   327     }
   321 
   328 
   322     /**
   329     /**
   323      * Set the choices to be used in formatting.
   330      * Set the choices to be used in formatting.
   324      * @param limits contains the top value that you want
   331      * @param limits contains the top value that you want
   325      * parsed with that format,and should be in ascending sorted order. When
   332      * parsed with that format, and should be in ascending sorted order. When
   326      * formatting X, the choice will be the i, where
   333      * formatting X, the choice will be the i, where
   327      * limit[i] &lt;= X &lt; limit[i+1].
   334      * limit[i] &le; X {@literal <} limit[i+1].
   328      * If the limit array is not in ascending order, the results of formatting
   335      * If the limit array is not in ascending order, the results of formatting
   329      * will be incorrect.
   336      * will be incorrect.
   330      * @param formats are the formats you want to use for each limit.
   337      * @param formats are the formats you want to use for each limit.
   331      * They can be either Format objects or Strings.
   338      * They can be either Format objects or Strings.
   332      * When formatting with object Y,
   339      * When formatting with object Y,
   432         }
   439         }
   433         return new Double(bestNumber);
   440         return new Double(bestNumber);
   434     }
   441     }
   435 
   442 
   436     /**
   443     /**
   437      * Finds the least double greater than d.
   444      * Finds the least double greater than {@code d}.
   438      * If NaN, returns same value.
   445      * If {@code NaN}, returns same value.
   439      * <p>Used to make half-open intervals.
   446      * <p>Used to make half-open intervals.
       
   447      *
       
   448      * @param d the reference value
       
   449      * @return the least double value greather than {@code d}
   440      * @see #previousDouble
   450      * @see #previousDouble
   441      */
   451      */
   442     public static final double nextDouble (double d) {
   452     public static final double nextDouble (double d) {
   443         return nextDouble(d,true);
   453         return nextDouble(d,true);
   444     }
   454     }
   445 
   455 
   446     /**
   456     /**
   447      * Finds the greatest double less than d.
   457      * Finds the greatest double less than {@code d}.
   448      * If NaN, returns same value.
   458      * If {@code NaN}, returns same value.
       
   459      *
       
   460      * @param d the reference value
       
   461      * @return the greatest double value less than {@code d}
   449      * @see #nextDouble
   462      * @see #nextDouble
   450      */
   463      */
   451     public static final double previousDouble (double d) {
   464     public static final double previousDouble (double d) {
   452         return nextDouble(d,false);
   465         return nextDouble(d,false);
   453     }
   466     }
   551     static final long SIGN                = 0x8000000000000000L;
   564     static final long SIGN                = 0x8000000000000000L;
   552     static final long EXPONENT            = 0x7FF0000000000000L;
   565     static final long EXPONENT            = 0x7FF0000000000000L;
   553     static final long POSITIVEINFINITY    = 0x7FF0000000000000L;
   566     static final long POSITIVEINFINITY    = 0x7FF0000000000000L;
   554 
   567 
   555     /**
   568     /**
   556      * Finds the least double greater than d (if positive == true),
   569      * Finds the least double greater than {@code d} (if {@code positive} is
   557      * or the greatest double less than d (if positive == false).
   570      * {@code true}), or the greatest double less than {@code d} (if
   558      * If NaN, returns same value.
   571      * {@code positive} is {@code false}).
       
   572      * If {@code NaN}, returns same value.
   559      *
   573      *
   560      * Does not affect floating-point flags,
   574      * Does not affect floating-point flags,
   561      * provided these member functions do not:
   575      * provided these member functions do not:
   562      *          Double.longBitsToDouble(long)
   576      *          Double.longBitsToDouble(long)
   563      *          Double.doubleToLongBits(double)
   577      *          Double.doubleToLongBits(double)
   564      *          Double.isNaN(double)
   578      *          Double.isNaN(double)
       
   579      *
       
   580      * @param d        the reference value
       
   581      * @param positive {@code true} if the least double is desired;
       
   582      *                 {@code false} otherwise
       
   583      * @return the least or greater double value
   565      */
   584      */
   566     public static double nextDouble (double d, boolean positive) {
   585     public static double nextDouble (double d, boolean positive) {
   567 
   586 
   568         /* filter out NaN's */
   587         /* filter out NaN's */
   569         if (Double.isNaN(d)) {
   588         if (Double.isNaN(d)) {