Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@
public class BigDecimalValidator extends AbstractNumberValidator {

private static final long serialVersionUID = -670320911490506772L;

private static final BigDecimalValidator VALIDATOR = new BigDecimalValidator();

/**
Expand All @@ -88,6 +87,23 @@ public static BigDecimalValidator getInstance() {
return VALIDATOR;
}

private static boolean isFinite(final Number value) {
if (value instanceof Double) {
return Double.isFinite((Double) value);
}
if (value instanceof Float) {
return Float.isFinite((Float) value);
}
return true;
}

private static BigDecimal toBigDecimal(final Object value) {
if (value instanceof Long) {
return BigDecimal.valueOf(((Long) value).longValue());
}
return value instanceof BigDecimal ? (BigDecimal) value : new BigDecimal(value.toString());
}

/**
* Constructs a <em>strict</em> instance.
*/
Expand Down Expand Up @@ -123,6 +139,17 @@ protected BigDecimalValidator(final boolean strict, final int formatType, final
super(strict, formatType, allowFractions);
}

/**
* Compares two values as BigDecimals.
*
* @param value1 {@code BigDecimal} to compare.
* @param value2 {@code BigDecimal} to which {@code value1} is to be compared.
* @return -1, 0, or 1 as this {@code BigDecimal} is numerically less than, equal to, or greater than {@code val}.
*/
private int compareTo(final Number value1, final Number value2) {
return toBigDecimal(value1).compareTo(toBigDecimal(value2));
}

/**
* Tests if the value is within a specified range.
*
Expand All @@ -146,6 +173,24 @@ public boolean maxValue(final BigDecimal value, final double max) {
return Double.isFinite(max) ? compareTo(value, max) <= 0 : value.doubleValue() <= max;
}

/**
* Tests if the value is less than or equal to a maximum, comparing the exact values.
*
* <p>
* This overrides the {@link Number} overload inherited from the superclass, which narrows the value to a {@code double} before comparing and so loses
* precision for a {@code BigDecimal} that differs from the bound only beyond double precision. A non-finite {@link Double} or {@link Float} operand keeps
* the {@code doubleValue()} comparison so the documented infinity behaviour is unchanged.
* </p>
*
* @param value The value validation is being performed on.
* @param max The maximum value.
* @return {@code true} if the value is less than or equal to the maximum.
*/
@Override
public boolean maxValue(final Number value, final Number max) {
return isFinite(value) && isFinite(max) ? compareTo(value, max) <= 0 : value.doubleValue() <= max.doubleValue();
}

/**
* Tests if the value is greater than or equal to a minimum.
*
Expand All @@ -157,6 +202,24 @@ public boolean minValue(final BigDecimal value, final double min) {
return Double.isFinite(min) ? compareTo(value, min) >= 0 : value.doubleValue() >= min;
}

/**
* Tests if the value is greater than or equal to a minimum, comparing the exact values.
*
* <p>
* This overrides the {@link Number} overload inherited from the superclass, which narrows the value to a {@code double} before comparing and so loses
* precision for a {@code BigDecimal} that differs from the bound only beyond double precision. A non-finite {@link Double} or {@link Float} operand keeps
* the {@code doubleValue()} comparison so the documented infinity behaviour is unchanged.
* </p>
*
* @param value The value validation is being performed on.
* @param min The minimum value.
* @return {@code true} if the value is greater than or equal to the minimum.
*/
@Override
public boolean minValue(final Number value, final Number min) {
return isFinite(value) && isFinite(min) ? compareTo(value, min) >= 0 : value.doubleValue() >= min.doubleValue();
}

/**
* Converts the parsed value to a {@code BigDecimal}.
*
Expand All @@ -166,12 +229,7 @@ public boolean minValue(final BigDecimal value, final double min) {
*/
@Override
protected Object processParsedValue(final Object value, final Format formatter) {
BigDecimal decimal;
if (value instanceof Long) {
decimal = BigDecimal.valueOf(((Long) value).longValue());
} else {
decimal = new BigDecimal(value.toString());
}
BigDecimal decimal = toBigDecimal(value);
final int scale = determineScale((NumberFormat) formatter);
if (scale >= 0) {
decimal = decimal.setScale(scale, BigDecimal.ROUND_DOWN);
Expand Down
Loading
Loading