ToLongConversion.java
package org.klojang.convert;
import static org.klojang.convert.NumberMethods.*;
import static org.klojang.convert.TypeConversionException.inputTypeNotSupported;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Predicate;
class ToLongConversion {
private static final Map<Class<?>, Predicate<Number>> fitsIntoLong = Map.of(
BigDecimal.class, ToLongConversion::testBigDecimal,
BigInteger.class, ToLongConversion::testBigInteger,
//Double.class, n -> n.doubleValue() == n.longValue(),
Double.class, ToLongConversion::testDouble,
//Float.class, n -> n.floatValue() == n.longValue(),
Float.class, ToLongConversion::testFloat,
Long.class, yes(),
AtomicLong.class, yes(),
Integer.class, yes(),
AtomicInteger.class, yes(),
Short.class, yes(),
Byte.class, yes()
);
static boolean isLossless(Number n) {
Predicate<Number> tester = fitsIntoLong.get(n.getClass());
if (tester != null) {
return tester.test(n);
}
throw inputTypeNotSupported(n, Long.class);
}
static Long exec(Number n) {
if (isLossless(n)) {
return n.longValue();
}
throw new TypeConversionException(n, Long.class);
}
private static boolean testBigDecimal(Number n) {
BigDecimal bd = (BigDecimal) n;
return isRound(bd)
&& bd.compareTo(MIN_LONG_BD) >= 0
&& bd.compareTo(MAX_LONG_BD) <= 0;
}
private static boolean testBigInteger(Number n) {
BigInteger bi = (BigInteger) n;
return bi.compareTo(MIN_LONG_BI) >= 0
&& bi.compareTo(MAX_LONG_BI) <= 0;
}
private static boolean testDouble(Number n) {
Double d = (Double) n;
return isRound(d)
&& d >= (double) Long.MIN_VALUE
&& d <= (double) Long.MAX_VALUE;
}
private static boolean testFloat(Number n) {
Float f = (Float) n;
return isRound(f)
&& f >= (float) Long.MIN_VALUE
&& f <= (float) Long.MAX_VALUE;
}
}