boolean ignoreNegativeSuffix = false;
DecimalFormatSymbols symbols = fmt.getDecimalFormatSymbols();
// Initialize the parsing result buffers
FastStringBuffer numberBuffer = new FastStringBuffer();
FastStringBuffer prefixStringStringBuffer = new FastStringBuffer();
FastStringBuffer suffixStringStringBuffer = new FastStringBuffer();
// Extract localized characters for parsing numbers
// For the string "1,234.56" '.' is the decimal separator.
char decimalSep = symbols.getDecimalSeparator();
//For the string "1,234.56" ',' is the grouping separator.
char groupSep = symbols.getGroupingSeparator();
// The negativePrefix will typically be ( or -, as in (100) or -100.
String negativePrefix = fmt.getNegativePrefix();
// The negative suffix will typically be ) or '', as in (100) or -100.
// Something like 100- is allowed in some locals as well though.
String negativeSuffix = fmt.getNegativeSuffix();
int length = string.length();
Log.util.debug("parseBigDecimal: string = %s, neg prefix = %s, neg suffix = %s",
string, negativePrefix, negativeSuffix);
// housekeeping for negative signs
boolean negativePrefixIsMissing =
StringUtil.nullOrEmptyOrBlankString(negativePrefix);
boolean negativeSuffixIsMissing =
StringUtil.nullOrEmptyOrBlankString(negativeSuffix);
if (negativePrefixIsMissing) {
if (!negativeSuffixIsMissing) {
ignoreNegativePrefix = true;
}
else {
// We have no negative prefix or suffix,
// so we don't have the (optional) negative pattern at all.
// The core java doc says to use '-' as prefix.
negativePrefix = CanonicalNegativePrefix;
ignoreNegativeSuffix = true;
}
}
// we have a negative prefix and no negative suffix
else if (negativeSuffixIsMissing) {
ignoreNegativeSuffix = true;
}
boolean negPrefixFound = false;
boolean negSuffixFound = false;
// if we've found any digits (decimal or integer) anywhere ever in the loop
boolean foundDigits = false;
// count of the decimal digits, ie 1.23 would have 2 at the end of the loop
int decimalDigits = 0;
// count of the integer digits, ie 1.23 would have 1 at the end of the loop
int integerDigits = 0;
// index of the decimal point, ie 1.23 would have decimal location 1
int decimalLocation = NOT_FOUND;
/*
* Read through input string, character by character.
* This will fill the buffers and replace any localized punctuation
* characters with canonical ones
*/
for (int i = 0; i < length; i++) {
char curChar = string.charAt(i);
char nextChar = i < length-1 ? string.charAt(i+1) : ' ';
// Are we on the format's negative prefix? If so, skip it
// We check for the canonical negative prefix below
if (!negPrefixFound && !foundDigits && negativePrefix.length() > 0 &&
string.indexOf(negativePrefix, i) == i)
{
Log.util.debug("found neg prefix at %s", i);
negPrefixFound = true;
i += negativePrefix.length()-1;
}
// Are we on the negative suffix? If so, skip it
else if (!negSuffixFound && foundDigits &&
negativeSuffix.length() > 0 &&
string.indexOf(negativeSuffix, i) == i)
{
negSuffixFound = true;
Log.util.debug("found neg suffix at %s", i);
i += negativeSuffix.length()-1;
}
// We found a decimal separator if there's a digit either
// before or after the separator and there aren't more
// decimal separators after the current one.
else if (decimalSep == curChar &&
(foundDigits || Character.isDigit(nextChar) &&
string.lastIndexOf(decimalSep) == i))
{
// Replace with the canonical decimal separator for the
// BigDecimal constructor.
numberBuffer.append(CanonicalDecimalSeparator);
decimalLocation = i;
}
// We're in the group separator (canonical ',') or in white space
else if (Character.isWhitespace(curChar) ||
Character.isSpaceChar(curChar) ||
groupSep == curChar)
{
// ignore these characters, no state changes at all
}
// We're either in the number itself
else if (Character.isDigit(curChar)) {
// If we found a suffix yet there's still digits,
// then we've got exponential notation or an invalid number
boolean exponentialOrInvalid =
suffixStringStringBuffer.length() > 0 || negSuffixFound;
if (exponentialOrInvalid) {
char prevChar = string.charAt(i -1);
boolean exponential = prevChar == 'E' || prevChar == 'e';
if (exponential) {
return BigDecimalParser.parseExponentialBigDecimal(string, fmt);
}
else {
throw makeParseException(InvalidCharacterInNumberKey, 1);
}
}
numberBuffer.append(curChar);
foundDigits = true;
if (decimalLocation > NOT_FOUND) {
// decimal place has been found
decimalDigits++;
}
else {
integerDigits++;
}
}
// we're on the prefix string, AKA random text before the number
else if (!foundDigits)
{
prefixStringStringBuffer.append(curChar);
}
// must be the string suffix
else {
suffixStringStringBuffer.append(curChar);
}
} // end input string loop
/* Convert the buffer data to the format for DecimalParseInfo's constructor */
// make number buffer negative based on housekeeping data
boolean negativePrefixWasIgnored =
!negPrefixFound && ignoreNegativePrefix;
boolean negativePrefixIsValid =
negativePrefixWasIgnored || negPrefixFound;
boolean negativeSuffixWasIgnored =
!negSuffixFound && ignoreNegativeSuffix;
boolean negativeSuffixIsValid =
negativeSuffixWasIgnored || negSuffixFound;
// Put back a canonical minus sign if the number is negative
boolean isNegative = negativePrefixIsValid && negativeSuffixIsValid;
if (isNegative) {
numberBuffer.insert(CanonicalMinusSign, 0);
}
// sanity check
boolean noNumbers = numberBuffer.length() == 0;
if (noNumbers) {
throw makeParseException(NoDigitsFoundKey, 0);
}
// convert number buffer to big decimal
String numberString = numberBuffer.toString();
BigDecimal amount = Constants.ZeroBigDecimal;
try {
amount = new BigDecimal(numberString);
}
catch (NumberFormatException e) {
throw makeParseException(NumberFormatErrorKey, 0);
}
// convert other buffers to strings
String prefixString = prefixStringStringBuffer.toString();
if (StringUtil.nullOrEmptyOrBlankString(prefixString)) {
prefixString = null;
}
String suffixString = suffixStringStringBuffer.toString();
if (StringUtil.nullOrEmptyOrBlankString(suffixString)) {
suffixString = null;
}
/* Use converted housekeeping data */