mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Add implementation of java.text.MessageFormat
This commit is contained in:
parent
6145afcbf8
commit
90cc2c4677
|
@ -0,0 +1,241 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2017 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.teavm.classlib.java.text;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import org.teavm.classlib.java.util.TLocale;
|
||||||
|
|
||||||
|
public class TChoiceFormat extends TNumberFormat {
|
||||||
|
private double[] choiceLimits;
|
||||||
|
private String[] choiceFormats;
|
||||||
|
|
||||||
|
public TChoiceFormat(double[] limits, String[] formats) {
|
||||||
|
setChoices(limits, formats);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TChoiceFormat(String template) {
|
||||||
|
applyPattern(template);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void applyPattern(String template) {
|
||||||
|
double[] limits = new double[5];
|
||||||
|
List<String> formats = new ArrayList<>();
|
||||||
|
int length = template.length();
|
||||||
|
int limitCount = 0;
|
||||||
|
int index = 0;
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
|
TNumberFormat format = TNumberFormat.getInstance(TLocale.US);
|
||||||
|
TParsePosition position = new TParsePosition(0);
|
||||||
|
while (true) {
|
||||||
|
index = skipWhitespace(template, index);
|
||||||
|
if (index >= length) {
|
||||||
|
if (limitCount == limits.length) {
|
||||||
|
choiceLimits = limits;
|
||||||
|
} else {
|
||||||
|
choiceLimits = new double[limitCount];
|
||||||
|
System.arraycopy(limits, 0, choiceLimits, 0, limitCount);
|
||||||
|
}
|
||||||
|
choiceFormats = new String[formats.size()];
|
||||||
|
for (int i = 0; i < formats.size(); i++) {
|
||||||
|
choiceFormats[i] = formats.get(i);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
position.setIndex(index);
|
||||||
|
Number value = format.parse(template, position);
|
||||||
|
index = skipWhitespace(template, position.getIndex());
|
||||||
|
if (position.getErrorIndex() != -1 || index >= length) {
|
||||||
|
// Fix Harmony 540
|
||||||
|
choiceLimits = new double[0];
|
||||||
|
choiceFormats = new String[0];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
char ch = template.charAt(index++);
|
||||||
|
if (limitCount == limits.length) {
|
||||||
|
double[] newLimits = new double[limitCount * 2];
|
||||||
|
System.arraycopy(limits, 0, newLimits, 0, limitCount);
|
||||||
|
limits = newLimits;
|
||||||
|
}
|
||||||
|
double next;
|
||||||
|
switch (ch) {
|
||||||
|
case '#':
|
||||||
|
case '\u2264':
|
||||||
|
next = value.doubleValue();
|
||||||
|
break;
|
||||||
|
case '<':
|
||||||
|
next = nextDouble(value.doubleValue());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
if (limitCount > 0 && next <= limits[limitCount - 1]) {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
buffer.setLength(0);
|
||||||
|
position.setIndex(index);
|
||||||
|
upTo(template, position, buffer, '|');
|
||||||
|
index = position.getIndex();
|
||||||
|
limits[limitCount++] = next;
|
||||||
|
formats.add(buffer.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object clone() {
|
||||||
|
TChoiceFormat clone = (TChoiceFormat) super.clone();
|
||||||
|
clone.choiceLimits = choiceLimits.clone();
|
||||||
|
clone.choiceFormats = choiceFormats.clone();
|
||||||
|
return clone;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object object) {
|
||||||
|
if (this == object) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!(object instanceof TChoiceFormat)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
TChoiceFormat choice = (TChoiceFormat) object;
|
||||||
|
return Arrays.equals(choiceLimits, choice.choiceLimits)
|
||||||
|
&& Arrays.equals(choiceFormats, choice.choiceFormats);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StringBuffer format(double value, StringBuffer buffer, TFieldPosition field) {
|
||||||
|
for (int i = choiceLimits.length - 1; i >= 0; i--) {
|
||||||
|
if (choiceLimits[i] <= value) {
|
||||||
|
return buffer.append(choiceFormats[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return choiceFormats.length == 0 ? buffer : buffer.append(choiceFormats[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StringBuffer format(long value, StringBuffer buffer, TFieldPosition field) {
|
||||||
|
return format((double) value, buffer, field);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object[] getFormats() {
|
||||||
|
return choiceFormats;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double[] getLimits() {
|
||||||
|
return choiceLimits;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int hashCode = 0;
|
||||||
|
for (int i = 0; i < choiceLimits.length; i++) {
|
||||||
|
long v = Double.doubleToLongBits(choiceLimits[i]);
|
||||||
|
hashCode += (int) (v ^ (v >>> 32)) + choiceFormats[i].hashCode();
|
||||||
|
}
|
||||||
|
return hashCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double nextDouble(double value) {
|
||||||
|
if (value == Double.POSITIVE_INFINITY) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
long bits;
|
||||||
|
// Handle -0.0
|
||||||
|
if (value == 0) {
|
||||||
|
bits = 0;
|
||||||
|
} else {
|
||||||
|
bits = Double.doubleToLongBits(value);
|
||||||
|
}
|
||||||
|
return Double.longBitsToDouble(value < 0 ? bits - 1 : bits + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double nextDouble(double value, boolean increment) {
|
||||||
|
return increment ? nextDouble(value) : previousDouble(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Number parse(String string, TParsePosition position) {
|
||||||
|
int offset = position.getIndex();
|
||||||
|
for (int i = 0; i < choiceFormats.length; i++) {
|
||||||
|
if (string.startsWith(choiceFormats[i], offset)) {
|
||||||
|
position.setIndex(offset + choiceFormats[i].length());
|
||||||
|
return choiceLimits[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
position.setErrorIndex(offset);
|
||||||
|
return Double.NaN;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double previousDouble(double value) {
|
||||||
|
if (value == Double.NEGATIVE_INFINITY) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
long bits;
|
||||||
|
// Handle 0.0
|
||||||
|
if (value == 0) {
|
||||||
|
bits = 0x8000000000000000L;
|
||||||
|
} else {
|
||||||
|
bits = Double.doubleToLongBits(value);
|
||||||
|
}
|
||||||
|
return Double.longBitsToDouble(value <= 0 ? bits + 1 : bits - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setChoices(double[] limits, String[] formats) {
|
||||||
|
if (limits.length != formats.length) {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
choiceLimits = limits;
|
||||||
|
choiceFormats = formats;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int skipWhitespace(String string, int index) {
|
||||||
|
int length = string.length();
|
||||||
|
while (index < length && Character.isWhitespace(string.charAt(index))) {
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toPattern() {
|
||||||
|
StringBuilder buffer = new StringBuilder();
|
||||||
|
for (int i = 0; i < choiceLimits.length; i++) {
|
||||||
|
if (i != 0) {
|
||||||
|
buffer.append('|');
|
||||||
|
}
|
||||||
|
String previous = String.valueOf(previousDouble(choiceLimits[i]));
|
||||||
|
String limit = String.valueOf(choiceLimits[i]);
|
||||||
|
if (previous.length() < limit.length()) {
|
||||||
|
buffer.append(previous);
|
||||||
|
buffer.append('<');
|
||||||
|
} else {
|
||||||
|
buffer.append(limit);
|
||||||
|
buffer.append('#');
|
||||||
|
}
|
||||||
|
boolean quote = choiceFormats[i].indexOf('|') != -1;
|
||||||
|
if (quote) {
|
||||||
|
buffer.append('\'');
|
||||||
|
}
|
||||||
|
buffer.append(choiceFormats[i]);
|
||||||
|
if (quote) {
|
||||||
|
buffer.append('\'');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
}
|
|
@ -47,6 +47,7 @@ public class TDecimalFormat extends TNumberFormat {
|
||||||
private boolean decimalSeparatorAlwaysShown;
|
private boolean decimalSeparatorAlwaysShown;
|
||||||
private boolean parseBigDecimal;
|
private boolean parseBigDecimal;
|
||||||
int exponentDigits;
|
int exponentDigits;
|
||||||
|
String pattern;
|
||||||
|
|
||||||
public TDecimalFormat() {
|
public TDecimalFormat() {
|
||||||
this(CLDRHelper.resolveNumberFormat(TLocale.getDefault().getLanguage(), TLocale.getDefault().getCountry()));
|
this(CLDRHelper.resolveNumberFormat(TLocale.getDefault().getLanguage(), TLocale.getDefault().getCountry()));
|
||||||
|
@ -65,6 +66,11 @@ public class TDecimalFormat extends TNumberFormat {
|
||||||
TDecimalFormatParser parser = new TDecimalFormatParser();
|
TDecimalFormatParser parser = new TDecimalFormatParser();
|
||||||
parser.parse(pattern);
|
parser.parse(pattern);
|
||||||
parser.apply(this);
|
parser.apply(this);
|
||||||
|
this.pattern = pattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
String toPattern() {
|
||||||
|
return pattern;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DecimalFormatSymbols getDecimalFormatSymbols() {
|
public DecimalFormatSymbols getDecimalFormatSymbols() {
|
||||||
|
|
|
@ -0,0 +1,651 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2017 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.classlib.java.text;
|
||||||
|
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import org.teavm.classlib.java.util.TIterator;
|
||||||
|
import org.teavm.classlib.java.util.TLocale;
|
||||||
|
|
||||||
|
public class TMessageFormat extends TFormat {
|
||||||
|
private TLocale locale = TLocale.getDefault();
|
||||||
|
transient private String[] strings;
|
||||||
|
private int[] argumentNumbers;
|
||||||
|
private TFormat[] formats;
|
||||||
|
private int maxOffset;
|
||||||
|
transient private int maxArgumentIndex;
|
||||||
|
|
||||||
|
public TMessageFormat(String template, TLocale locale) {
|
||||||
|
this.locale = locale;
|
||||||
|
applyPattern(template);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TMessageFormat(String template) {
|
||||||
|
applyPattern(template);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void applyPattern(String template) {
|
||||||
|
int length = template.length();
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
|
TParsePosition position = new TParsePosition(0);
|
||||||
|
List<String> localStrings = new ArrayList<>();
|
||||||
|
int argCount = 0;
|
||||||
|
int[] args = new int[10];
|
||||||
|
int maxArg = -1;
|
||||||
|
List<TFormat> localFormats = new ArrayList<>();
|
||||||
|
while (position.getIndex() < length) {
|
||||||
|
if (TFormat.upTo(template, position, buffer, '{')) {
|
||||||
|
int arg = 0;
|
||||||
|
int offset = position.getIndex();
|
||||||
|
if (offset >= length) {
|
||||||
|
throw new IllegalArgumentException("Invalid argument number");
|
||||||
|
}
|
||||||
|
// Get argument number
|
||||||
|
while (true) {
|
||||||
|
char ch = template.charAt(offset++);
|
||||||
|
if (ch == '}' || ch == ',') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (ch < '0' && ch > '9') {
|
||||||
|
throw new IllegalArgumentException("Invalid argument number");
|
||||||
|
}
|
||||||
|
arg = arg * 10 + (ch - '0');
|
||||||
|
if (arg < 0 || offset >= length) {
|
||||||
|
throw new IllegalArgumentException("Invalid argument number");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
offset--;
|
||||||
|
position.setIndex(offset);
|
||||||
|
localFormats.add(parseVariable(template, position));
|
||||||
|
if (argCount >= args.length) {
|
||||||
|
int[] newArgs = new int[args.length * 2];
|
||||||
|
System.arraycopy(args, 0, newArgs, 0, args.length);
|
||||||
|
args = newArgs;
|
||||||
|
}
|
||||||
|
args[argCount++] = arg;
|
||||||
|
if (arg > maxArg) {
|
||||||
|
maxArg = arg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
localStrings.add(buffer.toString());
|
||||||
|
buffer.setLength(0);
|
||||||
|
}
|
||||||
|
this.strings = new String[localStrings.size()];
|
||||||
|
for (int i = 0; i < localStrings.size(); i++) {
|
||||||
|
this.strings[i] = localStrings.get(i);
|
||||||
|
}
|
||||||
|
argumentNumbers = args;
|
||||||
|
this.formats = new TFormat[argCount];
|
||||||
|
for (int i = 0; i < argCount; i++) {
|
||||||
|
this.formats[i] = localFormats.get(i);
|
||||||
|
}
|
||||||
|
maxOffset = argCount - 1;
|
||||||
|
maxArgumentIndex = maxArg;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object clone() {
|
||||||
|
TMessageFormat clone = (TMessageFormat) super.clone();
|
||||||
|
TFormat[] array = new TFormat[formats.length];
|
||||||
|
for (int i = formats.length; --i >= 0;) {
|
||||||
|
if (formats[i] != null) {
|
||||||
|
array[i] = (TFormat) formats[i].clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
clone.formats = array;
|
||||||
|
return clone;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object object) {
|
||||||
|
if (this == object) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!(object instanceof TMessageFormat)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
TMessageFormat format = (TMessageFormat) object;
|
||||||
|
if (maxOffset != format.maxOffset) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Must use a loop since the lengths may be different due
|
||||||
|
// to serialization cross-loading
|
||||||
|
for (int i = 0; i <= maxOffset; i++) {
|
||||||
|
if (argumentNumbers[i] != format.argumentNumbers[i]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return locale.equals(format.locale)
|
||||||
|
&& Arrays.equals(strings, format.strings)
|
||||||
|
&& Arrays.equals(formats, format.formats);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TAttributedCharacterIterator formatToCharacterIterator(Object object) {
|
||||||
|
if (object == null) {
|
||||||
|
throw new NullPointerException();
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
|
List<FieldContainer> fields = new ArrayList<>();
|
||||||
|
|
||||||
|
// format the message, and find fields
|
||||||
|
formatImpl((Object[]) object, buffer, new TFieldPosition(0), fields);
|
||||||
|
|
||||||
|
// create an AttributedString with the formatted buffer
|
||||||
|
TAttributedString as = new TAttributedString(buffer.toString());
|
||||||
|
|
||||||
|
// add TMessageFormat field attributes and values to the AttributedString
|
||||||
|
for (FieldContainer fc : fields) {
|
||||||
|
as.addAttribute(fc.attribute, fc.value, fc.start, fc.end);
|
||||||
|
}
|
||||||
|
|
||||||
|
// return the CharacterIterator from AttributedString
|
||||||
|
return as.getIterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
public final StringBuffer format(Object[] objects, StringBuffer buffer, TFieldPosition field) {
|
||||||
|
return formatImpl(objects, buffer, field, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private StringBuffer formatImpl(Object[] objects, StringBuffer buffer, TFieldPosition position,
|
||||||
|
List<FieldContainer> fields) {
|
||||||
|
TFieldPosition passedField = new TFieldPosition(0);
|
||||||
|
for (int i = 0; i <= maxOffset; i++) {
|
||||||
|
buffer.append(strings[i]);
|
||||||
|
int begin = buffer.length();
|
||||||
|
Object arg;
|
||||||
|
if (objects != null && argumentNumbers[i] < objects.length) {
|
||||||
|
arg = objects[argumentNumbers[i]];
|
||||||
|
} else {
|
||||||
|
buffer.append('{');
|
||||||
|
buffer.append(argumentNumbers[i]);
|
||||||
|
buffer.append('}');
|
||||||
|
handleArgumentField(begin, buffer.length(), argumentNumbers[i], position, fields);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
TFormat format = formats[i];
|
||||||
|
if (format == null || arg == null) {
|
||||||
|
if (arg instanceof Number) {
|
||||||
|
format = TNumberFormat.getInstance();
|
||||||
|
} else if (arg instanceof Date) {
|
||||||
|
format = TDateFormat.getInstance();
|
||||||
|
} else {
|
||||||
|
buffer.append(arg);
|
||||||
|
handleArgumentField(begin, buffer.length(), argumentNumbers[i], position, fields);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (format instanceof TChoiceFormat) {
|
||||||
|
String result = format.format(arg);
|
||||||
|
TMessageFormat mf = new TMessageFormat(result);
|
||||||
|
mf.setLocale(locale);
|
||||||
|
mf.format(objects, buffer, passedField);
|
||||||
|
handleArgumentField(begin, buffer.length(), argumentNumbers[i], position, fields);
|
||||||
|
handleformat(format, arg, begin, fields);
|
||||||
|
} else {
|
||||||
|
format.format(arg, buffer, passedField);
|
||||||
|
handleArgumentField(begin, buffer.length(), argumentNumbers[i], position, fields);
|
||||||
|
handleformat(format, arg, begin, fields);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (maxOffset + 1 < strings.length) {
|
||||||
|
buffer.append(strings[maxOffset + 1]);
|
||||||
|
}
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleArgumentField(int begin, int end, int argnumber, TFieldPosition position,
|
||||||
|
List<FieldContainer> fields) {
|
||||||
|
if (fields != null) {
|
||||||
|
fields.add(new FieldContainer(begin, end, Field.ARGUMENT, argnumber));
|
||||||
|
} else {
|
||||||
|
if (position != null
|
||||||
|
&& position.getFieldAttribute() == Field.ARGUMENT
|
||||||
|
&& position.getEndIndex() == 0) {
|
||||||
|
position.setBeginIndex(begin);
|
||||||
|
position.setEndIndex(end);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An inner class to store attributes, values, start and end indices.
|
||||||
|
* Instances of this inner class are used as elements for the fields vector
|
||||||
|
*/
|
||||||
|
static class FieldContainer {
|
||||||
|
int start;
|
||||||
|
int end;
|
||||||
|
TAttributedCharacterIterator.Attribute attribute;
|
||||||
|
Object value;
|
||||||
|
|
||||||
|
FieldContainer(int start, int end, TAttributedCharacterIterator.Attribute attribute, Object value) {
|
||||||
|
this.start = start;
|
||||||
|
this.end = end;
|
||||||
|
this.attribute = attribute;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleformat(TFormat format, Object arg, int begin, List<FieldContainer> fields) {
|
||||||
|
if (fields != null) {
|
||||||
|
TAttributedCharacterIterator iterator = format.formatToCharacterIterator(arg);
|
||||||
|
while (iterator.getIndex() != iterator.getEndIndex()) {
|
||||||
|
int start = iterator.getRunStart();
|
||||||
|
int end = iterator.getRunLimit();
|
||||||
|
|
||||||
|
TIterator<TAttributedCharacterIterator.Attribute> iter = iterator.getAttributes().keySet().iterator();
|
||||||
|
while (iter.hasNext()) {
|
||||||
|
TAttributedCharacterIterator.Attribute attribute = iter.next();
|
||||||
|
Object value = iterator.getAttribute(attribute);
|
||||||
|
fields.add(new FieldContainer(begin + start, begin + end, attribute, value));
|
||||||
|
}
|
||||||
|
iterator.setIndex(end);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final StringBuffer format(Object object, StringBuffer buffer, TFieldPosition field) {
|
||||||
|
return format((Object[]) object, buffer, field);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String format(String template, Object... objects) {
|
||||||
|
if (objects != null) {
|
||||||
|
for (int i = 0; i < objects.length; i++) {
|
||||||
|
if (objects[i] == null) {
|
||||||
|
objects[i] = "null";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new TMessageFormat(template).format(objects, new StringBuffer(), new TFieldPosition(0)).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TFormat[] getFormats() {
|
||||||
|
return formats.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TFormat[] getFormatsByArgumentIndex() {
|
||||||
|
TFormat[] answer = new TFormat[maxArgumentIndex + 1];
|
||||||
|
for (int i = 0; i < maxOffset + 1; i++) {
|
||||||
|
answer[argumentNumbers[i]] = formats[i];
|
||||||
|
}
|
||||||
|
return answer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFormatByArgumentIndex(int argIndex, TFormat format) {
|
||||||
|
for (int i = 0; i < maxOffset + 1; i++) {
|
||||||
|
if (argumentNumbers[i] == argIndex) {
|
||||||
|
formats[i] = format;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFormatsByArgumentIndex(TFormat[] formats) {
|
||||||
|
for (int j = 0; j < formats.length; j++) {
|
||||||
|
for (int i = 0; i < maxOffset + 1; i++) {
|
||||||
|
if (argumentNumbers[i] == j) {
|
||||||
|
this.formats[i] = formats[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public TLocale getLocale() {
|
||||||
|
return locale;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int hashCode = 0;
|
||||||
|
for (int i = 0; i <= maxOffset; i++) {
|
||||||
|
hashCode += argumentNumbers[i] + strings[i].hashCode();
|
||||||
|
if (formats[i] != null) {
|
||||||
|
hashCode += formats[i].hashCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (maxOffset + 1 < strings.length) {
|
||||||
|
hashCode += strings[maxOffset + 1].hashCode();
|
||||||
|
}
|
||||||
|
if (locale != null) {
|
||||||
|
return hashCode + locale.hashCode();
|
||||||
|
}
|
||||||
|
return hashCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object[] parse(String string) throws ParseException {
|
||||||
|
TParsePosition position = new TParsePosition(0);
|
||||||
|
Object[] result = parse(string, position);
|
||||||
|
if (position.getIndex() == 0) {
|
||||||
|
throw new ParseException("MessageFormat.parseObject(String) parse failure", position.getErrorIndex());
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object[] parse(String string, TParsePosition position) {
|
||||||
|
if (string == null) {
|
||||||
|
return new Object[0];
|
||||||
|
}
|
||||||
|
TParsePosition internalPos = new TParsePosition(0);
|
||||||
|
int offset = position.getIndex();
|
||||||
|
Object[] result = new Object[maxArgumentIndex + 1];
|
||||||
|
for (int i = 0; i <= maxOffset; i++) {
|
||||||
|
String sub = strings[i];
|
||||||
|
if (!string.startsWith(sub, offset)) {
|
||||||
|
position.setErrorIndex(offset);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
offset += sub.length();
|
||||||
|
Object parse;
|
||||||
|
TFormat format = formats[i];
|
||||||
|
if (format == null) {
|
||||||
|
if (i + 1 < strings.length) {
|
||||||
|
int next = string.indexOf(strings[i + 1], offset);
|
||||||
|
if (next == -1) {
|
||||||
|
position.setErrorIndex(offset);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
parse = string.substring(offset, next);
|
||||||
|
offset = next;
|
||||||
|
} else {
|
||||||
|
parse = string.substring(offset);
|
||||||
|
offset = string.length();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
internalPos.setIndex(offset);
|
||||||
|
parse = format.parseObject(string, internalPos);
|
||||||
|
if (internalPos.getErrorIndex() != -1) {
|
||||||
|
position.setErrorIndex(offset);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
offset = internalPos.getIndex();
|
||||||
|
}
|
||||||
|
result[argumentNumbers[i]] = parse;
|
||||||
|
}
|
||||||
|
if (maxOffset + 1 < strings.length) {
|
||||||
|
String sub = strings[maxOffset + 1];
|
||||||
|
if (!string.startsWith(sub, offset)) {
|
||||||
|
position.setErrorIndex(offset);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
offset += sub.length();
|
||||||
|
}
|
||||||
|
position.setIndex(offset);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object parseObject(String string, TParsePosition position) {
|
||||||
|
return parse(string, position);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int match(String string, TParsePosition position, boolean last, String[] tokens) {
|
||||||
|
int length = string.length();
|
||||||
|
int offset = position.getIndex();
|
||||||
|
int token = -1;
|
||||||
|
while (offset < length && Character.isWhitespace(string.charAt(offset))) {
|
||||||
|
offset++;
|
||||||
|
}
|
||||||
|
for (int i = tokens.length; --i >= 0;) {
|
||||||
|
if (string.regionMatches(true, offset, tokens[i], 0, tokens[i].length())) {
|
||||||
|
token = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (token == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
offset += tokens[token].length();
|
||||||
|
while (offset < length && Character.isWhitespace(string.charAt(offset))) {
|
||||||
|
offset++;
|
||||||
|
}
|
||||||
|
char ch;
|
||||||
|
if (offset < length) {
|
||||||
|
ch = string.charAt(offset);
|
||||||
|
if (ch == '}' || (!last && ch == ',')) {
|
||||||
|
position.setIndex(offset + 1);
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private TFormat parseVariable(String string, TParsePosition position) {
|
||||||
|
int length = string.length();
|
||||||
|
int offset = position.getIndex();
|
||||||
|
char ch;
|
||||||
|
if (offset >= length) {
|
||||||
|
throw new IllegalArgumentException("Missing element format");
|
||||||
|
}
|
||||||
|
|
||||||
|
ch = string.charAt(offset++);
|
||||||
|
if (ch != '}' && ch != ',') {
|
||||||
|
throw new IllegalArgumentException("Missing element format");
|
||||||
|
}
|
||||||
|
|
||||||
|
position.setIndex(offset);
|
||||||
|
if (ch == '}') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
int type = match(string, position, false, new String[] { "time", "date", "number", "choice" });
|
||||||
|
if (type == -1) {
|
||||||
|
throw new IllegalArgumentException("Unknown element format");
|
||||||
|
}
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
|
ch = string.charAt(position.getIndex() - 1);
|
||||||
|
switch (type) {
|
||||||
|
case 0: // time
|
||||||
|
case 1: // date
|
||||||
|
if (ch == '}') {
|
||||||
|
return type == 1
|
||||||
|
? TDateFormat.getDateInstance(DateFormat.DEFAULT, locale)
|
||||||
|
: TDateFormat.getTimeInstance(DateFormat.DEFAULT, locale);
|
||||||
|
}
|
||||||
|
int dateStyle = match(string, position, true, new String[] { "full", "long", "medium", "short" });
|
||||||
|
if (dateStyle == -1) {
|
||||||
|
TFormat.upToWithQuotes(string, position, buffer, '}', '{');
|
||||||
|
return new TSimpleDateFormat(buffer.toString(), locale);
|
||||||
|
}
|
||||||
|
switch (dateStyle) {
|
||||||
|
case 0:
|
||||||
|
dateStyle = DateFormat.FULL;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
dateStyle = DateFormat.LONG;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
dateStyle = DateFormat.MEDIUM;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
dateStyle = DateFormat.SHORT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return type == 1
|
||||||
|
? TDateFormat.getDateInstance(dateStyle, locale)
|
||||||
|
: TDateFormat.getTimeInstance(dateStyle, locale);
|
||||||
|
case 2: // number
|
||||||
|
if (ch == '}') {
|
||||||
|
return TNumberFormat.getInstance();
|
||||||
|
}
|
||||||
|
int numberStyle = match(string, position, true, new String[] { "currency", "percent", "integer" });
|
||||||
|
if (numberStyle == -1) {
|
||||||
|
upToWithQuotes(string, position, buffer, '}', '{');
|
||||||
|
return new TDecimalFormat(buffer.toString(), new TDecimalFormatSymbols(locale));
|
||||||
|
}
|
||||||
|
switch (numberStyle) {
|
||||||
|
case 0: // currency
|
||||||
|
return TNumberFormat.getCurrencyInstance(locale);
|
||||||
|
case 1: // percent
|
||||||
|
return TNumberFormat.getPercentInstance(locale);
|
||||||
|
}
|
||||||
|
return TNumberFormat.getIntegerInstance(locale);
|
||||||
|
}
|
||||||
|
// choice
|
||||||
|
try {
|
||||||
|
upToWithQuotes(string, position, buffer, '}', '{');
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
|
return new TChoiceFormat(buffer.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFormat(int offset, TFormat format) {
|
||||||
|
formats[offset] = format;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFormats(TFormat[] formats) {
|
||||||
|
int min = this.formats.length;
|
||||||
|
if (formats.length < min) {
|
||||||
|
min = formats.length;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < min; i++) {
|
||||||
|
this.formats[i] = formats[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLocale(TLocale locale) {
|
||||||
|
this.locale = locale;
|
||||||
|
for (int i = 0; i <= maxOffset; i++) {
|
||||||
|
TFormat format = formats[i];
|
||||||
|
if (format instanceof TDecimalFormat) {
|
||||||
|
formats[i] = new TDecimalFormat(((TDecimalFormat) format).toPattern(),
|
||||||
|
new TDecimalFormatSymbols(locale));
|
||||||
|
} else if (format instanceof TSimpleDateFormat) {
|
||||||
|
formats[i] = new TSimpleDateFormat(((TSimpleDateFormat) format).toPattern(), locale);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String decodeDecimalFormat(StringBuffer buffer, TFormat format) {
|
||||||
|
buffer.append(",number");
|
||||||
|
if (format.equals(TNumberFormat.getNumberInstance(locale))) {
|
||||||
|
// Empty block
|
||||||
|
} else if (format.equals(TNumberFormat.getIntegerInstance(locale))) {
|
||||||
|
buffer.append(",integer");
|
||||||
|
} else if (format.equals(TNumberFormat.getCurrencyInstance(locale))) {
|
||||||
|
buffer.append(",currency");
|
||||||
|
} else if (format.equals(TNumberFormat.getPercentInstance(locale))) {
|
||||||
|
buffer.append(",percent");
|
||||||
|
} else {
|
||||||
|
buffer.append(',');
|
||||||
|
return ((TDecimalFormat) format).toPattern();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String decodeSimpleDateFormat(StringBuffer buffer, TFormat format) {
|
||||||
|
if (format.equals(TDateFormat.getTimeInstance(DateFormat.DEFAULT, locale))) {
|
||||||
|
buffer.append(",time");
|
||||||
|
} else if (format.equals(TDateFormat.getDateInstance(DateFormat.DEFAULT, locale))) {
|
||||||
|
buffer.append(",date");
|
||||||
|
} else if (format.equals(TDateFormat.getTimeInstance(DateFormat.SHORT, locale))) {
|
||||||
|
buffer.append(",time,short");
|
||||||
|
} else if (format.equals(TDateFormat.getDateInstance(DateFormat.SHORT, locale))) {
|
||||||
|
buffer.append(",date,short");
|
||||||
|
} else if (format.equals(TDateFormat.getTimeInstance(DateFormat.LONG, locale))) {
|
||||||
|
buffer.append(",time,long");
|
||||||
|
} else if (format.equals(TDateFormat.getDateInstance(DateFormat.LONG, locale))) {
|
||||||
|
buffer.append(",date,long");
|
||||||
|
} else if (format.equals(TDateFormat.getTimeInstance(DateFormat.FULL, locale))) {
|
||||||
|
buffer.append(",time,full");
|
||||||
|
} else if (format.equals(TDateFormat.getDateInstance(DateFormat.FULL, locale))) {
|
||||||
|
buffer.append(",date,full");
|
||||||
|
} else {
|
||||||
|
buffer.append(",date,");
|
||||||
|
return ((TSimpleDateFormat) format).toPattern();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toPattern() {
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
|
for (int i = 0; i <= maxOffset; i++) {
|
||||||
|
appendQuoted(buffer, strings[i]);
|
||||||
|
buffer.append('{');
|
||||||
|
buffer.append(argumentNumbers[i]);
|
||||||
|
TFormat format = formats[i];
|
||||||
|
String pattern = null;
|
||||||
|
if (format instanceof TChoiceFormat) {
|
||||||
|
buffer.append(",choice,");
|
||||||
|
pattern = ((TChoiceFormat) format).toPattern();
|
||||||
|
} else if (format instanceof TDecimalFormat) {
|
||||||
|
pattern = decodeDecimalFormat(buffer, format);
|
||||||
|
} else if (format instanceof TSimpleDateFormat) {
|
||||||
|
pattern = decodeSimpleDateFormat(buffer, format);
|
||||||
|
} else if (format != null) {
|
||||||
|
throw new IllegalArgumentException("Unknown format");
|
||||||
|
}
|
||||||
|
if (pattern != null) {
|
||||||
|
boolean quote = false;
|
||||||
|
int index = 0;
|
||||||
|
int length = pattern.length();
|
||||||
|
int count = 0;
|
||||||
|
while (index < length) {
|
||||||
|
char ch = pattern.charAt(index++);
|
||||||
|
if (ch == '\'') {
|
||||||
|
quote = !quote;
|
||||||
|
}
|
||||||
|
if (!quote) {
|
||||||
|
if (ch == '{') {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
if (ch == '}') {
|
||||||
|
if (count > 0) {
|
||||||
|
count--;
|
||||||
|
} else {
|
||||||
|
buffer.append("'}");
|
||||||
|
ch = '\'';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buffer.append(ch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buffer.append('}');
|
||||||
|
}
|
||||||
|
if (maxOffset + 1 < strings.length) {
|
||||||
|
appendQuoted(buffer, strings[maxOffset + 1]);
|
||||||
|
}
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void appendQuoted(StringBuffer buffer, String string) {
|
||||||
|
int length = string.length();
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
char ch = string.charAt(i);
|
||||||
|
if (ch == '{' || ch == '}') {
|
||||||
|
buffer.append('\'');
|
||||||
|
buffer.append(ch);
|
||||||
|
buffer.append('\'');
|
||||||
|
} else {
|
||||||
|
buffer.append(ch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Field extends TFormat.Field {
|
||||||
|
public static final Field ARGUMENT = new Field("message argument field");
|
||||||
|
|
||||||
|
protected Field(String fieldName) {
|
||||||
|
super(fieldName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,612 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2017 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.teavm.classlib.java.text;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
import java.text.ChoiceFormat;
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.text.FieldPosition;
|
||||||
|
import java.text.Format;
|
||||||
|
import java.text.MessageFormat;
|
||||||
|
import java.text.NumberFormat;
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.ParsePosition;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.GregorianCalendar;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.teavm.junit.TeaVMProperties;
|
||||||
|
import org.teavm.junit.TeaVMProperty;
|
||||||
|
import org.teavm.junit.TeaVMTestRunner;
|
||||||
|
|
||||||
|
@RunWith(TeaVMTestRunner.class)
|
||||||
|
@TeaVMProperties(value = { @TeaVMProperty(key = "java.util.Locale.available", value = "en, en_US, fr") })
|
||||||
|
public class MessageFormatTest {
|
||||||
|
private MessageFormat format1;
|
||||||
|
private MessageFormat format2;
|
||||||
|
private MessageFormat format3;
|
||||||
|
private Locale defaultLocale;
|
||||||
|
|
||||||
|
public MessageFormatTest() {
|
||||||
|
defaultLocale = Locale.getDefault();
|
||||||
|
Locale.setDefault(Locale.US);
|
||||||
|
|
||||||
|
// test with repeating formats and max argument index < max offset
|
||||||
|
String pattern = "A {3, number, currency} B {2, time} C {0, number, percent} D {4} "
|
||||||
|
+ "E {1,choice,0#off|1#on} F {0, date}";
|
||||||
|
format1 = new MessageFormat(pattern);
|
||||||
|
|
||||||
|
// test with max argument index > max offset
|
||||||
|
pattern = "A {3, number, currency} B {8, time} C {0, number, percent} D {6} "
|
||||||
|
+ "E {1,choice,0#off|1#on} F {0, date}";
|
||||||
|
format2 = new MessageFormat(pattern);
|
||||||
|
|
||||||
|
// test with argument number being zero
|
||||||
|
pattern = "A B C D E F";
|
||||||
|
format3 = new MessageFormat(pattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void constructorLjava_lang_StringLjava_util_Locale() {
|
||||||
|
// Test for method java.text.MessageFormat(java.lang.String,
|
||||||
|
// java.util.Locale)
|
||||||
|
Locale mk = new Locale("mk", "MK");
|
||||||
|
MessageFormat format = new MessageFormat(
|
||||||
|
"Date: {0,date} Currency: {1, number, currency} Integer: {2, number, integer}",
|
||||||
|
mk);
|
||||||
|
|
||||||
|
assertTrue("Wrong locale1", format.getLocale().equals(mk));
|
||||||
|
assertTrue("Wrong locale2", format.getFormats()[0].equals(DateFormat.getDateInstance(DateFormat.DEFAULT, mk)));
|
||||||
|
assertTrue("Wrong locale3", format.getFormats()[1].equals(NumberFormat.getCurrencyInstance(mk)));
|
||||||
|
assertTrue("Wrong locale4", format.getFormats()[2].equals(NumberFormat.getIntegerInstance(mk)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void constructorLjava_lang_String() {
|
||||||
|
// Test for method java.text.MessageFormat(java.lang.String)
|
||||||
|
MessageFormat format = new MessageFormat(
|
||||||
|
"abc {4,time} def {3,date} ghi {2,number} jkl {1,choice,0#low|1#high} mnop {0}");
|
||||||
|
assertTrue("Not a MessageFormat", format.getClass() == MessageFormat.class);
|
||||||
|
Format[] formats = format.getFormats();
|
||||||
|
assertNotNull("null formats", formats);
|
||||||
|
assertTrue("Wrong format count: " + formats.length, formats.length >= 5);
|
||||||
|
assertTrue("Wrong time format", formats[0].equals(DateFormat.getTimeInstance()));
|
||||||
|
assertTrue("Wrong date format", formats[1].equals(DateFormat.getDateInstance()));
|
||||||
|
assertTrue("Wrong number format", formats[2].equals(NumberFormat.getInstance()));
|
||||||
|
assertTrue("Wrong choice format", formats[3].equals(new ChoiceFormat("0.0#low|1.0#high")));
|
||||||
|
assertNull("Wrong string format", formats[4]);
|
||||||
|
|
||||||
|
Date date = new Date();
|
||||||
|
FieldPosition pos = new FieldPosition(-1);
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
|
format.format(new Object[] { "123", 1.6, 7.2, date, date }, buffer, pos);
|
||||||
|
String result = buffer.toString();
|
||||||
|
buffer.setLength(0);
|
||||||
|
buffer.append("abc ");
|
||||||
|
buffer.append(DateFormat.getTimeInstance().format(date));
|
||||||
|
buffer.append(" def ");
|
||||||
|
buffer.append(DateFormat.getDateInstance().format(date));
|
||||||
|
buffer.append(" ghi ");
|
||||||
|
buffer.append(NumberFormat.getInstance().format(new Double(7.2)));
|
||||||
|
buffer.append(" jkl high mnop 123");
|
||||||
|
assertTrue("Wrong answer:\n" + result + "\n" + buffer, result.equals(buffer.toString()));
|
||||||
|
|
||||||
|
assertEquals("Simple string", "Test message", new MessageFormat("Test message").format(new Object[0]));
|
||||||
|
|
||||||
|
result = new MessageFormat("Don't").format(new Object[0]);
|
||||||
|
assertTrue("Should not throw IllegalArgumentException: " + result, "Dont".equals(result));
|
||||||
|
|
||||||
|
try {
|
||||||
|
new MessageFormat("Invalid {1,foobar} format descriptor!");
|
||||||
|
fail("Expected test_ConstructorLjava_lang_String to throw IAE.");
|
||||||
|
} catch (IllegalArgumentException ex) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
new MessageFormat("Invalid {1,date,invalid-spec} format descriptor!");
|
||||||
|
} catch (IllegalArgumentException ex) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
|
||||||
|
// Regression for HARMONY-65
|
||||||
|
try {
|
||||||
|
new MessageFormat("{0,number,integer");
|
||||||
|
fail("Assert 0: Failed to detect unmatched brackets.");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void applyPatternLjava_lang_String() {
|
||||||
|
MessageFormat format = new MessageFormat("test");
|
||||||
|
format.applyPattern("xx {0}");
|
||||||
|
assertEquals("Invalid number", "xx 46", format.format(new Object[] { 46 }));
|
||||||
|
Date date = new Date();
|
||||||
|
String result = format.format(new Object[] { date });
|
||||||
|
String expected = "xx " + DateFormat.getInstance().format(date);
|
||||||
|
assertTrue("Invalid date:\n" + result + "\n" + expected, result.equals(expected));
|
||||||
|
format = new MessageFormat("{0,date}{1,time}{2,number,integer}");
|
||||||
|
format.applyPattern("nothing");
|
||||||
|
assertEquals("Found formats", "nothing", format.toPattern());
|
||||||
|
|
||||||
|
format.applyPattern("{0}");
|
||||||
|
assertNull("Wrong format", format.getFormats()[0]);
|
||||||
|
assertEquals("Wrong pattern", "{0}", format.toPattern());
|
||||||
|
|
||||||
|
format.applyPattern("{0, \t\u001ftime }");
|
||||||
|
assertTrue("Wrong time format", format.getFormats()[0].equals(DateFormat.getTimeInstance()));
|
||||||
|
assertEquals("Wrong time pattern", "{0,time}", format.toPattern());
|
||||||
|
format.applyPattern("{0,Time, Short\n}");
|
||||||
|
assertTrue("Wrong short time format", format.getFormats()[0].equals(
|
||||||
|
DateFormat.getTimeInstance(DateFormat.SHORT)));
|
||||||
|
assertEquals("Wrong short time pattern", "{0,time,short}", format.toPattern());
|
||||||
|
format.applyPattern("{0,TIME,\nmedium }");
|
||||||
|
assertTrue("Wrong medium time format", format.getFormats()[0].equals(
|
||||||
|
DateFormat.getTimeInstance(DateFormat.MEDIUM)));
|
||||||
|
assertEquals("Wrong medium time pattern", "{0,time}", format.toPattern());
|
||||||
|
format.applyPattern("{0,time,LONG}");
|
||||||
|
assertTrue("Wrong long time format", format.getFormats()[0].equals(
|
||||||
|
DateFormat.getTimeInstance(DateFormat.LONG)));
|
||||||
|
assertEquals("Wrong long time pattern", "{0,time,long}", format.toPattern());
|
||||||
|
format.setLocale(Locale.FRENCH); // use French since English has the
|
||||||
|
// same LONG and FULL time patterns
|
||||||
|
format.applyPattern("{0,time, Full}");
|
||||||
|
assertTrue("Wrong full time format", format.getFormats()[0]
|
||||||
|
.equals(DateFormat.getTimeInstance(DateFormat.FULL, Locale.FRENCH)));
|
||||||
|
assertEquals("Wrong full time pattern", "{0,time,full}", format.toPattern());
|
||||||
|
format.setLocale(Locale.getDefault());
|
||||||
|
|
||||||
|
format.applyPattern("{0, date}");
|
||||||
|
assertTrue("Wrong date format", format.getFormats()[0].equals(DateFormat.getDateInstance()));
|
||||||
|
assertEquals("Wrong date pattern", "{0,date}", format.toPattern());
|
||||||
|
format.applyPattern("{0, date, short}");
|
||||||
|
assertTrue("Wrong short date format", format.getFormats()[0]
|
||||||
|
.equals(DateFormat.getDateInstance(DateFormat.SHORT)));
|
||||||
|
assertEquals("Wrong short date pattern", "{0,date,short}", format.toPattern());
|
||||||
|
format.applyPattern("{0, date, medium}");
|
||||||
|
assertTrue("Wrong medium date format", format.getFormats()[0]
|
||||||
|
.equals(DateFormat.getDateInstance(DateFormat.MEDIUM)));
|
||||||
|
assertEquals("Wrong medium date pattern",
|
||||||
|
"{0,date}", format.toPattern());
|
||||||
|
format.applyPattern("{0, date, long}");
|
||||||
|
assertTrue("Wrong long date format", format.getFormats()[0]
|
||||||
|
.equals(DateFormat.getDateInstance(DateFormat.LONG)));
|
||||||
|
assertEquals("Wrong long date pattern", "{0,date,long}", format.toPattern());
|
||||||
|
format.applyPattern("{0, date, full}");
|
||||||
|
assertTrue("Wrong full date format", format.getFormats()[0]
|
||||||
|
.equals(DateFormat.getDateInstance(DateFormat.FULL)));
|
||||||
|
assertEquals("Wrong full date pattern", "{0,date,full}", format.toPattern());
|
||||||
|
|
||||||
|
format.applyPattern("{0, date, MMM d {hh:mm:ss}}");
|
||||||
|
assertEquals("Wrong time/date format", " MMM d {hh:mm:ss}", ((SimpleDateFormat) (format
|
||||||
|
.getFormats()[0])).toPattern());
|
||||||
|
assertEquals("Wrong time/date pattern",
|
||||||
|
"{0,date, MMM d {hh:mm:ss}}", format.toPattern());
|
||||||
|
|
||||||
|
format.applyPattern("{0, number}");
|
||||||
|
assertTrue("Wrong number format", format.getFormats()[0].equals(NumberFormat.getNumberInstance()));
|
||||||
|
assertEquals("Wrong number pattern", "{0,number}", format.toPattern());
|
||||||
|
format.applyPattern("{0, number, currency}");
|
||||||
|
assertTrue("Wrong currency number format", format.getFormats()[0].equals(NumberFormat.getCurrencyInstance()));
|
||||||
|
assertEquals("Wrong currency number pattern", "{0,number,currency}", format.toPattern());
|
||||||
|
format.applyPattern("{0, number, percent}");
|
||||||
|
assertTrue("Wrong percent number format", format.getFormats()[0].equals(NumberFormat.getPercentInstance()));
|
||||||
|
assertEquals("Wrong percent number pattern", "{0,number,percent}", format.toPattern());
|
||||||
|
format.applyPattern("{0, number, integer}");
|
||||||
|
NumberFormat nf = NumberFormat.getInstance();
|
||||||
|
nf.setMaximumFractionDigits(0);
|
||||||
|
nf.setParseIntegerOnly(true);
|
||||||
|
assertTrue("Wrong integer number format", format.getFormats()[0].equals(nf));
|
||||||
|
assertEquals("Wrong integer number pattern", "{0,number,integer}", format.toPattern());
|
||||||
|
|
||||||
|
format.applyPattern("{0, number, {'#'}##0.0E0}");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO validate these assertions
|
||||||
|
* String actual = ((DecimalFormat)(format.getFormats()[0])).toPattern();
|
||||||
|
* assertEquals("Wrong pattern number format", "' {#}'##0.0E0", actual);
|
||||||
|
* assertEquals("Wrong pattern number pattern", "{0,number,' {#}'##0.0E0}", format.toPattern());
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
format.applyPattern("{0, choice,0#no|1#one|2#{1,number}}");
|
||||||
|
assertEquals("Wrong choice format", "0.0#no|1.0#one|2.0#{1,number}",
|
||||||
|
((ChoiceFormat) format.getFormats()[0]).toPattern());
|
||||||
|
assertEquals("Wrong choice pattern", "{0,choice,0.0#no|1.0#one|2.0#{1,number}}", format.toPattern());
|
||||||
|
assertEquals("Wrong formatted choice", "3.6", format.format(new Object[] { 2, 3.6f }));
|
||||||
|
|
||||||
|
try {
|
||||||
|
format.applyPattern("WRONG MESSAGE FORMAT {0,number,{}");
|
||||||
|
fail("Expected IllegalArgumentException for invalid pattern");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
|
||||||
|
// Regression for HARMONY-65
|
||||||
|
MessageFormat mf = new MessageFormat("{0,number,integer}");
|
||||||
|
String badpattern = "{0,number,#";
|
||||||
|
try {
|
||||||
|
mf.applyPattern(badpattern);
|
||||||
|
fail("Assert 0: Failed to detect unmatched brackets.");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_clone() {
|
||||||
|
MessageFormat format = new MessageFormat("'{'choice'}'{0}");
|
||||||
|
MessageFormat clone = (MessageFormat) format.clone();
|
||||||
|
assertTrue("Clone not equal", format.equals(clone));
|
||||||
|
assertEquals("Wrong answer", "{choice}{0}", format.format(new Object[] {}));
|
||||||
|
clone.setFormat(0, DateFormat.getInstance());
|
||||||
|
assertTrue("Clone shares format data", !format.equals(clone));
|
||||||
|
format = (MessageFormat) clone.clone();
|
||||||
|
Format[] formats = clone.getFormats();
|
||||||
|
((SimpleDateFormat) formats[0]).applyPattern("adk123");
|
||||||
|
assertTrue("Clone shares format data", !format.equals(clone));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_equalsLjava_lang_Object() {
|
||||||
|
MessageFormat format1 = new MessageFormat("{0}");
|
||||||
|
MessageFormat format2 = new MessageFormat("{1}");
|
||||||
|
assertTrue("Should not be equal", !format1.equals(format2));
|
||||||
|
format2.applyPattern("{0}");
|
||||||
|
assertTrue("Should be equal", format1.equals(format2));
|
||||||
|
SimpleDateFormat date = (SimpleDateFormat) DateFormat.getTimeInstance();
|
||||||
|
format1.setFormat(0, DateFormat.getTimeInstance());
|
||||||
|
format2.setFormat(0, new SimpleDateFormat(date.toPattern()));
|
||||||
|
assertTrue("Should be equal2", format1.equals(format2));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_hashCode() {
|
||||||
|
assertEquals("Should be equal", 3648, new MessageFormat("rr", null).hashCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void format$Ljava_lang_ObjectLjava_lang_StringBufferLjava_text_FieldPosition() {
|
||||||
|
MessageFormat format = new MessageFormat("{1,number,integer}");
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
|
format.format(new Object[] { "0", 53.863 }, buffer, new FieldPosition(0));
|
||||||
|
assertEquals("Wrong result", "54", buffer.toString());
|
||||||
|
format.applyPattern("{0,choice,0#zero|1#one '{1,choice,2#two {2,time}}'}");
|
||||||
|
Date date = new Date();
|
||||||
|
String expected = "one two " + DateFormat.getTimeInstance().format(date);
|
||||||
|
String result = format.format(new Object[] { 1.6, 3, date });
|
||||||
|
assertTrue("Choice not recursive:\n" + expected + "\n" + result, expected.equals(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getFormats() {
|
||||||
|
// test with repeating formats and max argument index < max offset
|
||||||
|
Format[] formats = format1.getFormats();
|
||||||
|
Format[] correctFormats = new Format[] {
|
||||||
|
NumberFormat.getCurrencyInstance(),
|
||||||
|
DateFormat.getTimeInstance(),
|
||||||
|
NumberFormat.getPercentInstance(), null,
|
||||||
|
new ChoiceFormat("0#off|1#on"), DateFormat.getDateInstance()
|
||||||
|
};
|
||||||
|
|
||||||
|
assertEquals("Test1:Returned wrong number of formats:", correctFormats.length, formats.length);
|
||||||
|
for (int i = 0; i < correctFormats.length; i++) {
|
||||||
|
assertEquals("Test1:wrong format for pattern index " + i + ":", correctFormats[i], formats[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// test with max argument index > max offset
|
||||||
|
formats = format2.getFormats();
|
||||||
|
correctFormats = new Format[] { NumberFormat.getCurrencyInstance(),
|
||||||
|
DateFormat.getTimeInstance(),
|
||||||
|
NumberFormat.getPercentInstance(), null,
|
||||||
|
new ChoiceFormat("0#off|1#on"), DateFormat.getDateInstance()
|
||||||
|
};
|
||||||
|
|
||||||
|
assertEquals("Test2:Returned wrong number of formats:", correctFormats.length, formats.length);
|
||||||
|
for (int i = 0; i < correctFormats.length; i++) {
|
||||||
|
assertEquals("Test2:wrong format for pattern index " + i + ":", correctFormats[i], formats[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// test with argument number being zero
|
||||||
|
formats = format3.getFormats();
|
||||||
|
assertEquals("Test3: Returned wrong number of formats:", 0, formats.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getFormatsByArgumentIndex() {
|
||||||
|
// test with repeating formats and max argument index < max offset
|
||||||
|
Format[] formats = format1.getFormatsByArgumentIndex();
|
||||||
|
Format[] correctFormats = new Format[] { DateFormat.getDateInstance(),
|
||||||
|
new ChoiceFormat("0#off|1#on"), DateFormat.getTimeInstance(),
|
||||||
|
NumberFormat.getCurrencyInstance(), null };
|
||||||
|
|
||||||
|
assertEquals("Test1:Returned wrong number of formats:",
|
||||||
|
correctFormats.length, formats.length);
|
||||||
|
for (int i = 0; i < correctFormats.length; i++) {
|
||||||
|
assertEquals("Test1:wrong format for argument index " + i + ":", correctFormats[i], formats[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// test with max argument index > max offset
|
||||||
|
formats = format2.getFormatsByArgumentIndex();
|
||||||
|
correctFormats = new Format[] { DateFormat.getDateInstance(),
|
||||||
|
new ChoiceFormat("0#off|1#on"), null,
|
||||||
|
NumberFormat.getCurrencyInstance(), null, null, null, null,
|
||||||
|
DateFormat.getTimeInstance()
|
||||||
|
};
|
||||||
|
|
||||||
|
assertEquals("Test2:Returned wrong number of formats:", correctFormats.length, formats.length);
|
||||||
|
for (int i = 0; i < correctFormats.length; i++) {
|
||||||
|
assertEquals("Test2:wrong format for argument index " + i + ":", correctFormats[i], formats[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// test with argument number being zero
|
||||||
|
formats = format3.getFormatsByArgumentIndex();
|
||||||
|
assertEquals("Test3: Returned wrong number of formats:", 0, formats.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void setFormatByArgumentIndexILjava_text_Format() {
|
||||||
|
MessageFormat f1 = (MessageFormat) format1.clone();
|
||||||
|
f1.setFormatByArgumentIndex(0, DateFormat.getTimeInstance());
|
||||||
|
f1.setFormatByArgumentIndex(4, new ChoiceFormat("1#few|2#ok|3#a lot"));
|
||||||
|
|
||||||
|
// test with repeating formats and max argument index < max offset
|
||||||
|
// compare getFormatsByArgumentIndex() results after calls to
|
||||||
|
// setFormatByArgumentIndex()
|
||||||
|
Format[] formats = f1.getFormatsByArgumentIndex();
|
||||||
|
|
||||||
|
Format[] correctFormats = new Format[] { DateFormat.getTimeInstance(),
|
||||||
|
new ChoiceFormat("0#off|1#on"), DateFormat.getTimeInstance(),
|
||||||
|
NumberFormat.getCurrencyInstance(),
|
||||||
|
new ChoiceFormat("1#few|2#ok|3#a lot")
|
||||||
|
};
|
||||||
|
|
||||||
|
assertEquals("Test1A:Returned wrong number of formats:", correctFormats.length, formats.length);
|
||||||
|
for (int i = 0; i < correctFormats.length; i++) {
|
||||||
|
assertEquals("Test1B:wrong format for argument index " + i + ":", correctFormats[i], formats[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// compare getFormats() results after calls to
|
||||||
|
// setFormatByArgumentIndex()
|
||||||
|
formats = f1.getFormats();
|
||||||
|
|
||||||
|
correctFormats = new Format[] { NumberFormat.getCurrencyInstance(),
|
||||||
|
DateFormat.getTimeInstance(), DateFormat.getTimeInstance(),
|
||||||
|
new ChoiceFormat("1#few|2#ok|3#a lot"),
|
||||||
|
new ChoiceFormat("0#off|1#on"), DateFormat.getTimeInstance()
|
||||||
|
};
|
||||||
|
|
||||||
|
assertEquals("Test1C:Returned wrong number of formats:", correctFormats.length, formats.length);
|
||||||
|
for (int i = 0; i < correctFormats.length; i++) {
|
||||||
|
assertEquals("Test1D:wrong format for pattern index " + i + ":", correctFormats[i], formats[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// test setting argumentIndexes that are not used
|
||||||
|
MessageFormat f2 = (MessageFormat) format2.clone();
|
||||||
|
f2.setFormatByArgumentIndex(2, NumberFormat.getPercentInstance());
|
||||||
|
f2.setFormatByArgumentIndex(4, DateFormat.getTimeInstance());
|
||||||
|
|
||||||
|
formats = f2.getFormatsByArgumentIndex();
|
||||||
|
correctFormats = format2.getFormatsByArgumentIndex();
|
||||||
|
|
||||||
|
assertEquals("Test2A:Returned wrong number of formats:", correctFormats.length, formats.length);
|
||||||
|
for (int i = 0; i < correctFormats.length; i++) {
|
||||||
|
assertEquals("Test2B:wrong format for argument index " + i + ":", correctFormats[i], formats[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
formats = f2.getFormats();
|
||||||
|
correctFormats = format2.getFormats();
|
||||||
|
|
||||||
|
assertEquals("Test2C:Returned wrong number of formats:", correctFormats.length, formats.length);
|
||||||
|
for (int i = 0; i < correctFormats.length; i++) {
|
||||||
|
assertEquals("Test2D:wrong format for pattern index " + i + ":", correctFormats[i], formats[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// test exceeding the argumentIndex number
|
||||||
|
MessageFormat f3 = (MessageFormat) format3.clone();
|
||||||
|
f3.setFormatByArgumentIndex(1, NumberFormat.getCurrencyInstance());
|
||||||
|
|
||||||
|
formats = f3.getFormatsByArgumentIndex();
|
||||||
|
assertEquals("Test3A:Returned wrong number of formats:", 0, formats.length);
|
||||||
|
|
||||||
|
formats = f3.getFormats();
|
||||||
|
assertEquals("Test3B:Returned wrong number of formats:", 0, formats.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void setFormatsByArgumentIndex$Ljava_text_Format() {
|
||||||
|
MessageFormat f1 = (MessageFormat) format1.clone();
|
||||||
|
|
||||||
|
// test with repeating formats and max argument index < max offset
|
||||||
|
// compare getFormatsByArgumentIndex() results after calls to
|
||||||
|
// setFormatsByArgumentIndex(Format[])
|
||||||
|
Format[] correctFormats = new Format[] { DateFormat.getTimeInstance(),
|
||||||
|
new ChoiceFormat("0#off|1#on"), DateFormat.getTimeInstance(),
|
||||||
|
NumberFormat.getCurrencyInstance(),
|
||||||
|
new ChoiceFormat("1#few|2#ok|3#a lot")
|
||||||
|
};
|
||||||
|
|
||||||
|
f1.setFormatsByArgumentIndex(correctFormats);
|
||||||
|
Format[] formats = f1.getFormatsByArgumentIndex();
|
||||||
|
|
||||||
|
assertEquals("Test1A:Returned wrong number of formats:", correctFormats.length, formats.length);
|
||||||
|
for (int i = 0; i < correctFormats.length; i++) {
|
||||||
|
assertEquals("Test1B:wrong format for argument index " + i + ":", correctFormats[i], formats[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// compare getFormats() results after calls to
|
||||||
|
// setFormatByArgumentIndex()
|
||||||
|
formats = f1.getFormats();
|
||||||
|
correctFormats = new Format[] { NumberFormat.getCurrencyInstance(),
|
||||||
|
DateFormat.getTimeInstance(), DateFormat.getTimeInstance(),
|
||||||
|
new ChoiceFormat("1#few|2#ok|3#a lot"),
|
||||||
|
new ChoiceFormat("0#off|1#on"), DateFormat.getTimeInstance()
|
||||||
|
};
|
||||||
|
|
||||||
|
assertEquals("Test1C:Returned wrong number of formats:", correctFormats.length, formats.length);
|
||||||
|
for (int i = 0; i < correctFormats.length; i++) {
|
||||||
|
assertEquals("Test1D:wrong format for pattern index " + i + ":", correctFormats[i], formats[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// test setting argumentIndexes that are not used
|
||||||
|
MessageFormat f2 = (MessageFormat) format2.clone();
|
||||||
|
Format[] inputFormats = new Format[] { DateFormat.getDateInstance(),
|
||||||
|
new ChoiceFormat("0#off|1#on"),
|
||||||
|
NumberFormat.getPercentInstance(),
|
||||||
|
NumberFormat.getCurrencyInstance(),
|
||||||
|
DateFormat.getTimeInstance(), null, null, null,
|
||||||
|
DateFormat.getTimeInstance()
|
||||||
|
};
|
||||||
|
f2.setFormatsByArgumentIndex(inputFormats);
|
||||||
|
|
||||||
|
formats = f2.getFormatsByArgumentIndex();
|
||||||
|
correctFormats = format2.getFormatsByArgumentIndex();
|
||||||
|
|
||||||
|
assertEquals("Test2A:Returned wrong number of formats:", correctFormats.length, formats.length);
|
||||||
|
for (int i = 0; i < correctFormats.length; i++) {
|
||||||
|
assertEquals("Test2B:wrong format for argument index " + i + ":", correctFormats[i], formats[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
formats = f2.getFormats();
|
||||||
|
correctFormats = new Format[] { NumberFormat.getCurrencyInstance(),
|
||||||
|
DateFormat.getTimeInstance(), DateFormat.getDateInstance(),
|
||||||
|
null, new ChoiceFormat("0#off|1#on"),
|
||||||
|
DateFormat.getDateInstance()
|
||||||
|
};
|
||||||
|
|
||||||
|
assertEquals("Test2C:Returned wrong number of formats:", correctFormats.length, formats.length);
|
||||||
|
for (int i = 0; i < correctFormats.length; i++) {
|
||||||
|
assertEquals("Test2D:wrong format for pattern index " + i + ":", correctFormats[i], formats[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// test exceeding the argumentIndex number
|
||||||
|
MessageFormat f3 = (MessageFormat) format3.clone();
|
||||||
|
f3.setFormatsByArgumentIndex(inputFormats);
|
||||||
|
|
||||||
|
formats = f3.getFormatsByArgumentIndex();
|
||||||
|
assertEquals("Test3A:Returned wrong number of formats:", 0, formats.length);
|
||||||
|
|
||||||
|
formats = f3.getFormats();
|
||||||
|
assertEquals("Test3B:Returned wrong number of formats:", 0, formats.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parseLjava_lang_StringLjava_text_ParsePosition() {
|
||||||
|
MessageFormat format = new MessageFormat("date is {0,date,MMM d, yyyy}");
|
||||||
|
ParsePosition pos = new ParsePosition(2);
|
||||||
|
Object[] result = format.parse("xxdate is Feb 28, 1999", pos);
|
||||||
|
assertTrue("No result: " + result.length, result.length >= 1);
|
||||||
|
assertTrue("Wrong answer", result[0].equals(new GregorianCalendar(1999, Calendar.FEBRUARY, 28).getTime()));
|
||||||
|
|
||||||
|
MessageFormat mf = new MessageFormat("vm={0},{1},{2}");
|
||||||
|
result = mf.parse("vm=win,foo,bar", new ParsePosition(0));
|
||||||
|
assertTrue("Invalid parse", result[0].equals("win") && result[1].equals("foo") && result[2].equals("bar"));
|
||||||
|
|
||||||
|
mf = new MessageFormat("{0}; {0}; {0}");
|
||||||
|
String parse = "a; b; c";
|
||||||
|
result = mf.parse(parse, new ParsePosition(0));
|
||||||
|
assertEquals("Wrong variable result", "c", result[0]);
|
||||||
|
|
||||||
|
mf = new MessageFormat("before {0}, after {1,number}");
|
||||||
|
parse = "before you, after 42";
|
||||||
|
pos.setIndex(0);
|
||||||
|
pos.setErrorIndex(8);
|
||||||
|
result = mf.parse(parse, pos);
|
||||||
|
assertEquals(2, result.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void setLocaleLjava_util_Locale() {
|
||||||
|
MessageFormat format = new MessageFormat("date {0,date}");
|
||||||
|
format.setLocale(Locale.CHINA);
|
||||||
|
assertEquals("Wrong locale1", Locale.CHINA, format.getLocale());
|
||||||
|
format.applyPattern("{1,date}");
|
||||||
|
assertEquals("Wrong locale3", DateFormat.getDateInstance(DateFormat.DEFAULT,
|
||||||
|
Locale.CHINA), format.getFormats()[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void toPattern() {
|
||||||
|
String pattern = "[{0}]";
|
||||||
|
MessageFormat mf = new MessageFormat(pattern);
|
||||||
|
assertTrue("Wrong pattern", mf.toPattern().equals(pattern));
|
||||||
|
|
||||||
|
// Regression for HARMONY-59
|
||||||
|
new MessageFormat("CHOICE {1,choice}").toPattern();
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
Locale.setDefault(defaultLocale);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void constructorLjava_util_Locale() {
|
||||||
|
// Regression for HARMONY-65
|
||||||
|
try {
|
||||||
|
new MessageFormat("{0,number,integer", Locale.US);
|
||||||
|
fail("Assert 0: Failed to detect unmatched brackets.");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parse() throws ParseException {
|
||||||
|
// Regression for HARMONY-63
|
||||||
|
MessageFormat mf = new MessageFormat("{0,number,#,####}", Locale.US);
|
||||||
|
Object[] res = mf.parse("1,00,00");
|
||||||
|
assertEquals("Assert 0: incorrect size of parsed data ", 1, res.length);
|
||||||
|
assertEquals("Assert 1: parsed value incorrectly", 10000L, res[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void format_Object() {
|
||||||
|
// Regression for HARMONY-1875
|
||||||
|
Locale.setDefault(Locale.CANADA);
|
||||||
|
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
|
||||||
|
String pat = "text here {0, date, yyyyyyyyy } and here";
|
||||||
|
String etalon = "text here 000002007 and here";
|
||||||
|
MessageFormat obj = new MessageFormat(pat);
|
||||||
|
assertEquals(etalon, obj.format(new Object[] { new Date(1198141737640L) }));
|
||||||
|
|
||||||
|
assertEquals("{0}", MessageFormat.format("{0}", (Object[]) null));
|
||||||
|
assertEquals("nullABC", MessageFormat.format("{0}{1}", new String[]{null, "ABC"}));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHARMONY5323() {
|
||||||
|
Object[] messageArgs = new Object[11];
|
||||||
|
for (int i = 0; i < messageArgs.length; i++) {
|
||||||
|
messageArgs[i] = "dumb" + i;
|
||||||
|
}
|
||||||
|
|
||||||
|
String res = MessageFormat.format("bgcolor=\"{10}\"", messageArgs);
|
||||||
|
assertEquals(res, "bgcolor=\"dumb10\"");
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user