80 lines
3.6 KiB
Java
80 lines
3.6 KiB
Java
package com.cygnus.db;
|
|
|
|
import java.math.BigDecimal;
|
|
import java.sql.Date;
|
|
import java.sql.Timestamp;
|
|
import java.time.Instant;
|
|
import java.time.LocalDate;
|
|
import java.time.LocalDateTime;
|
|
import java.time.OffsetDateTime;
|
|
import java.util.UUID;
|
|
|
|
final class ValueConverter {
|
|
private ValueConverter() {}
|
|
|
|
@SuppressWarnings({"unchecked", "rawtypes"})
|
|
static <T> T convert(Object value, Class<T> target) {
|
|
if (value == null) return target.isPrimitive() ? (T) primitiveDefault(target) : null;
|
|
Class<?> boxed = box(target);
|
|
if (boxed.isInstance(value)) return (T) value;
|
|
if (boxed == String.class) return (T) value.toString();
|
|
if (Number.class.isAssignableFrom(boxed) && value instanceof Number number) {
|
|
return (T) number(number, boxed);
|
|
}
|
|
if (boxed == Boolean.class) {
|
|
if (value instanceof Number number) return (T) Boolean.valueOf(number.intValue() != 0);
|
|
return (T) Boolean.valueOf(value.toString());
|
|
}
|
|
if (boxed == Character.class) {
|
|
String text = value.toString();
|
|
if (text.isEmpty()) throw new IllegalArgumentException("Cannot convert an empty value to char");
|
|
return (T) Character.valueOf(text.charAt(0));
|
|
}
|
|
if (boxed == UUID.class) return (T) UUID.fromString(value.toString());
|
|
if (boxed == LocalDate.class && value instanceof Date date) return (T) date.toLocalDate();
|
|
if (boxed == LocalDateTime.class && value instanceof Timestamp timestamp) return (T) timestamp.toLocalDateTime();
|
|
if (boxed == Instant.class && value instanceof Timestamp timestamp) return (T) timestamp.toInstant();
|
|
if (boxed == OffsetDateTime.class && value instanceof OffsetDateTime dateTime) return (T) dateTime;
|
|
if (boxed.isEnum()) return (T) Enum.valueOf((Class<Enum>) boxed, value.toString());
|
|
throw new DatabaseExecutionException(0,
|
|
"Cannot convert " + value.getClass().getName() + " to " + target.getName(), null);
|
|
}
|
|
|
|
private static Object number(Number value, Class<?> target) {
|
|
if (target == Integer.class) return value.intValue();
|
|
if (target == Long.class) return value.longValue();
|
|
if (target == Double.class) return value.doubleValue();
|
|
if (target == Float.class) return value.floatValue();
|
|
if (target == Short.class) return value.shortValue();
|
|
if (target == Byte.class) return value.byteValue();
|
|
if (target == BigDecimal.class) return value instanceof BigDecimal decimal
|
|
? decimal : new BigDecimal(value.toString());
|
|
return value;
|
|
}
|
|
|
|
private static Class<?> box(Class<?> type) {
|
|
if (!type.isPrimitive()) return type;
|
|
if (type == int.class) return Integer.class;
|
|
if (type == long.class) return Long.class;
|
|
if (type == double.class) return Double.class;
|
|
if (type == float.class) return Float.class;
|
|
if (type == short.class) return Short.class;
|
|
if (type == byte.class) return Byte.class;
|
|
if (type == boolean.class) return Boolean.class;
|
|
if (type == char.class) return Character.class;
|
|
return type;
|
|
}
|
|
|
|
private static Object primitiveDefault(Class<?> type) {
|
|
if (type == boolean.class) return false;
|
|
if (type == char.class) return '\0';
|
|
if (type == byte.class) return (byte) 0;
|
|
if (type == short.class) return (short) 0;
|
|
if (type == int.class) return 0;
|
|
if (type == long.class) return 0L;
|
|
if (type == float.class) return 0F;
|
|
if (type == double.class) return 0D;
|
|
return null;
|
|
}
|
|
}
|