< prev index next >

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

Print this page


   1 /*
   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.
   4  *
   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
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


 339  * @see          SimpleDateFormat
 340  *
 341  * @author       Mark Davis
 342  */
 343 
 344 public class MessageFormat extends Format {
 345 
 346     private static final long serialVersionUID = 6479157306784022952L;
 347 
 348     /**
 349      * Constructs a MessageFormat for the default
 350      * {@link java.util.Locale.Category#FORMAT FORMAT} locale and the
 351      * specified pattern.
 352      * The constructor first sets the locale, then parses the pattern and
 353      * creates a list of subformats for the format elements contained in it.
 354      * Patterns and their interpretation are specified in the
 355      * <a href="#patterns">class description</a>.
 356      *
 357      * @param pattern the pattern for this message format
 358      * @exception IllegalArgumentException if the pattern is invalid


 359      */
 360     public MessageFormat(String pattern) {
 361         this.locale = Locale.getDefault(Locale.Category.FORMAT);
 362         applyPattern(pattern);
 363     }
 364 
 365     /**
 366      * Constructs a MessageFormat for the specified locale and
 367      * pattern.
 368      * The constructor first sets the locale, then parses the pattern and
 369      * creates a list of subformats for the format elements contained in it.
 370      * Patterns and their interpretation are specified in the
 371      * <a href="#patterns">class description</a>.
 372      *
 373      * @param pattern the pattern for this message format
 374      * @param locale the locale for this message format
 375      * @exception IllegalArgumentException if the pattern is invalid


 376      * @since 1.4
 377      */
 378     public MessageFormat(String pattern, Locale locale) {
 379         this.locale = locale;
 380         applyPattern(pattern);
 381     }
 382 
 383     /**
 384      * Sets the locale to be used when creating or comparing subformats.
 385      * This affects subsequent calls
 386      * <ul>
 387      * <li>to the {@link #applyPattern applyPattern}
 388      *     and {@link #toPattern toPattern} methods if format elements specify
 389      *     a format type and therefore have the subformats created in the
 390      *     <code>applyPattern</code> method, as well as
 391      * <li>to the <code>format</code> and
 392      *     {@link #formatToCharacterIterator formatToCharacterIterator} methods
 393      *     if format elements do not specify a format type and therefore have
 394      *     the subformats created in the formatting methods.
 395      * </ul>


 403 
 404     /**
 405      * Gets the locale that's used when creating or comparing subformats.
 406      *
 407      * @return the locale used when creating or comparing subformats
 408      */
 409     public Locale getLocale() {
 410         return locale;
 411     }
 412 
 413 
 414     /**
 415      * Sets the pattern used by this message format.
 416      * The method parses the pattern and creates a list of subformats
 417      * for the format elements contained in it.
 418      * Patterns and their interpretation are specified in the
 419      * <a href="#patterns">class description</a>.
 420      *
 421      * @param pattern the pattern for this message format
 422      * @exception IllegalArgumentException if the pattern is invalid


 423      */
 424     @SuppressWarnings("fallthrough") // fallthrough in switch is expected, suppress it
 425     public void applyPattern(String pattern) {
 426             StringBuilder[] segments = new StringBuilder[4];
 427             // Allocate only segments[SEG_RAW] here. The rest are
 428             // allocated on demand.
 429             segments[SEG_RAW] = new StringBuilder();
 430 
 431             int part = SEG_RAW;
 432             int formatNumber = 0;
 433             boolean inQuote = false;
 434             int braceStack = 0;
 435             maxOffset = -1;
 436             for (int i = 0; i < pattern.length(); ++i) {
 437                 char ch = pattern.charAt(i);
 438                 if (part == SEG_RAW) {
 439                     if (ch == '\'') {
 440                         if (i + 1 < pattern.length()
 441                             && pattern.charAt(i+1) == '\'') {
 442                             segments[part].append(ch);  // handle doubles


 797      *       <td><code>argument</code>
 798      *    <tr>
 799      *       <td><code>null</code>
 800      *       <td><i>any</i>
 801      *       <td><code>argument.toString()</code>
 802      * </table>
 803      * <p>
 804      * If <code>pos</code> is non-null, and refers to
 805      * <code>Field.ARGUMENT</code>, the location of the first formatted
 806      * string will be returned.
 807      *
 808      * @param arguments an array of objects to be formatted and substituted.
 809      * @param result where text is appended.
 810      * @param pos On input: an alignment field, if desired.
 811      *            On output: the offsets of the alignment field.
 812      * @return the string buffer passed in as {@code result}, with formatted
 813      * text appended
 814      * @exception IllegalArgumentException if an argument in the
 815      *            <code>arguments</code> array is not of the type
 816      *            expected by the format element(s) that use it.

 817      */
 818     public final StringBuffer format(Object[] arguments, StringBuffer result,
 819                                      FieldPosition pos)
 820     {
 821         return subformat(arguments, result, pos, null);
 822     }
 823 
 824     /**
 825      * Creates a MessageFormat with the given pattern and uses it
 826      * to format the given arguments. This is equivalent to
 827      * <blockquote>
 828      *     <code>(new {@link #MessageFormat(String) MessageFormat}(pattern)).{@link #format(java.lang.Object[], java.lang.StringBuffer, java.text.FieldPosition) format}(arguments, new StringBuffer(), null).toString()</code>
 829      * </blockquote>
 830      *
 831      * @param pattern   the pattern string
 832      * @param arguments object(s) to format
 833      * @return the formatted string
 834      * @exception IllegalArgumentException if the pattern is invalid,
 835      *            or if an argument in the <code>arguments</code> array
 836      *            is not of the type expected by the format element(s)
 837      *            that use it.

 838      */
 839     public static String format(String pattern, Object ... arguments) {
 840         MessageFormat temp = new MessageFormat(pattern);
 841         return temp.format(arguments);
 842     }
 843 
 844     // Overrides
 845     /**
 846      * Formats an array of objects and appends the <code>MessageFormat</code>'s
 847      * pattern, with format elements replaced by the formatted objects, to the
 848      * provided <code>StringBuffer</code>.
 849      * This is equivalent to
 850      * <blockquote>
 851      *     <code>{@link #format(java.lang.Object[], java.lang.StringBuffer, java.text.FieldPosition) format}((Object[]) arguments, result, pos)</code>
 852      * </blockquote>
 853      *
 854      * @param arguments an array of objects to be formatted and substituted.
 855      * @param result where text is appended.
 856      * @param pos On input: an alignment field, if desired.
 857      *            On output: the offsets of the alignment field.
 858      * @exception IllegalArgumentException if an argument in the
 859      *            <code>arguments</code> array is not of the type
 860      *            expected by the format element(s) that use it.

 861      */
 862     public final StringBuffer format(Object arguments, StringBuffer result,
 863                                      FieldPosition pos)
 864     {
 865         return subformat((Object[]) arguments, result, pos, null);
 866     }
 867 
 868     /**
 869      * Formats an array of objects and inserts them into the
 870      * <code>MessageFormat</code>'s pattern, producing an
 871      * <code>AttributedCharacterIterator</code>.
 872      * You can use the returned <code>AttributedCharacterIterator</code>
 873      * to build the resulting String, as well as to determine information
 874      * about the resulting String.
 875      * <p>
 876      * The text of the returned <code>AttributedCharacterIterator</code> is
 877      * the same that would be returned by
 878      * <blockquote>
 879      *     <code>{@link #format(java.lang.Object[], java.lang.StringBuffer, java.text.FieldPosition) format}(arguments, new StringBuffer(), null).toString()</code>
 880      * </blockquote>


 930      *     the substituted strings contain {n} references.)
 931      * <li>Will not always find a match (or the correct match)
 932      *     if some part of the parse is ambiguous.
 933      *     For example, if the pattern "{1},{2}" is used with the
 934      *     string arguments {"a,b", "c"}, it will format as "a,b,c".
 935      *     When the result is parsed, it will return {"a", "b,c"}.
 936      * <li>If a single argument is parsed more than once in the string,
 937      *     then the later parse wins.
 938      * </ul>
 939      * When the parse fails, use ParsePosition.getErrorIndex() to find out
 940      * where in the string the parsing failed.  The returned error
 941      * index is the starting offset of the sub-patterns that the string
 942      * is comparing with.  For example, if the parsing string "AAA {0} BBB"
 943      * is comparing against the pattern "AAD {0} BBB", the error index is
 944      * 0. When an error occurs, the call to this method will return null.
 945      * If the source is null, return an empty array.
 946      *
 947      * @param source the string to parse
 948      * @param pos    the parse position
 949      * @return an array of parsed objects


 950      */
 951     public Object[] parse(String source, ParsePosition pos) {
 952         if (source == null) {
 953             Object[] empty = {};
 954             return empty;
 955         }
 956 
 957         int maximumArgumentNumber = -1;
 958         for (int i = 0; i <= maxOffset; i++) {
 959             if (argumentNumbers[i] > maximumArgumentNumber) {
 960                 maximumArgumentNumber = argumentNumbers[i];
 961             }
 962         }
 963         Object[] resultArray = new Object[maximumArgumentNumber + 1];
 964 
 965         int patternOffset = 0;
 966         int sourceOffset = pos.index;
 967         ParsePosition tempStatus = new ParsePosition(0);
 968         for (int i = 0; i <= maxOffset; ++i) {
 969             // match up to format


   1 /*
   2  * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   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
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


 339  * @see          SimpleDateFormat
 340  *
 341  * @author       Mark Davis
 342  */
 343 
 344 public class MessageFormat extends Format {
 345 
 346     private static final long serialVersionUID = 6479157306784022952L;
 347 
 348     /**
 349      * Constructs a MessageFormat for the default
 350      * {@link java.util.Locale.Category#FORMAT FORMAT} locale and the
 351      * specified pattern.
 352      * The constructor first sets the locale, then parses the pattern and
 353      * creates a list of subformats for the format elements contained in it.
 354      * Patterns and their interpretation are specified in the
 355      * <a href="#patterns">class description</a>.
 356      *
 357      * @param pattern the pattern for this message format
 358      * @exception IllegalArgumentException if the pattern is invalid
 359      * @exception NullPointerException if {@code pattern} is
 360      *            {@code null}
 361      */
 362     public MessageFormat(String pattern) {
 363         this.locale = Locale.getDefault(Locale.Category.FORMAT);
 364         applyPattern(pattern);
 365     }
 366 
 367     /**
 368      * Constructs a MessageFormat for the specified locale and
 369      * pattern.
 370      * The constructor first sets the locale, then parses the pattern and
 371      * creates a list of subformats for the format elements contained in it.
 372      * Patterns and their interpretation are specified in the
 373      * <a href="#patterns">class description</a>.
 374      *
 375      * @param pattern the pattern for this message format
 376      * @param locale the locale for this message format
 377      * @exception IllegalArgumentException if the pattern is invalid
 378      * @exception NullPointerException if {@code pattern} is
 379      *            {@code null}
 380      * @since 1.4
 381      */
 382     public MessageFormat(String pattern, Locale locale) {
 383         this.locale = locale;
 384         applyPattern(pattern);
 385     }
 386 
 387     /**
 388      * Sets the locale to be used when creating or comparing subformats.
 389      * This affects subsequent calls
 390      * <ul>
 391      * <li>to the {@link #applyPattern applyPattern}
 392      *     and {@link #toPattern toPattern} methods if format elements specify
 393      *     a format type and therefore have the subformats created in the
 394      *     <code>applyPattern</code> method, as well as
 395      * <li>to the <code>format</code> and
 396      *     {@link #formatToCharacterIterator formatToCharacterIterator} methods
 397      *     if format elements do not specify a format type and therefore have
 398      *     the subformats created in the formatting methods.
 399      * </ul>


 407 
 408     /**
 409      * Gets the locale that's used when creating or comparing subformats.
 410      *
 411      * @return the locale used when creating or comparing subformats
 412      */
 413     public Locale getLocale() {
 414         return locale;
 415     }
 416 
 417 
 418     /**
 419      * Sets the pattern used by this message format.
 420      * The method parses the pattern and creates a list of subformats
 421      * for the format elements contained in it.
 422      * Patterns and their interpretation are specified in the
 423      * <a href="#patterns">class description</a>.
 424      *
 425      * @param pattern the pattern for this message format
 426      * @exception IllegalArgumentException if the pattern is invalid
 427      * @exception NullPointerException if {@code pattern} is
 428      *            {@code null}
 429      */
 430     @SuppressWarnings("fallthrough") // fallthrough in switch is expected, suppress it
 431     public void applyPattern(String pattern) {
 432             StringBuilder[] segments = new StringBuilder[4];
 433             // Allocate only segments[SEG_RAW] here. The rest are
 434             // allocated on demand.
 435             segments[SEG_RAW] = new StringBuilder();
 436 
 437             int part = SEG_RAW;
 438             int formatNumber = 0;
 439             boolean inQuote = false;
 440             int braceStack = 0;
 441             maxOffset = -1;
 442             for (int i = 0; i < pattern.length(); ++i) {
 443                 char ch = pattern.charAt(i);
 444                 if (part == SEG_RAW) {
 445                     if (ch == '\'') {
 446                         if (i + 1 < pattern.length()
 447                             && pattern.charAt(i+1) == '\'') {
 448                             segments[part].append(ch);  // handle doubles


 803      *       <td><code>argument</code>
 804      *    <tr>
 805      *       <td><code>null</code>
 806      *       <td><i>any</i>
 807      *       <td><code>argument.toString()</code>
 808      * </table>
 809      * <p>
 810      * If <code>pos</code> is non-null, and refers to
 811      * <code>Field.ARGUMENT</code>, the location of the first formatted
 812      * string will be returned.
 813      *
 814      * @param arguments an array of objects to be formatted and substituted.
 815      * @param result where text is appended.
 816      * @param pos On input: an alignment field, if desired.
 817      *            On output: the offsets of the alignment field.
 818      * @return the string buffer passed in as {@code result}, with formatted
 819      * text appended
 820      * @exception IllegalArgumentException if an argument in the
 821      *            <code>arguments</code> array is not of the type
 822      *            expected by the format element(s) that use it.
 823      * @exception NullPointerException if {@code result} is {@code null}
 824      */
 825     public final StringBuffer format(Object[] arguments, StringBuffer result,
 826                                      FieldPosition pos)
 827     {
 828         return subformat(arguments, result, pos, null);
 829     }
 830 
 831     /**
 832      * Creates a MessageFormat with the given pattern and uses it
 833      * to format the given arguments. This is equivalent to
 834      * <blockquote>
 835      *     <code>(new {@link #MessageFormat(String) MessageFormat}(pattern)).{@link #format(java.lang.Object[], java.lang.StringBuffer, java.text.FieldPosition) format}(arguments, new StringBuffer(), null).toString()</code>
 836      * </blockquote>
 837      *
 838      * @param pattern   the pattern string
 839      * @param arguments object(s) to format
 840      * @return the formatted string
 841      * @exception IllegalArgumentException if the pattern is invalid,
 842      *            or if an argument in the <code>arguments</code> array
 843      *            is not of the type expected by the format element(s)
 844      *            that use it.
 845      * @exception NullPointerException if {@code pattern} is {@code null}
 846      */
 847     public static String format(String pattern, Object ... arguments) {
 848         MessageFormat temp = new MessageFormat(pattern);
 849         return temp.format(arguments);
 850     }
 851 
 852     // Overrides
 853     /**
 854      * Formats an array of objects and appends the <code>MessageFormat</code>'s
 855      * pattern, with format elements replaced by the formatted objects, to the
 856      * provided <code>StringBuffer</code>.
 857      * This is equivalent to
 858      * <blockquote>
 859      *     <code>{@link #format(java.lang.Object[], java.lang.StringBuffer, java.text.FieldPosition) format}((Object[]) arguments, result, pos)</code>
 860      * </blockquote>
 861      *
 862      * @param arguments an array of objects to be formatted and substituted.
 863      * @param result where text is appended.
 864      * @param pos On input: an alignment field, if desired.
 865      *            On output: the offsets of the alignment field.
 866      * @exception IllegalArgumentException if an argument in the
 867      *            <code>arguments</code> array is not of the type
 868      *            expected by the format element(s) that use it.
 869      * @exception NullPointerException if {@code result} is {@code null}
 870      */
 871     public final StringBuffer format(Object arguments, StringBuffer result,
 872                                      FieldPosition pos)
 873     {
 874         return subformat((Object[]) arguments, result, pos, null);
 875     }
 876 
 877     /**
 878      * Formats an array of objects and inserts them into the
 879      * <code>MessageFormat</code>'s pattern, producing an
 880      * <code>AttributedCharacterIterator</code>.
 881      * You can use the returned <code>AttributedCharacterIterator</code>
 882      * to build the resulting String, as well as to determine information
 883      * about the resulting String.
 884      * <p>
 885      * The text of the returned <code>AttributedCharacterIterator</code> is
 886      * the same that would be returned by
 887      * <blockquote>
 888      *     <code>{@link #format(java.lang.Object[], java.lang.StringBuffer, java.text.FieldPosition) format}(arguments, new StringBuffer(), null).toString()</code>
 889      * </blockquote>


 939      *     the substituted strings contain {n} references.)
 940      * <li>Will not always find a match (or the correct match)
 941      *     if some part of the parse is ambiguous.
 942      *     For example, if the pattern "{1},{2}" is used with the
 943      *     string arguments {"a,b", "c"}, it will format as "a,b,c".
 944      *     When the result is parsed, it will return {"a", "b,c"}.
 945      * <li>If a single argument is parsed more than once in the string,
 946      *     then the later parse wins.
 947      * </ul>
 948      * When the parse fails, use ParsePosition.getErrorIndex() to find out
 949      * where in the string the parsing failed.  The returned error
 950      * index is the starting offset of the sub-patterns that the string
 951      * is comparing with.  For example, if the parsing string "AAA {0} BBB"
 952      * is comparing against the pattern "AAD {0} BBB", the error index is
 953      * 0. When an error occurs, the call to this method will return null.
 954      * If the source is null, return an empty array.
 955      *
 956      * @param source the string to parse
 957      * @param pos    the parse position
 958      * @return an array of parsed objects
 959      * @exception NullPointerException if {@code pos} is {@code null}
 960      *            for a non-null {@code source} string.
 961      */
 962     public Object[] parse(String source, ParsePosition pos) {
 963         if (source == null) {
 964             Object[] empty = {};
 965             return empty;
 966         }
 967 
 968         int maximumArgumentNumber = -1;
 969         for (int i = 0; i <= maxOffset; i++) {
 970             if (argumentNumbers[i] > maximumArgumentNumber) {
 971                 maximumArgumentNumber = argumentNumbers[i];
 972             }
 973         }
 974         Object[] resultArray = new Object[maximumArgumentNumber + 1];
 975 
 976         int patternOffset = 0;
 977         int sourceOffset = pos.index;
 978         ParsePosition tempStatus = new ParsePosition(0);
 979         for (int i = 0; i <= maxOffset; ++i) {
 980             // match up to format


< prev index next >