ICU-12351 Add missing field position data in DecimalFormat

X-SVN-Rev: 38544
This commit is contained in:
Craig Cornelius 2016-03-21 17:18:32 +00:00
parent 34dc0a8069
commit 16557dbe12
2 changed files with 260 additions and 12 deletions

View File

@ -843,6 +843,9 @@ public class DecimalFormat extends NumberFormat {
}
result.append(symbols.getNaN());
// TODO: Combine setting a single FieldPosition or adding to an AttributedCharacterIterator
// into a function like recordAttribute(FieldAttribute, begin, end).
// [Spark/CDL] Add attribute for NaN here.
// result.append(symbols.getNaN());
if (parseAttr) {
@ -1429,10 +1432,9 @@ public class DecimalFormat extends NumberFormat {
// [Spark/CDL] Record the integer start index.
int intBegin = result.length();
// Record field information for caller.
if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
fieldPosition.setBeginIndex(result.length());
} else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
fieldPosition.setBeginIndex(result.length());
if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD ||
fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
fieldPosition.setBeginIndex(intBegin);
}
long fractionalDigits = 0;
int fractionalDigitsCount = 0;
@ -1484,17 +1486,22 @@ public class DecimalFormat extends NumberFormat {
if (isGroupingPosition(i)) {
result.append(grouping);
// [Spark/CDL] Add grouping separator attribute here.
// Set only for the first instance.
// Length of grouping separator is 1.
if (fieldPosition.getFieldAttribute() == Field.GROUPING_SEPARATOR &&
fieldPosition.getBeginIndex() == 0 && fieldPosition.getEndIndex() == 0) {
fieldPosition.setBeginIndex(result.length()-1);
fieldPosition.setEndIndex(result.length());
}
if (parseAttr) {
// Length of grouping separator is 1.
addAttribute(Field.GROUPING_SEPARATOR, result.length() - 1, result.length());
}
}
}
// Record field information for caller.
if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
fieldPosition.setEndIndex(result.length());
} else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD ||
fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
fieldPosition.setEndIndex(result.length());
}
@ -1640,7 +1647,6 @@ public class DecimalFormat extends NumberFormat {
fieldPosition.setBeginIndex(-1);
}
// [Spark/CDL]
// the begin index of integer part
// the end index of integer part
@ -1716,7 +1722,13 @@ public class DecimalFormat extends NumberFormat {
intEnd = result.length();
addAttribute(Field.INTEGER, intBegin, result.length());
}
if (fieldPosition.getFieldAttribute() == Field.DECIMAL_SEPARATOR) {
fieldPosition.setBeginIndex(result.length());
}
result.append(decimal);
if (fieldPosition.getFieldAttribute() == Field.DECIMAL_SEPARATOR) {
fieldPosition.setEndIndex(result.length());
}
// [Spark/CDL] Add attribute for decimal separator
fracBegin = result.length();
if (parseAttr) {
@ -1777,7 +1789,7 @@ public class DecimalFormat extends NumberFormat {
((UFieldPosition) fieldPosition).setFractionDigits(fractionalDigitsCount, fractionalDigits);
}
// [Spark/CDL] Calcuate the end index of integer part and fractional
// [Spark/CDL] Calculate the end index of integer part and fractional
// part if they are not properly processed yet.
if (parseAttr) {
if (intEnd < 0) {
@ -1791,7 +1803,14 @@ public class DecimalFormat extends NumberFormat {
// The exponent is output using the pattern-specified minimum exponent
// digits. There is no maximum limit to the exponent digits, since truncating
// the exponent would result in an unacceptable inaccuracy.
if (fieldPosition.getFieldAttribute() == Field.EXPONENT_SYMBOL) {
fieldPosition.setBeginIndex(result.length());
}
result.append(symbols.getExponentSeparator());
if (fieldPosition.getFieldAttribute() == Field.EXPONENT_SYMBOL) {
fieldPosition.setEndIndex(result.length());
}
// [Spark/CDL] For exponent symbol, add an attribute.
if (parseAttr) {
addAttribute(Field.EXPONENT_SYMBOL, result.length() -
@ -1806,7 +1825,13 @@ public class DecimalFormat extends NumberFormat {
boolean negativeExponent = exponent < 0;
if (negativeExponent) {
exponent = -exponent;
if (fieldPosition.getFieldAttribute() == Field.EXPONENT_SIGN) {
fieldPosition.setBeginIndex(result.length());
}
result.append(symbols.getMinusString());
if (fieldPosition.getFieldAttribute() == Field.EXPONENT_SIGN) {
fieldPosition.setEndIndex(result.length());
}
// [Spark/CDL] If exponent has sign, then add an exponent sign
// attribute.
if (parseAttr) {
@ -1814,7 +1839,13 @@ public class DecimalFormat extends NumberFormat {
addAttribute(Field.EXPONENT_SIGN, result.length() - 1, result.length());
}
} else if (exponentSignAlwaysShown) {
if (fieldPosition.getFieldAttribute() == Field.EXPONENT_SIGN) {
fieldPosition.setBeginIndex(result.length());
}
result.append(symbols.getPlusString());
if (fieldPosition.getFieldAttribute() == Field.EXPONENT_SIGN) {
fieldPosition.setEndIndex(result.length());
}
// [Spark/CDL] Add an plus sign attribute.
if (parseAttr) {
// Length of exponent sign is 1.
@ -1837,6 +1868,10 @@ public class DecimalFormat extends NumberFormat {
: digits[0]);
}
// [Spark/CDL] Add attribute for exponent part.
if (fieldPosition.getFieldAttribute() == Field.EXPONENT) {
fieldPosition.setBeginIndex(expBegin);
fieldPosition.setEndIndex(result.length());
}
if (parseAttr) {
addAttribute(Field.EXPONENT, expBegin, result.length());
}
@ -4240,7 +4275,31 @@ public class DecimalFormat extends NumberFormat {
}
}
// If kCurrencySymbol or kIntlCurrencySymbol is in the affix, check for currency symbol.
// Look for SIGN, PERCENT, PERMILLE in the formatted affix.
if (fieldPosition.getFieldAttribute() == NumberFormat.Field.SIGN) {
String sign = isNegative ? symbols.getMinusString() : symbols.getPlusString();
int firstPos = affix.indexOf(sign);
if (firstPos > -1) {
int startPos = buf.length() + firstPos;
fieldPosition.setBeginIndex(startPos);
fieldPosition.setEndIndex(startPos + sign.length());
}
} else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.PERCENT) {
int firstPos = affix.indexOf(symbols.getPercent());
if (firstPos > -1) {
int startPos = buf.length() + firstPos;
fieldPosition.setBeginIndex(startPos);
fieldPosition.setEndIndex(startPos + 1);
}
} else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.PERMILLE) {
int firstPos = affix.indexOf(symbols.getPerMill());
if (firstPos > -1) {
int startPos = buf.length() + firstPos;
fieldPosition.setBeginIndex(startPos);
fieldPosition.setEndIndex(startPos + 1);
}
} else
// If CurrencySymbol or InternationalCurrencySymbol is in the affix, check for currency symbol.
// Get spelled out name if "¤¤¤" is in the pattern.
if (fieldPosition.getFieldAttribute() == NumberFormat.Field.CURRENCY) {
if (affix.indexOf(symbols.getCurrencySymbol()) > -1) {
@ -4251,7 +4310,7 @@ public class DecimalFormat extends NumberFormat {
fieldPosition.setBeginIndex(start);
fieldPosition.setEndIndex(end);
} else if (affix.indexOf(symbols.getInternationalCurrencySymbol()) > -1) {
String aff = symbols.getInternationalCurrencySymbol();
String aff = symbols.getInternationalCurrencySymbol();
int firstPos = affix.indexOf(aff);
int start = buf.length() + firstPos;
int end = start + aff.length();

View File

@ -16,6 +16,7 @@ import java.io.IOException;
import java.math.BigInteger;
import java.text.AttributedCharacterIterator;
import java.text.FieldPosition;
import java.text.Format;
import java.text.ParseException;
import java.text.ParsePosition;
import java.util.ArrayList;
@ -4509,4 +4510,192 @@ public class NumberFormatTest extends com.ibm.icu.dev.test.TestFmwk {
assertEquals("ICU and JDK placement of decimal in exponent", jdk, icu);
}
private void checkFormatWithField(String testInfo, Format format, Object object,
String expected, Format.Field field, int begin, int end) {
StringBuffer buffer = new StringBuffer();
FieldPosition pos = new FieldPosition(field);
format.format(object, buffer, pos);
assertEquals("Test " + testInfo + ": incorrect formatted text", expected, buffer.toString());
if (begin != pos.getBeginIndex() || end != pos.getEndIndex()) {
assertEquals("Index mismatch", field + " " + begin + ".." + end,
pos.getFieldAttribute() + " " + pos.getBeginIndex() + ".." + pos.getEndIndex());
}
}
public void TestMissingFieldPositionsCurrency() {
DecimalFormat formatter = (DecimalFormat) NumberFormat.getCurrencyInstance(ULocale.US);
Number number = new Double(92314587.66);
String result = "$92,314,587.66";
checkFormatWithField("currency", formatter, number, result,
NumberFormat.Field.CURRENCY, 0, 1);
checkFormatWithField("integer", formatter, number, result,
NumberFormat.Field.INTEGER, 1, 11);
checkFormatWithField("grouping separator", formatter, number, result,
NumberFormat.Field.GROUPING_SEPARATOR, 3, 4);
checkFormatWithField("decimal separator", formatter, number, result,
NumberFormat.Field.DECIMAL_SEPARATOR, 11, 12);
checkFormatWithField("fraction", formatter, number, result,
NumberFormat.Field.FRACTION, 12, 14);
}
public void TestMissingFieldPositionsNegativeDouble() {
// test for exponential fields with double
DecimalFormatSymbols us_symbols = new DecimalFormatSymbols(ULocale.US);
Number number = new Double(-12345678.90123);
DecimalFormat formatter = new DecimalFormat("0.#####E+00", us_symbols);
String numFmtted = formatter.format(number);
checkFormatWithField("sign", formatter, number, numFmtted,
NumberFormat.Field.SIGN, 0, 1);
checkFormatWithField("integer", formatter, number, numFmtted,
NumberFormat.Field.INTEGER, 1, 2);
checkFormatWithField("decimal separator", formatter, number, numFmtted,
NumberFormat.Field.DECIMAL_SEPARATOR, 2, 3);
checkFormatWithField("exponent symbol", formatter, number, numFmtted,
NumberFormat.Field.EXPONENT_SYMBOL, 8, 9);
checkFormatWithField("exponent sign", formatter, number, numFmtted,
NumberFormat.Field.EXPONENT_SIGN, 9, 10);
checkFormatWithField("exponent", formatter, number, numFmtted,
NumberFormat.Field.EXPONENT, 10, 12);
}
public void TestMissingFieldPositionsPerCent() {
// Check PERCENT
DecimalFormat percentFormat = (DecimalFormat) NumberFormat.getPercentInstance(ULocale.US);
Number number = new Double(-0.986);
String numberFormatted = percentFormat.format(number);
checkFormatWithField("sign", percentFormat, number, numberFormatted,
NumberFormat.Field.SIGN, 0, 1);
checkFormatWithField("integer", percentFormat, number, numberFormatted,
NumberFormat.Field.INTEGER, 1, 3);
checkFormatWithField("percent", percentFormat, number, numberFormatted,
NumberFormat.Field.PERCENT, 3, 4);
}
public void TestMissingFieldPositionsPerCentPattern() {
// Check PERCENT with more digits
DecimalFormatSymbols us_symbols = new DecimalFormatSymbols(ULocale.US);
DecimalFormat fmtPercent = new DecimalFormat("0.#####%", us_symbols);
Number number = new Double(-0.986);
String numFmtted = fmtPercent.format(number);
checkFormatWithField("sign", fmtPercent, number, numFmtted,
NumberFormat.Field.SIGN, 0, 1);
checkFormatWithField("integer", fmtPercent, number, numFmtted,
NumberFormat.Field.INTEGER, 1, 3);
checkFormatWithField("decimal separator", fmtPercent, number, numFmtted,
NumberFormat.Field.DECIMAL_SEPARATOR, 3, 4);
checkFormatWithField("fraction", fmtPercent, number, numFmtted,
NumberFormat.Field.FRACTION, 4, 5);
checkFormatWithField("percent", fmtPercent, number, numFmtted,
NumberFormat.Field.PERCENT, 5, 6);
}
public void TestMissingFieldPositionsPerMille() {
// Check PERMILLE
DecimalFormatSymbols us_symbols = new DecimalFormatSymbols(ULocale.US);
DecimalFormat fmtPerMille = new DecimalFormat("0.######‰", us_symbols);
Number numberPermille = new Double(-0.98654);
String numFmtted = fmtPerMille.format(numberPermille);
checkFormatWithField("sign", fmtPerMille, numberPermille, numFmtted,
NumberFormat.Field.SIGN, 0, 1);
checkFormatWithField("integer", fmtPerMille, numberPermille, numFmtted,
NumberFormat.Field.INTEGER, 1, 4);
checkFormatWithField("decimal separator", fmtPerMille, numberPermille, numFmtted,
NumberFormat.Field.DECIMAL_SEPARATOR, 4, 5);
checkFormatWithField("fraction", fmtPerMille, numberPermille, numFmtted,
NumberFormat.Field.FRACTION, 5, 7);
checkFormatWithField("permille", fmtPerMille, numberPermille, numFmtted,
NumberFormat.Field.PERMILLE, 7, 8);
}
public void TestMissingFieldPositionsNegativeBigInt() {
DecimalFormatSymbols us_symbols = new DecimalFormatSymbols(ULocale.US);
DecimalFormat formatter = new DecimalFormat("0.#####E+0", us_symbols);
Number number = new BigDecimal("-123456789987654321");
String bigDecFmtted = formatter.format(number);
checkFormatWithField("sign", formatter, number, bigDecFmtted,
NumberFormat.Field.SIGN, 0, 1);
checkFormatWithField("integer", formatter, number, bigDecFmtted,
NumberFormat.Field.INTEGER, 1, 2);
checkFormatWithField("decimal separator", formatter, number, bigDecFmtted,
NumberFormat.Field.DECIMAL_SEPARATOR, 2, 3);
checkFormatWithField("exponent symbol", formatter, number, bigDecFmtted,
NumberFormat.Field.EXPONENT_SYMBOL, 8, 9);
checkFormatWithField("exponent sign", formatter, number, bigDecFmtted,
NumberFormat.Field.EXPONENT_SIGN, 9, 10);
checkFormatWithField("exponent", formatter, number, bigDecFmtted,
NumberFormat.Field.EXPONENT, 10, 12);
}
public void TestMissingFieldPositionsNegativeLong() {
Number number = new Long("-123456789987654321");
DecimalFormatSymbols us_symbols = new DecimalFormatSymbols(ULocale.US);
DecimalFormat formatter = new DecimalFormat("0.#####E+0", us_symbols);
String longFmtted = formatter.format(number);
checkFormatWithField("sign", formatter, number, longFmtted,
NumberFormat.Field.SIGN, 0, 1);
checkFormatWithField("integer", formatter, number, longFmtted,
NumberFormat.Field.INTEGER, 1, 2);
checkFormatWithField("decimal separator", formatter, number, longFmtted,
NumberFormat.Field.DECIMAL_SEPARATOR, 2, 3);
checkFormatWithField("exponent symbol", formatter, number, longFmtted,
NumberFormat.Field.EXPONENT_SYMBOL, 8, 9);
checkFormatWithField("exponent sign", formatter, number, longFmtted,
NumberFormat.Field.EXPONENT_SIGN, 9, 10);
checkFormatWithField("exponent", formatter, number, longFmtted,
NumberFormat.Field.EXPONENT, 10, 12);
}
public void TestMissingFieldPositionsPositiveBigDec() {
// Check complex positive;negative pattern.
DecimalFormatSymbols us_symbols = new DecimalFormatSymbols(ULocale.US);
DecimalFormat fmtPosNegSign = new DecimalFormat("+0.####E+00;-0.#######E+0", us_symbols);
Number positiveExp = new Double("9876543210");
String posExpFormatted = fmtPosNegSign.format(positiveExp);
checkFormatWithField("sign", fmtPosNegSign, positiveExp, posExpFormatted,
NumberFormat.Field.SIGN, 0, 1);
checkFormatWithField("integer", fmtPosNegSign, positiveExp, posExpFormatted,
NumberFormat.Field.INTEGER, 1, 2);
checkFormatWithField("decimal separator", fmtPosNegSign, positiveExp, posExpFormatted,
NumberFormat.Field.DECIMAL_SEPARATOR, 2, 3);
checkFormatWithField("fraction", fmtPosNegSign, positiveExp, posExpFormatted,
NumberFormat.Field.FRACTION, 3, 7);
checkFormatWithField("exponent symbol", fmtPosNegSign, positiveExp, posExpFormatted,
NumberFormat.Field.EXPONENT_SYMBOL, 7, 8);
checkFormatWithField("exponent sign", fmtPosNegSign, positiveExp, posExpFormatted,
NumberFormat.Field.EXPONENT_SIGN, 8, 9);
checkFormatWithField("exponent", fmtPosNegSign, positiveExp, posExpFormatted,
NumberFormat.Field.EXPONENT, 9, 11);
}
public void TestMissingFieldPositionsNegativeBigDec() {
// Check complex positive;negative pattern.
DecimalFormatSymbols us_symbols = new DecimalFormatSymbols(ULocale.US);
DecimalFormat fmtPosNegSign = new DecimalFormat("+0.####E+00;-0.#######E+0", us_symbols);
Number negativeExp = new BigDecimal("-0.000000987654321083");
String negExpFormatted = fmtPosNegSign.format(negativeExp);
checkFormatWithField("sign", fmtPosNegSign, negativeExp, negExpFormatted,
NumberFormat.Field.SIGN, 0, 1);
checkFormatWithField("integer", fmtPosNegSign, negativeExp, negExpFormatted,
NumberFormat.Field.INTEGER, 1, 2);
checkFormatWithField("decimal separator", fmtPosNegSign, negativeExp, negExpFormatted,
NumberFormat.Field.DECIMAL_SEPARATOR, 2, 3);
checkFormatWithField("fraction", fmtPosNegSign, negativeExp, negExpFormatted,
NumberFormat.Field.FRACTION, 3, 7);
checkFormatWithField("exponent symbol", fmtPosNegSign, negativeExp, negExpFormatted,
NumberFormat.Field.EXPONENT_SYMBOL, 7, 8);
checkFormatWithField("exponent sign", fmtPosNegSign, negativeExp, negExpFormatted,
NumberFormat.Field.EXPONENT_SIGN, 8, 9);
checkFormatWithField("exponent", fmtPosNegSign, negativeExp, negExpFormatted,
NumberFormat.Field.EXPONENT, 9, 11);
}
}