messageformat.java
来自「《移动Agent技术》一书的所有章节源代码。」· Java 代码 · 共 850 行 · 第 1/3 页
JAVA
850 行
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;
/**
* Constructs with the specified pattern.
* @see MessageFormat#applyPattern
*/
private MessageFormat(String pattern, Locale loc) {
locale = (Locale)loc.clone();
applyPattern(pattern);
}
/**
* 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 {
arg = obj.toString();
if (arg == null) arg = "null";
}
// recurse if necessary
if (tryRecursion && arg.indexOf('{') >= 0) {
MessageFormat temp = new MessageFormat(arg, locale);
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);
}
}
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?