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 convert(Object value, Class 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) 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; } }