org.csveed.bean.conversion.NumberUtils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of csveed Show documentation
Show all versions of csveed Show documentation
Java toolkit for mapping CSV-to-Bean mapping and vice versa. Redirection to Introduction in 5 seconds!
package org.csveed.bean.conversion;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.ParseException;
import static org.csveed.bean.conversion.ConversionUtil.trimAllWhitespace;
public abstract class NumberUtils {
@SuppressWarnings("unchecked")
public static T convertNumberToTargetClass(Number number, Class targetClass)
throws IllegalArgumentException {
if (targetClass.isInstance(number)) {
return (T) number;
}
else if (targetClass.equals(Byte.class)) {
long value = number.longValue();
if (value < Byte.MIN_VALUE || value > Byte.MAX_VALUE) {
raiseOverflowException(number, targetClass);
}
return (T) new Byte(number.byteValue());
}
else if (targetClass.equals(Short.class)) {
long value = number.longValue();
if (value < Short.MIN_VALUE || value > Short.MAX_VALUE) {
raiseOverflowException(number, targetClass);
}
return (T) new Short(number.shortValue());
}
else if (targetClass.equals(Integer.class)) {
long value = number.longValue();
if (value < Integer.MIN_VALUE || value > Integer.MAX_VALUE) {
raiseOverflowException(number, targetClass);
}
return (T) new Integer(number.intValue());
}
else if (targetClass.equals(Long.class)) {
return (T) new Long(number.longValue());
}
else if (targetClass.equals(BigInteger.class)) {
if (number instanceof BigDecimal) {
// do not lose precision - use BigDecimal's own conversion
return (T) ((BigDecimal) number).toBigInteger();
}
else {
// original value is not a Big* number - use standard long conversion
return (T) BigInteger.valueOf(number.longValue());
}
}
else if (targetClass.equals(Float.class)) {
return (T) new Float(number.floatValue());
}
else if (targetClass.equals(Double.class)) {
return (T) new Double(number.doubleValue());
}
else if (targetClass.equals(BigDecimal.class)) {
// always use BigDecimal(String) here to avoid unpredictability of BigDecimal(double)
// (see BigDecimal javadoc for details)
return (T) new BigDecimal(number.toString());
}
else {
throw new IllegalArgumentException("Could not convert number [" + number + "] of type [" +
number.getClass().getName() + "] to unknown target class [" + targetClass.getName() + "]");
}
}
private static void raiseOverflowException(Number number, Class targetClass) {
throw new IllegalArgumentException("Could not convert number [" + number + "] of type [" +
number.getClass().getName() + "] to target class [" + targetClass.getName() + "]: overflow");
}
@SuppressWarnings("unchecked")
public static T parseNumber(String text, Class targetClass) {
String trimmed = trimAllWhitespace(text);
if (targetClass.equals(Byte.class)) {
return (T) (isHexNumber(trimmed) ? Byte.decode(trimmed) : Byte.valueOf(trimmed));
}
else if (targetClass.equals(Short.class)) {
return (T) (isHexNumber(trimmed) ? Short.decode(trimmed) : Short.valueOf(trimmed));
}
else if (targetClass.equals(Integer.class)) {
return (T) (isHexNumber(trimmed) ? Integer.decode(trimmed) : Integer.valueOf(trimmed));
}
else if (targetClass.equals(Long.class)) {
return (T) (isHexNumber(trimmed) ? Long.decode(trimmed) : Long.valueOf(trimmed));
}
else if (targetClass.equals(BigInteger.class)) {
return (T) (isHexNumber(trimmed) ? decodeBigInteger(trimmed) : new BigInteger(trimmed));
}
else if (targetClass.equals(Float.class)) {
return (T) Float.valueOf(trimmed);
}
else if (targetClass.equals(Double.class)) {
return (T) Double.valueOf(trimmed);
}
else if (targetClass.equals(BigDecimal.class) || targetClass.equals(Number.class)) {
return (T) new BigDecimal(trimmed);
}
else {
throw new IllegalArgumentException(
"Cannot convert String [" + text + "] to target class [" + targetClass.getName() + "]");
}
}
public static T parseNumber(String text, Class targetClass, NumberFormat numberFormat) {
if (numberFormat != null) {
DecimalFormat decimalFormat = null;
boolean resetBigDecimal = false;
if (numberFormat instanceof DecimalFormat) {
decimalFormat = (DecimalFormat) numberFormat;
if (BigDecimal.class.equals(targetClass) && !decimalFormat.isParseBigDecimal()) {
decimalFormat.setParseBigDecimal(true);
resetBigDecimal = true;
}
}
try {
Number number = numberFormat.parse(trimAllWhitespace(text));
return convertNumberToTargetClass(number, targetClass);
}
catch (ParseException ex) {
throw new IllegalArgumentException("Could not parse number: " + ex.getMessage());
}
finally {
if (resetBigDecimal) {
decimalFormat.setParseBigDecimal(false);
}
}
}
else {
return parseNumber(text, targetClass);
}
}
private static boolean isHexNumber(String value) {
int index = (value.startsWith("-") ? 1 : 0);
return (value.startsWith("0x", index) || value.startsWith("0X", index) || value.startsWith("#", index));
}
private static BigInteger decodeBigInteger(String value) {
int radix = 10;
int index = 0;
boolean negative = false;
// Handle minus sign, if present.
if (value.startsWith("-")) {
negative = true;
index++;
}
// Handle radix specifier, if present.
if (value.startsWith("0x", index) || value.startsWith("0X", index)) {
index += 2;
radix = 16;
}
else if (value.startsWith("#", index)) {
index++;
radix = 16;
}
else if (value.startsWith("0", index) && value.length() > 1 + index) {
index++;
radix = 8;
}
BigInteger result = new BigInteger(value.substring(index), radix);
return (negative ? result.negate() : result);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy