home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Komputer 1998 July & August
/
Pcwk78a98.iso
/
Internet
/
Javadraw
/
DATA.Z
/
MessageFormat.java
< prev
next >
Wrap
Text File
|
1997-08-30
|
33KB
|
828 lines
/*
* @(#)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>
*
* @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) {
locale = theLocale;
}
/**
* 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;
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;
}
} else {
switch (ch) {
case ',':
if (part < 3)
part += 1;
else
segments[part].append(ch);
break;
case '{':
++braceStack;
segments[part].append(ch);
break;
case '}':
if (braceStack == 0) {
part = 0;
makeFormat(i, formatNumber, segments);
formatNumber++;
} else {
--braceStack;
segments[part].append(ch);
}
break;
case '\'':
inQuote = true;
// fall through, so we keep quotes in other parts
default:
segments[part].append(ch);
break;
}
}
}
pattern = segments[0].toString();
}
/**
* Gets the pattern. See the class description.
*/
public String toPattern() {
// later, make this more extensible
int lastOffset = 0;
StringBuffer result = new StringBuffer();
for (int i = 0; i <= maxOffset; ++i) {
copyAndFixQuotes(pattern, lastOffset, offsets[i],result);
lastOffset = offsets[i];
result.append('{');
result.append(argumentNumbers[i]);
if (formats[i] == null) {
// do nothing, string format
} else if (formats[i] instanceof DecimalFormat) {
if (formats[i].equals(NumberFormat.getInstance(locale))) {
result.append(",number");
} else if (formats[i].equals(
NumberFormat.getCurrencyInstance(locale))) {
result.append(",number,currency");
} else if (formats[i].equals(
NumberFormat.getPercentInstance(locale))) {
result.append(",number,percent");
} else if (formats[i].equals(getIntegerFormat(locale))) {
result.append(",number,integer");
} else {
result.append(",number," +
((DecimalFormat)formats[i]).toPattern());
}
} else if (formats[i] instanceof SimpleDateFormat) {
if (formats[i].equals(DateFormat.getDateInstance(
DateFormat.DEFAULT,locale))) {
result.append(",date");
} else if (formats[i].equals(DateFormat.getDateInstance(
DateFormat.SHORT,locale))) {
result.append(",date,short");
} else if (formats[i].equals(DateFormat.getDateInstance(
DateFormat.DEFAULT,locale))) {
result.append(",date,medium");
} else if (formats[i].equals(DateFormat.getDateInstance(
DateFormat.LONG,locale))) {
result.append(",date,long");
} else if (formats[i].equals(DateFormat.getDateInstance(
DateFormat.FULL,locale))) {
result.append(",date,full");
} else if (formats[i].equals(DateFormat.getTimeInstance(
DateFormat.DEFAULT,locale))) {
result.append(",time");
} else if (formats[i].equals(DateFormat.getTimeInstance(
DateFormat.SHORT,locale))) {
result.append(",time,short");
} else if (formats[i].equals(DateFormat.getTimeInstance(
DateFormat.DEFAULT,locale))) {
result.append(",time,medium");
} else if (formats[i].equals(DateFormat.getTimeInstance(
DateFormat.LONG,locale))) {
result.append(",time,long");
} else if (formats[i].equals(DateFormat.getTimeInstance(
DateFormat.FULL,locale))) {
result.append(",time,full");
} else {
result.append(",date,"
+ ((SimpleDateFormat)formats[i]).toPattern());
}
} else if (formats[i] instanceof ChoiceFormat) {
result.append(",choice,"
+ ((ChoiceFormat)formats[i]).toPattern());
} else {
//result.append(", unknown");
}
result.append('}');
}
copyAndFixQuotes(pattern, lastOffset, pattern.length(), result);
return result.toString();
}
/**
* Sets formats to use on parameters.
* See the class description about format numbering.
*/
public void setFormats(Format[] newFormats) {
try {
formats = (Format[]) newFormats.clone();
} catch (Exception e) {
return; // should never occur!
}
}
/**
* Sets formats individually to use on parameters.
* See the class description about format numbering.
*/
public void setFormat(int variable, Format newFormat) {
formats[variable] = newFormat;
}
/**
* Gets formats that were set with setFormats.
* See the class description about format numbering.
*/
public Format[] getFormats() {
try {
return (Format[]) formats.clone();
} catch (Exception e) {
return formats; // should never occur!
}
}
/**
* Returns pattern with formatted objects.
* @param source an array of objects to be formatted & substituted.
* @param result where text is appended.
* @param ignore no useful status is returned.
*/
public final StringBuffer format(Object[] source, StringBuffer result,
FieldPosition ignore)
{
return format(source,result,ignore, 0);
}
/**
* Convenience routine.
* Avoids explicit creation of MessageFormat,
* but doesn't allow future optimizations.
*/
public static String format(String pattern, Object[] arguments) {
MessageFormat temp = new MessageFormat(pattern);
return temp.format(arguments);
}
// Overrides
public final StringBuffer format(Object source, StringBuffer result,
FieldPosition ignore)
{
return format((Object[])source,result,ignore, 0);
}
/**
* Parses the string.
*
* <p>Caveats: The parse may fail in a number of circumstances.
* For example:
* <ul>
* <li>If one of the arguments does not occur in the pattern.
* <li>If the format of an argument is loses information, such as
* with a choice format where a large number formats to "many".
* <li>Does not yet handle recursion (where
* the substituted strings contain {n} references.)
* <li>Will not always find a match (or the correct match)
* if some part of the parse is ambiguous.
* For example, if the pattern "{1},{2}" is used with the
* string arguments {"a,b", "c"}, it will format as "a,b,c".
* When the result is parsed, it will return {"a", "b,c"}.
* <li>If a single argument is formatted twice in the string,
* then the later parse wins.
* </ul>
*/
public Object[] parse(String source, ParsePosition status) {
Object[] resultArray = new Object[10];
int patternOffset = 0;
int sourceOffset = status.index;
ParsePosition tempStatus = new ParsePosition(0);
for (int i = 0; i <= maxOffset; ++i) {
// match up to format
int len = offsets[i] - patternOffset;
if (len == 0 || pattern.regionMatches(patternOffset,
source, sourceOffset, len)) {
sourceOffset += len;
patternOffset += len;
} else {
return null; // leave index as is to signal error
}
// now use format
if (formats[i] == null) { // string format
// if at end, use longest possible match
// otherwise uses first match to intervening string
// does NOT recursively try all possibilities
int tempLength = (i != maxOffset) ? offsets[i+1] : pattern.length();
int next = source.indexOf(
pattern.substring(patternOffset,tempLength),
sourceOffset);
if (next < 0) {
return null; // leave index as is to signal error
} else {
resultArray[argumentNumbers[i]]
= source.substring(sourceOffset,next);
sourceOffset = next;
}
} else {
tempStatus.index = sourceOffset;
resultArray[argumentNumbers[i]]
= formats[i].parseObject(source,tempStatus);
if (tempStatus.index == sourceOffset) {
return null; // leave index as is to signal error
}
sourceOffset = tempStatus.index; // update
}
}
int len = pattern.length() - patternOffset;
if (len == 0 || pattern.regionMatches(patternOffset,
source, sourceOffset, len)) {
status.index = sourceOffset + len;
} else {
return null; // leave index as is to signal error
}
return resultArray;
}
/**
* Parses the string. Does not yet handle recursion (where
* the substituted strings contain {n} references.)
* @exception ParseException if the string can't be parsed.
*/
public Object[] parse(String source) throws ParseException {
ParsePosition status = new ParsePosition(0);
Object[] result = parse(source, status);
if (status.index == 0) // unchanged, returned object is null
throw new ParseException("MessageFormat parse error!", 0);
return result;
}
/**
* Parses the string. Does not yet handle recursion (where
* the substituted strings contain %n references.)
*/
public Object parseObject (String text, ParsePosition status) {
return parse(text, status);
}
/**
* Overrides Cloneable
*/
public Object clone()
{
MessageFormat other = (MessageFormat) super.clone();
// clone arrays. Can't do with utility because of bug in Cloneable
other.formats = (Format[]) formats.clone(); // shallow clone
for (int i = 0; i < formats.length; ++i) {
if (formats[i] != null)
other.formats[i] = (Format)formats[i].clone();
}
// for primitives or immutables, shallow clone is enough
other.offsets = (int[]) offsets.clone();
other.argumentNumbers = (int[]) argumentNumbers.clone();
return other;
}
/**
* Equality comparision between two message format objects
*/
public boolean equals(Object obj) {
if (this == obj) // quick check
return true;
if (getClass() != obj.getClass())
return false;
MessageFormat other = (MessageFormat) obj;
return (maxOffset == other.maxOffset
&& pattern.equals(other.pattern)
&& Utility.objectEquals(locale, other.locale) // does null check
&& Utility.arrayEquals(offsets,other.offsets)
&& Utility.arrayEquals(argumentNumbers,other.argumentNumbers)
&& Utility.arrayEquals(formats,other.formats));
}
/**
* Generates a hash code for the message format object.
*/
public int hashCode() {
return pattern.hashCode(); // enough for reasonable distribution
}
// ===========================privates============================
// Mark : Is this the right fix? (HS)
private Locale locale = Locale.getDefault();
private String pattern = "";
// later, allow more than ten items
private Format[] formats = new Format[10];
private int[] offsets = new int[10];
private int[] argumentNumbers = new int[10];
private int maxOffset = -1;
/**
* Internal routine used by format.
* @param recursionProtection Initially zero. Bits 0..9 are used to indicate
* that a parameter has already been seen, to avoid recursion. Currently
* unused.
*/
private StringBuffer format(Object[] arguments, StringBuffer result,
FieldPosition status, int recursionProtection) {
// note: this implementation assumes a fast substring & index.
// if this is not true, would be better to append chars one by one.
int lastOffset = 0;
for (int i = 0; i <= maxOffset; ++i) {
result.append(pattern.substring(lastOffset, offsets[i]));
lastOffset = offsets[i];
int argumentNumber = argumentNumbers[i];
if (argumentNumber >= arguments.length)
throw new IllegalArgumentException("Argument # > Arg length");
// int argRecursion = ((recursionProtection >> (argumentNumber*2)) & 0x3);
if (false) { // if (argRecursion == 3){
// prevent loop!!!
result.append('\uFFFD');
} else {
Object obj = arguments[argumentNumber];
String arg;
boolean tryRecursion = false;
if (formats[i] != null) {
arg = formats[i].format(obj);
tryRecursion = formats[i] instanceof ChoiceFormat;
} else if (obj instanceof Number) {
// format number if can
arg = NumberFormat.getInstance(locale).format(obj); // fix
} else if (obj instanceof Date) {
// format a Date if can
arg = DateFormat.getDateTimeInstance(DateFormat.SHORT,
DateFormat.SHORT,
locale).format(obj);//fix
} else if (obj instanceof String) {
arg = (String) obj;
} else {
System.out.println("Unknown object of type:" +
obj.getClass().getName());
throw new IllegalArgumentException("Unknown argument");
}
// recurse if necessary
if (tryRecursion && arg.indexOf('{') >= 0) {
MessageFormat temp = new MessageFormat(arg);
temp.format(arguments,result,status,recursionProtection);
} else {
result.append(arg);
}
}
}
result.append(pattern.substring(lastOffset, pattern.length()));
return result;
}
private static final String[] typeList =
{"", "", "number", "", "date", "", "time", "", "choice"};
private static final String[] modifierList =
{"", "", "currency", "", "percent", "", "integer"};
private static final String[] dateModifierList =
{"", "", "short", "", "medium", "", "long", "", "full"};
private void makeFormat(int position, int offsetNumber,
StringBuffer[] segments)
{
// get the number
int argumentNumber;
try {
argumentNumber = Integer.parseInt(segments[1].toString()); // always unlocalized!
if (argumentNumber < 0 || argumentNumber > 9) {
throw new NumberFormatException();
}
maxOffset = offsetNumber;
offsets[offsetNumber] = segments[0].length();
argumentNumbers[offsetNumber] = argumentNumber;
} catch (Exception e) {
throw new IllegalArgumentException("argument number too large at ");
}
// now get the format
Format newFormat = null;
switch (findKeyword(segments[2].toString(), typeList)) {
case 0:
// string format
/*if (!segments[3].equals(""))
throw new IllegalArgumentException("can't modify string format, at ");
//*/
break;
case 1: case 2:// number
switch (findKeyword(segments[3].toString(), modifierList)) {
case 0: // default;
newFormat = NumberFormat.getInstance(locale);
break;
case 1: case 2:// currency
newFormat = NumberFormat.getCurrencyInstance(locale);
break;
case 3: case 4:// percent
newFormat = NumberFormat.getPercentInstance(locale);
break;
case 5: case 6:// integer
newFormat = getIntegerFormat(locale);
break;
default: // pattern
newFormat = NumberFormat.getInstance(locale);
try {
((DecimalFormat)newFormat).applyPattern(segments[3].toString());
} catch (Exception e) {
throw new IllegalArgumentException(
"Pattern incorrect or locale does not support formats, error at ");
}
break;
}
break;
case 3: case 4: // date
switch (findKeyword(segments[3].toString(), dateModifierList)) {
case 0: // default
newFormat = DateFormat.getDateInstance(DateFormat.DEFAULT, locale);
break;
case 1: case 2: // short
newFormat = DateFormat.getDateInstance(DateFormat.SHORT, locale);
break;
case 3: case 4: // medium
newFormat = DateFormat.getDateInstance(DateFormat.DEFAULT, locale);
break;
case 5: case 6: // long
newFormat = DateFormat.getDateInstance(DateFormat.LONG, locale);
break;
case 7: case 8: // full
newFormat = DateFormat.getDateInstance(DateFormat.FULL, locale);
break;
default:
newFormat = DateFormat.getDateInstance(DateFormat.DEFAULT, locale);
try {
((SimpleDateFormat)newFormat).applyPattern(segments[3].toString());
} catch (Exception e) {
throw new IllegalArgumentException(
"Pattern incorrect or locale does not support formats, error at ");
}
break;
}
break;
case 5: case 6:// time
switch (findKeyword(segments[3].toString(), dateModifierList)) {
case 0: // default
newFormat = DateFormat.getTimeInstance(DateFormat.DEFAULT, locale);
break;
case 1: case 2: // short
newFormat = DateFormat.getTimeInstance(DateFormat.SHORT, locale);
break;
case 3: case 4: // medium
newFormat = DateFormat.getTimeInstance(DateFormat.DEFAULT, locale);
break;
case 5: case 6: // long
newFormat = DateFormat.getTimeInstance(DateFormat.LONG, locale);
break;
case 7: case 8: // full
newFormat = DateFormat.getTimeInstance(DateFormat.FULL, locale);
break;
default:
newFormat = DateFormat.getTimeInstance(DateFormat.DEFAULT, locale);
try {
((SimpleDateFormat)newFormat).applyPattern(segments[3].toString());
} catch (Exception e) {
throw new IllegalArgumentException(
"Pattern incorrect or locale does not support formats, error at ");
}
break;
}
break;
case 7: case 8:// choice
try {
newFormat = new ChoiceFormat(segments[3].toString());
} catch (Exception e) {
throw new IllegalArgumentException(
"Choice Pattern incorrect, error at ");
}
break;
default:
throw new IllegalArgumentException("unknown format type at ");
}
formats[offsetNumber] = newFormat;
segments[1].setLength(0); // throw away other segments
segments[2].setLength(0);
segments[3].setLength(0);
}
private static final int findKeyword(String s, String[] list) {
s = s.trim().toLowerCase();
for (int i = 0; i < list.length; ++i) {
if (s.equals(list[i]))
return i;
}
return -1;
}
/**
* Convenience method that ought to be in NumberFormat
*/
NumberFormat getIntegerFormat(Locale locale) {
NumberFormat temp = NumberFormat.getInstance(locale);
if (temp instanceof DecimalFormat) {
DecimalFormat temp2 = (DecimalFormat) temp;
temp2.setMaximumFractionDigits(0);
temp2.setDecimalSeparatorAlwaysShown(false);
temp2.setParseIntegerOnly(true);
}
return temp;
}
private static final void copyAndFixQuotes(
String source, int start, int end, StringBuffer target) {
for (int i = start; i < end; ++i) {
char ch = source.charAt(i);
if (ch == '{') {
target.append("'{'");
} else if (ch == '\'') {
target.append("''");
} else {
target.append(ch);
}
}
}
}