Files
matrix/cygnus-onprem-db/src/main/java/com/cygnus/db/ValueConverter.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;
}
}