package io.ebeaninternal.server.core; import io.ebeaninternal.server.type.ScalarTypeUUIDBinary; import java.io.Serializable; import java.math.BigDecimal; import java.math.BigInteger; import java.sql.Timestamp; import java.sql.Types; import java.util.Calendar; import java.util.UUID; /** * Default implementation of TypeConverter. * <p> * Converts objects to the required type if required. * </p> */ public final class BasicTypeConverter implements Serializable { private static final long serialVersionUID = 7691463236204070311L; /** * Type code for java.util.Calendar. */ public static final int UTIL_CALENDAR = -999998986; /** * Type code for java.util.Date. */ public static final int UTIL_DATE = -999998988; private BasicTypeConverter() { } /** * Convert the Object to the required data type. * * @param value the Object value * @param toDataType the dataType as per java.sql.Types. */ public static Object convert(Object value, int toDataType) { try { switch (toDataType) { case UTIL_DATE: { return toUtilDate(value); } case UTIL_CALENDAR: { return toCalendar(value); } case Types.BIGINT: { return toLong(value); } case Types.INTEGER: { return toInteger(value); } case Types.BIT: { return toBoolean(value); } case Types.TINYINT: { return toByte(value); } case Types.SMALLINT: { return toShort(value); } case Types.NUMERIC: { return toBigDecimal(value); } case Types.DECIMAL: { return toBigDecimal(value); } case Types.REAL: { return toFloat(value); } case Types.DOUBLE: { return toDouble(value); } case Types.FLOAT: { return toDouble(value); } case Types.BOOLEAN: { return toBoolean(value); } case Types.TIMESTAMP: { return toTimestamp(value); } case Types.DATE: { return toDate(value); } case Types.VARCHAR: { return toString(value); } case Types.CHAR: { return toString(value); } case Types.OTHER: { return value; } case Types.JAVA_OBJECT: { return value; } case Types.BINARY: case Types.LONGVARBINARY: case Types.BLOB: { return value; } case Types.LONGVARCHAR: case Types.CLOB: { return value; } default: { String msg = "Unhandled data type [" + toDataType + "] converting [" + value + "]"; throw new RuntimeException(msg); } } } catch (ClassCastException e) { String m = "ClassCastException converting to data type [" + toDataType + "] value [" + value + "]"; throw new RuntimeException(m); } } /** * Convert the value to a String. */ public static String toString(Object value) { if (value == null) { return null; } if (value instanceof String) { return (String) value; } if (value instanceof char[]) { return String.valueOf((char[]) value); } return value.toString(); } /** * Convert the value to a Boolean with an explicit String true value. */ public static Boolean toBoolean(Object value, String dbTrueValue) { if (value == null) { return null; } if (value instanceof Boolean) { return (Boolean) value; } if (value instanceof Number) { return ((Number) value).intValue() == 1; } String s = value.toString(); return s.equalsIgnoreCase(dbTrueValue); } /** * Convert the value to a Boolean. Can be a Boolean or the string values * "true" or "false". */ public static Boolean toBoolean(Object value) { if (value == null) { return null; } if (value instanceof Boolean) { return (Boolean) value; } return Boolean.valueOf(value.toString()); } /** * Convert the value to a UUID. */ public static UUID toUUID(Object value) { if (value == null) { return null; } if (value instanceof UUID) { return (UUID) value; } if (value instanceof String) { return UUID.fromString((String) value); } if (value instanceof byte[]) { return ScalarTypeUUIDBinary.convertFromBytes((byte[]) value); } return UUID.fromString(value.toString()); } /** * convert the passed in object to a BigDecimal. It should be another * numeric type. */ public static BigDecimal toBigDecimal(Object value) { if (value == null) { return null; } if (value instanceof BigDecimal) { return (BigDecimal) value; } return new BigDecimal(value.toString()); } public static Float toFloat(Object value) { if (value == null) { return null; } if (value instanceof Float) { return (Float) value; } if (value instanceof Number) { return ((Number) value).floatValue(); } return Float.valueOf(value.toString()); } public static Short toShort(Object value) { if (value == null) { return null; } if (value instanceof Short) { return (Short) value; } if (value instanceof Number) { return ((Number) value).shortValue(); } return Short.valueOf(value.toString()); } public static Byte toByte(Object value) { if (value == null) { return null; } if (value instanceof Byte) { return (Byte) value; } return Byte.valueOf(value.toString()); } /** * convert the passed in object to a Integer. It should be another numeric * type. */ public static Integer toInteger(Object value) { if (value == null) { return null; } if (value instanceof Integer) { return (Integer) value; } if (value instanceof Number) { return ((Number) value).intValue(); } return Integer.valueOf(value.toString()); } /** * Convert the object to a Long. It should be another numeric type. */ public static Long toLong(Object value) { if (value == null) { return null; } if (value instanceof Long) { return (Long) value; } if (value instanceof String) { return Long.valueOf((String) value); } if (value instanceof Number) { return ((Number) value).longValue(); } if (value instanceof java.util.Date) { return ((java.util.Date) value).getTime(); } if (value instanceof Calendar) { return ((Calendar) value).getTime().getTime(); } return Long.valueOf(value.toString()); } public static BigInteger toMathBigInteger(Object value) { if (value == null) { return null; } if (value instanceof BigInteger) { return (BigInteger) value; } return new BigInteger(value.toString()); } /** * Convert the object to a Double. It should be another numberic type. */ public static Double toDouble(Object value) { if (value == null) { return null; } if (value instanceof Double) { return (Double) value; } if (value instanceof Number) { return ((Number) value).doubleValue(); } return Double.valueOf(value.toString()); } /** * convert the passed in object to a Timestamp. It is expected to be a * java.sql.Date really. */ public static Timestamp toTimestamp(Object value) { if (value == null) { return null; } if (value instanceof Timestamp) { return (Timestamp) value; } else if (value instanceof java.util.Date) { // no nanos here... so hopefully ok return new Timestamp(((java.util.Date) value).getTime()); } else if (value instanceof Calendar) { return new Timestamp(((Calendar) value).getTime().getTime()); } else if (value instanceof String) { return Timestamp.valueOf((String) value); } else if (value instanceof Number) { return new Timestamp(((Number) value).longValue()); } else { String msg = "Unable to convert [" + value.getClass().getName() + "] into a Timestamp."; throw new RuntimeException(msg); } } public static java.sql.Time toTime(Object value) { if (value == null) { return null; } if (value instanceof java.sql.Time) { return (java.sql.Time) value; } else if (value instanceof String) { return java.sql.Time.valueOf((String) value); } else { String m = "Unable to convert [" + value.getClass().getName() + "] into a java.sql.Date."; throw new RuntimeException(m); } } /** * convert the passed in object to a java sql Date. */ public static java.sql.Date toDate(Object value) { if (value == null) { return null; } if (value instanceof java.sql.Date) { return (java.sql.Date) value; } else if (value instanceof java.util.Date) { return new java.sql.Date(((java.util.Date) value).getTime()); } else if (value instanceof Calendar) { return new java.sql.Date(((Calendar) value).getTime().getTime()); } else if (value instanceof String) { return java.sql.Date.valueOf((String) value); } else if (value instanceof Number) { return new java.sql.Date(((Number) value).longValue()); } else { String m = "Unable to convert [" + value.getClass().getName() + "] into a java.sql.Date."; throw new RuntimeException(m); } } /** * convert the passed in object to a java sql Date. */ public static java.util.Date toUtilDate(Object value) { if (value == null) { return null; } if (value instanceof java.sql.Timestamp) { // loss of nanos precision return new java.util.Date(((java.sql.Timestamp) value).getTime()); } // DEVNOTE: strictly speaking do I need to convert a java.sql.Date to // java.util.Date? equals() is symmetrical so perhaps this is not // really required? if (value instanceof java.sql.Date) { return new java.util.Date(((java.sql.Date) value).getTime()); } if (value instanceof java.util.Date) { return (java.util.Date) value; } else if (value instanceof Calendar) { return ((Calendar) value).getTime(); } else if (value instanceof String) { return new java.util.Date(Timestamp.valueOf((String) value).getTime()); } else if (value instanceof Number) { return new java.util.Date(((Number) value).longValue()); } else { throw new RuntimeException("Unable to convert [" + value.getClass().getName() + "] into a java.util.Date"); } } /** * convert the passed in object to a java sql Date. */ public static Calendar toCalendar(Object value) { if (value == null) { return null; } if (value instanceof Calendar) { return (Calendar) value; } else if (value instanceof java.util.Date) { java.util.Date date = ((java.util.Date) value); return toCalendarFromDate(date); } else if (value instanceof String) { java.util.Date date = toUtilDate(value); return toCalendarFromDate(date); } else if (value instanceof Number) { long timeMillis = ((Number) value).longValue(); java.util.Date date = new java.util.Date(timeMillis); return toCalendarFromDate(date); } else { String m = "Unable to convert [" + value.getClass().getName() + "] into a java.util.Date"; throw new RuntimeException(m); } } private static Calendar toCalendarFromDate(java.util.Date date) { Calendar cal = Calendar.getInstance(); cal.setTime(date); return cal; } }