messageformat.java
来自「《移动Agent技术》一书的所有章节源代码。」· Java 代码 · 共 850 行 · 第 1/3 页
JAVA
850 行
/*
* @(#)MessageFormat.java 1.15 97/01/29
*
* (C) Copyright Taligent, Inc. 1996,1997 - All Rights Reserved
* (C) Copyright IBM Corp. 1996,1997 - All Rights Reserved
*
* Portions copyright (c) 1996-1997 Sun Microsystems, Inc. All Rights Reserved.
*
* The original version of this source code and documentation is copyrighted
* and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
* materials are provided under terms of a License Agreement between Taligent
* and Sun. This technology is protected by multiple US and International
* patents. This notice and attribution to Taligent may not be removed.
* Taligent is a registered trademark of Taligent, Inc.
*
* Permission to use, copy, modify, and distribute this software
* and its documentation for NON-COMMERCIAL purposes and without
* fee is hereby granted provided that this copyright notice
* appears in all copies. Please refer to the file "copyright.html"
* for further important copyright and licensing information.
*
* SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
* THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
* ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
* DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
*
*/
package java.text;
import java.util.Date;
import java.util.Locale;
import java.text.DecimalFormat;
import java.text.Utility;
/**
* <code>MessageFormat</code> provides a means to produce concatenated
* messages in language-neutral way. Use this to construct messages
* displayed for end users.
*
* <p>
* <code>MessageFormat</code> takes a set of objects, formats them, then
* inserts the formatted strings into the pattern at the appropriate places.
*
* <p>
* <strong>Note:</strong>
* <code>MessageFormat</code> differs from the other <code>Format</code>
* classes in that you create a <code>MessageFormat</code> object with one
* of its constructors (not with a <code>getInstance</code> style factory
* method). The factory methods aren't necessary because <code>MessageFormat</code>
* doesn't require any complex setup for a given locale. In fact,
* <code>MessageFormat</code> doesn't implement any locale specific behavior
* at all. It just needs to be set up on a sentence by sentence basis.
*
* <p>
* Here are some examples of usage:
* <blockquote>
* <pre>
* Object[] arguments = {
* new Integer(7),
* new Date(System.currentTimeMillis()),
* "a disturbance in the Force"
* };
*
* String result = MessageFormat.format(
* "At {1,time} on {1,date}, there was {2} on planet {0,number,integer}.",
* arguments);
*
* <output>: At 12:30 PM on Jul 3, 2053, there was a disturbance
* in the Force on planet 7.
*
* </pre>
* </blockquote>
* Typically, the message format will come from resources, and the
* arguments will be dynamically set at runtime.
*
* <p>
* Example 2:
* <blockquote>
* <pre>
* Object[] testArgs = {new Long(3), "MyDisk"};
*
* MessageFormat form = new MessageFormat(
* "The disk \"{1}\" contains {0} file(s).");
*
* System.out.println(form.format(testArgs));
*
* // output, with different testArgs
* <output>: The disk "MyDisk" contains 0 file(s).
* <output>: The disk "MyDisk" contains 1 file(s).
* <output>: The disk "MyDisk" contains 1,273 file(s).
* </pre>
* </blockquote>
*
* <p>
* The pattern is of the form:
* <blockquote>
* <pre>
* messageFormatPattern := string ( "{" messageFormatElement "}" string )*
*
* messageFormatElement := argument { "," elementFormat }
*
* elementFormat := "time" { "," datetimeStyle }
* | "date" { "," datetimeStyle }
* | "number" { "," numberStyle }
* | "choice" { "," choiceStyle }
*
* datetimeStyle := "short"
* | "medium"
* | "long"
* | "full"
* | dateFormatPattern
*
* numberStyle := "currency"
* | "percent"
* | "integer"
* | numberFormatPattern
*
* choiceStyle := choiceFormatPattern
* </pre>
* </blockquote>
* If there is no <code>elementFormat</code>,
* then the argument must be a string, which is substituted. If there is
* no <code>dateTimeStyle</code> or <code>numberStyle</code>, then the
* default format is used (for example, <code>NumberFormat.getInstance</code>,
* <code>DateFormat.getTimeInstance</code>, or <code>DateFormat.getInstance</code>).
*
* <p>
* In strings, single quotes can be used to quote the "{"
* (curly brace) if necessary. A real single quote is represented by ''.
* Inside a <code>messageFormatElement</code>, quotes are <strong>not</strong>
* removed. For example, {1,number,$'#',##} will produce a number format
* with the pound-sign quoted, with a result such as: "$#31,45".
*
* <p>
* If a pattern is used, then unquoted braces in the pattern, if any, must match:
* that is, "ab {0} de" and "ab '}' de" are ok, but "ab {0'}' de" and "ab } de" are
* not.
*
* <p>
* The argument is a number from 0 to 9, which corresponds to the
* arguments presented in an array to be formatted.
*
* <p>
* It is ok to have unused arguments in the array.
* With missing arguments or arguments that are not of the right class for
* the specified format, a <code>ParseException</code> is thrown.
* First, <code>format</code> checks to see if a <code>Format</code> object has been
* specified for the argument with the <code>setFormats</code> method.
* If so, then <code>format</code> uses that <code>Format</code> object to format the
* argument. Otherwise, the argument is formatted based on the object's
* type. If the argument is a <code>Number</code>, then <code>format</code>
* uses <code>NumberFormat.getInstance</code> to format the argument; if the
* argument is a <code>Date</code>, then <code>format</code> uses
* <code>DateFormat.getDateTimeInstance</code> to format the argument.
* Otherwise, it uses the <code>toString</code> method.
*
* <p>
* For more sophisticated patterns, you can use a <code>ChoiceFormat</code> to get
* output such as:
* <blockquote>
* <pre>
* MessageFormat form = new MessageFormat("The disk \"{1}\" contains {0}.");
* double[] filelimits = {0,1,2};
* String[] filepart = {"no files","one file","{0,number} files"};
* ChoiceFormat fileform = new ChoiceFormat(filelimits, filepart);
* form.setFormat(1,fileform); // NOT zero, see below
*
* Object[] testArgs = {new Long(12373), "MyDisk"};
*
* System.out.println(form.format(testArgs));
*
* // output, with different testArgs
* output: The disk "MyDisk" contains no files.
* output: The disk "MyDisk" contains one file.
* output: The disk "MyDisk" contains 1,273 files.
* </pre>
* </blockquote>
* You can either do this programmatically, as in the above example,
* or by using a pattern (see
* <a href="java.text.ChoiceFormat.html"><code>ChoiceFormat</code></a>
* for more information) as in:
* <blockquote>
* <pre>
* form.applyPattern(
* "There {0,choice,0#are no files|1#is one file|1#are {0,number,integer} files}.");
* </pre>
* </blockquote>
* <p>
* <strong>Note:</strong> As we see above, the string produced
* by a <code>ChoiceFormat</code> in <code>MessageFormat</code> is treated specially;
* occurances of '{' are used to indicated subformats, and cause recursion.
* If you create both a <code>MessageFormat</code> and <code>ChoiceFormat</code>
* programmatically (instead of using the string patterns), then be careful not to
* produce a format that recurses on itself, which will cause an infinite loop.
* <p>
* <strong>Note:</strong> formats are numbered by order of
* variable in the string.
* This is <strong>not</strong> the same as the argument numbering!
* For example: with "abc{2}def{3}ghi{0}...",
* <ul>
* <li>format0 affects the first variable {2}
* <li>format1 affects the second variable {3}
* <li>format2 affects the second variable {0}
* <li>and so on.
* </ul>
* <p>
* You can use <code>setLocale</code> followed by <code>applyPattern</code>
* (and then possibly <code>setFormat</code>) to re-initialize a
* <code>MessageFormat</code> with a different locale.
*
* @see java.util.Locale
* @see Format
* @see NumberFormat
* @see DecimalFormat
* @see ChoiceFormat
* @version 1.15 29 Jan 1997
* @author Mark Davis
*/
public class MessageFormat extends Format {
/**
* Constructs with the specified pattern.
* @see MessageFormat#applyPattern
*/
public MessageFormat(String pattern) {
applyPattern(pattern);
}
/**
* Constructs with the specified pattern and formats for the
* arguments in that pattern.
* @see MessageFormat#setPattern
*/
public void setLocale(Locale theLocale) {
String existingPattern = toPattern(); /*ibm.3550*/
locale = theLocale;
applyPattern(existingPattern); /*ibm.3550*/
}
/**
* Gets the locale. This locale is used for fetching default number or date
* format information.
*/
public Locale getLocale() {
return locale;
}
/**
* Sets the pattern. See the class description.
*/
public void applyPattern(String newPattern) {
StringBuffer[] segments = new StringBuffer[4];
for (int i = 0; i < segments.length; ++i) {
segments[i] = new StringBuffer();
}
int part = 0;
int formatNumber = 0;
boolean inQuote = false;
int braceStack = 0;
maxOffset = -1;
for (int i = 0; i < newPattern.length(); ++i) {
char ch = newPattern.charAt(i);
if (part == 0) {
if (ch == '\'') {
if (i + 1 < newPattern.length()
&& newPattern.charAt(i+1) == '\'') {
segments[part].append(ch); // handle doubles
++i;
} else {
inQuote = !inQuote;
}
} else if (ch == '{' && !inQuote) {
part = 1;
} else {
segments[part].append(ch);
}
} else if (inQuote) { // just copy quotes in parts
segments[part].append(ch);
if (ch == '\'') {
inQuote = false;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?