package com.cedarsoftware.util;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.Date;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
/**
* Handy conversion utilities
*
* @author John DeRegnaucourt (john@cedarsoftware.com)
* <br>
* Copyright (c) Cedar Software LLC
* <br><br>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <br><br>
* http://www.apache.org/licenses/LICENSE-2.0
* <br><br>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
public final class Converter
{
private static final Byte BYTE_ZERO = (byte)0;
private static final Byte BYTE_ONE = (byte)1;
private static final Short SHORT_ZERO = (short)0;
private static final Short SHORT_ONE = (short)1;
private static final Integer INTEGER_ZERO = 0;
private static final Integer INTEGER_ONE = 1;
private static final Long LONG_ZERO = 0L;
private static final Long LONG_ONE = 1L;
private static final Float FLOAT_ZERO = 0.0f;
private static final Float FLOAT_ONE = 1.0f;
private static final Double DOUBLE_ZERO = 0.0d;
private static final Double DOUBLE_ONE = 1.0d;
/**
* Static utility class.
*/
private Converter() {
}
/**
* Turn the passed in value to the class indicated. This will allow, for
* example, a String value to be passed in and have it coerced to a Long.
* <pre>
* Examples:
* Long x = convert("35", Long.class);
* Date d = convert("2015/01/01", Date.class)
* int y = convert(45.0, int.class)
* String date = convert(date, String.class)
* String date = convert(calendar, String.class)
* Short t = convert(true, short.class); // returns (short) 1 or (short) 0
* Long date = convert(calendar, long.class); // get calendar's time into long
* </pre>
* @param fromInstance A value used to create the targetType, even though it may
* not (most likely will not) be the same data type as the targetType
* @param toType Class which indicates the targeted (final) data type.
* Please note that in addition to the 8 Java primitives, the targeted class
* can also be Date.class, String.class, BigInteger.class, and BigDecimal.class.
* The primitive class can be either primitive class or primitive wrapper class,
* however, the returned value will always [obviously] be a primitive wrapper.
* @return An instanceof targetType class, based upon the value passed in.
*/
public static Object convert(Object fromInstance, Class toType)
{
if (toType == null)
{
throw new IllegalArgumentException("Type cannot be null in Converter.convert(value, type)");
}
if (toType == String.class)
{
if (fromInstance == null || fromInstance instanceof String)
{
return fromInstance;
}
else if (fromInstance instanceof BigDecimal)
{
return ((BigDecimal) fromInstance).stripTrailingZeros().toPlainString();
}
else if (fromInstance instanceof Number || fromInstance instanceof Boolean || fromInstance instanceof AtomicBoolean)
{
return fromInstance.toString();
}
else if (fromInstance instanceof Date)
{
return SafeSimpleDateFormat.getDateFormat("yyyy-MM-dd'T'HH:mm:ss").format(fromInstance);
}
else if (fromInstance instanceof Calendar)
{
return SafeSimpleDateFormat.getDateFormat("yyyy-MM-dd'T'HH:mm:ss").format(((Calendar)fromInstance).getTime());
}
else if (fromInstance instanceof Character)
{
return "" + fromInstance;
}
nope(fromInstance, "String");
}
else if (toType == long.class)
{
return fromInstance == null ? 0L : convertLong(fromInstance);
}
else if (toType == Long.class)
{
return fromInstance == null ? null : convertLong(fromInstance);
}
else if (toType == int.class)
{
return fromInstance == null ? 0 : convertInteger(fromInstance);
}
else if (toType == Integer.class)
{
return fromInstance == null ? null : convertInteger(fromInstance);
}
else if (toType == Date.class)
{
if (fromInstance == null)
{
return null;
}
try
{
if (fromInstance instanceof String)
{
return DateUtilities.parseDate(((String) fromInstance).trim());
}
else if (fromInstance instanceof java.sql.Date)
{ // convert from java.sql.Date to java.util.Date
return new Date(((java.sql.Date)fromInstance).getTime());
}
else if (fromInstance instanceof Timestamp)
{
Timestamp timestamp = (Timestamp) fromInstance;
return new Date(timestamp.getTime());
}
else if (fromInstance instanceof Date)
{ // Return a clone, not the same instance because Dates are not immutable
return new Date(((Date)fromInstance).getTime());
}
else if (fromInstance instanceof Calendar)
{
return ((Calendar) fromInstance).getTime();
}
else if (fromInstance instanceof Long)
{
return new Date((Long) fromInstance);
}
else if (fromInstance instanceof AtomicLong)
{
return new Date(((AtomicLong) fromInstance).get());
}
}
catch(Exception e)
{
throw new IllegalArgumentException("value [" + name(fromInstance) + "] could not be converted to a 'Date'", e);
}
nope(fromInstance, "Date");
}
else if (toType == BigDecimal.class)
{
if (fromInstance == null)
{
return null;
}
try
{
if (fromInstance instanceof String)
{
if (StringUtilities.isEmpty((String)fromInstance))
{
return BigDecimal.ZERO;
}
return new BigDecimal(((String) fromInstance).trim());
}
else if (fromInstance instanceof BigDecimal)
{
return fromInstance;
}
else if (fromInstance instanceof BigInteger)
{
return new BigDecimal((BigInteger) fromInstance);
}
else if (fromInstance instanceof Number)
{
return new BigDecimal(((Number) fromInstance).doubleValue());
}
else if (fromInstance instanceof Boolean)
{
return (Boolean) fromInstance ? BigDecimal.ONE : BigDecimal.ZERO;
}
else if (fromInstance instanceof AtomicBoolean)
{
return ((AtomicBoolean) fromInstance).get() ? BigDecimal.ONE : BigDecimal.ZERO;
}
else if (fromInstance instanceof Date)
{
return new BigDecimal(((Date)fromInstance).getTime());
}
else if (fromInstance instanceof Calendar)
{
return new BigDecimal(((Calendar)fromInstance).getTime().getTime());
}
}
catch(Exception e)
{
throw new IllegalArgumentException("value [" + name(fromInstance) + "] could not be converted to a 'BigDecimal'", e);
}
nope(fromInstance, "BigDecimal");
}
else if (toType == BigInteger.class)
{
if (fromInstance == null)
{
return null;
}
try
{
if (fromInstance instanceof String)
{
if (StringUtilities.isEmpty((String)fromInstance))
{
return BigInteger.ZERO;
}
return new BigInteger(((String) fromInstance).trim());
}
else if (fromInstance instanceof BigInteger)
{
return fromInstance;
}
else if (fromInstance instanceof BigDecimal)
{
return ((BigDecimal) fromInstance).toBigInteger();
}
else if (fromInstance instanceof Number)
{
return new BigInteger(Long.toString(((Number) fromInstance).longValue()));
}
else if (fromInstance instanceof Boolean)
{
return (Boolean) fromInstance ? BigInteger.ONE : BigInteger.ZERO;
}
else if (fromInstance instanceof AtomicBoolean)
{
return ((AtomicBoolean) fromInstance).get() ? BigInteger.ONE : BigInteger.ZERO;
}
else if (fromInstance instanceof Date)
{
return new BigInteger(Long.toString(((Date) fromInstance).getTime()));
}
else if (fromInstance instanceof Calendar)
{
return new BigInteger(Long.toString(((Calendar) fromInstance).getTime().getTime()));
}
}
catch(Exception e)
{
throw new IllegalArgumentException("value [" + name(fromInstance) + "] could not be converted to a 'BigInteger'", e);
}
nope(fromInstance, "BigInteger");
}
else if (toType == java.sql.Date.class)
{
if (fromInstance == null)
{
return null;
}
try
{
if (fromInstance instanceof java.sql.Date)
{ // Return a clone of the current date time because java.sql.Date is mutable.
return new java.sql.Date(((java.sql.Date)fromInstance).getTime());
}
else if (fromInstance instanceof Timestamp)
{
Timestamp timestamp = (Timestamp) fromInstance;
return new java.sql.Date(timestamp.getTime());
}
else if (fromInstance instanceof Date)
{ // convert from java.util.Date to java.sql.Date
return new java.sql.Date(((Date)fromInstance).getTime());
}
else if (fromInstance instanceof String)
{
Date date = DateUtilities.parseDate(((String) fromInstance).trim());
return new java.sql.Date(date.getTime());
}
else if (fromInstance instanceof Calendar)
{
return new java.sql.Date(((Calendar) fromInstance).getTime().getTime());
}
else if (fromInstance instanceof Long)
{
return new java.sql.Date((Long) fromInstance);
}
else if (fromInstance instanceof AtomicLong)
{
return new java.sql.Date(((AtomicLong) fromInstance).get());
}
}
catch(Exception e)
{
throw new IllegalArgumentException("value [" + name(fromInstance) + "] could not be converted to a 'java.sql.Date'", e);
}
nope(fromInstance, "java.sql.Date");
}
else if (toType == Timestamp.class)
{
if (fromInstance == null)
{
return null;
}
try
{
if (fromInstance instanceof java.sql.Date)
{ // convert from java.sql.Date to java.util.Date
return new Timestamp(((java.sql.Date)fromInstance).getTime());
}
else if (fromInstance instanceof Timestamp)
{ // return a clone of the Timestamp because it is mutable
return new Timestamp(((Timestamp)fromInstance).getTime());
}
else if (fromInstance instanceof Date)
{
return new Timestamp(((Date) fromInstance).getTime());
}
else if (fromInstance instanceof String)
{
Date date = DateUtilities.parseDate(((String) fromInstance).trim());
return new Timestamp(date.getTime());
}
else if (fromInstance instanceof Calendar)
{
return new Timestamp(((Calendar) fromInstance).getTime().getTime());
}
else if (fromInstance instanceof Long)
{
return new Timestamp((Long) fromInstance);
}
else if (fromInstance instanceof AtomicLong)
{
return new Timestamp(((AtomicLong) fromInstance).get());
}
}
catch(Exception e)
{
throw new IllegalArgumentException("value [" + name(fromInstance) + "] could not be converted to a 'Timestamp'", e);
}
nope(fromInstance, "Timestamp");
}
else if (toType == AtomicInteger.class)
{
if (fromInstance == null)
{
return null;
}
try
{
if (fromInstance instanceof AtomicInteger)
{ // return a new instance because AtomicInteger is mutable
return new AtomicInteger(((AtomicInteger)fromInstance).get());
}
else if (fromInstance instanceof String)
{
if (StringUtilities.isEmpty((String)fromInstance))
{
return new AtomicInteger(0);
}
return new AtomicInteger(Integer.valueOf(((String) fromInstance).trim()));
}
else if (fromInstance instanceof Number)
{
return new AtomicInteger(((Number)fromInstance).intValue());
}
else if (fromInstance instanceof Boolean)
{
return (Boolean) fromInstance ? new AtomicInteger(1) : new AtomicInteger(0);
}
else if (fromInstance instanceof AtomicBoolean)
{
return ((AtomicBoolean) fromInstance).get() ? new AtomicInteger(1) : new AtomicInteger(0);
}
}
catch(Exception e)
{
throw new IllegalArgumentException("value [" + name(fromInstance) + "] could not be converted to an 'AtomicInteger'", e);
}
nope(fromInstance, "AtomicInteger");
}
else if (toType == AtomicLong.class)
{
if (fromInstance == null)
{
return null;
}
try
{
if (fromInstance instanceof String)
{
if (StringUtilities.isEmpty((String)fromInstance))
{
return new AtomicLong(0);
}
return new AtomicLong(Long.valueOf(((String) fromInstance).trim()));
}
else if (fromInstance instanceof AtomicLong)
{ // return a clone of the AtomicLong because it is mutable
return new AtomicLong(((AtomicLong)fromInstance).get());
}
else if (fromInstance instanceof Number)
{
return new AtomicLong(((Number)fromInstance).longValue());
}
else if (fromInstance instanceof Date)
{
return new AtomicLong(((Date)fromInstance).getTime());
}
else if (fromInstance instanceof Boolean)
{
return (Boolean) fromInstance ? new AtomicLong(1L) : new AtomicLong(0L);
}
else if (fromInstance instanceof AtomicBoolean)
{
return ((AtomicBoolean) fromInstance).get() ? new AtomicLong(1L) : new AtomicLong(0L);
}
else if (fromInstance instanceof Calendar)
{
return new AtomicLong(((Calendar)fromInstance).getTime().getTime());
}
}
catch(Exception e)
{
throw new IllegalArgumentException("value [" + name(fromInstance) + "] could not be converted to an 'AtomicLong'", e);
}
nope(fromInstance, "AtomicLong");
}
else if (toType == AtomicBoolean.class)
{
if (fromInstance == null)
{
return null;
}
else if (fromInstance instanceof String)
{
if (StringUtilities.isEmpty((String)fromInstance))
{
return new AtomicBoolean(false);
}
String value = (String) fromInstance;
return new AtomicBoolean("true".equalsIgnoreCase(value));
}
else if (fromInstance instanceof AtomicBoolean)
{ // return a clone of the AtomicBoolean because it is mutable
return new AtomicBoolean(((AtomicBoolean)fromInstance).get());
}
else if (fromInstance instanceof Boolean)
{
return new AtomicBoolean((Boolean) fromInstance);
}
else if (fromInstance instanceof Number)
{
return new AtomicBoolean(((Number)fromInstance).longValue() != 0);
}
nope(fromInstance, "AtomicBoolean");
}
else if (toType == boolean.class)
{
return fromInstance == null ? Boolean.FALSE : convertBoolean(fromInstance);
}
else if (toType == Boolean.class)
{
return fromInstance == null ? null : convertBoolean(fromInstance);
}
else if (toType == double.class)
{
return fromInstance == null ? DOUBLE_ZERO : convertDouble(fromInstance);
}
else if (toType == Double.class)
{
return fromInstance == null ? null : convertDouble(fromInstance);
}
else if (toType == byte.class)
{
return fromInstance == null ? BYTE_ZERO : convertByte(fromInstance);
}
else if (toType == Byte.class)
{
return fromInstance == null ? null : convertByte(fromInstance);
}
else if (toType == float.class)
{
return fromInstance == null ? FLOAT_ZERO : convertFloat(fromInstance);
}
else if (toType == Float.class)
{
return fromInstance == null ? null : convertFloat(fromInstance);
}
else if (toType == short.class)
{
return fromInstance == null ? SHORT_ZERO : convertShort(fromInstance);
}
else if (toType == Short.class)
{
return fromInstance == null ? null : convertShort(fromInstance);
}
throw new IllegalArgumentException("Unsupported type '" + toType.getName() + "' for conversion");
}
private static Object convertByte(Object fromInstance)
{
try
{
if (fromInstance instanceof String)
{
if (StringUtilities.isEmpty((String)fromInstance))
{
return BYTE_ZERO;
}
return Byte.valueOf(((String) fromInstance).trim());
}
else if (fromInstance instanceof Byte)
{
return fromInstance;
}
else if (fromInstance instanceof Number)
{
return ((Number)fromInstance).byteValue();
}
else if (fromInstance instanceof Boolean)
{
return (Boolean) fromInstance ? BYTE_ONE : BYTE_ZERO;
}
else if (fromInstance instanceof AtomicBoolean)
{
return ((AtomicBoolean)fromInstance).get() ? BYTE_ONE : BYTE_ZERO;
}
}
catch(Exception e)
{
throw new IllegalArgumentException("value [" + name(fromInstance) + "] could not be converted to a 'Byte'", e);
}
return nope(fromInstance, "Byte");
}
private static Object convertShort(Object fromInstance)
{
try
{
if (fromInstance instanceof String)
{
if (StringUtilities.isEmpty((String)fromInstance))
{
return SHORT_ZERO;
}
return Short.valueOf(((String) fromInstance).trim());
}
else if (fromInstance instanceof Short)
{
return fromInstance;
}
else if (fromInstance instanceof Number)
{
return ((Number)fromInstance).shortValue();
}
else if (fromInstance instanceof Boolean)
{
return (Boolean) fromInstance ? SHORT_ONE : SHORT_ZERO;
}
else if (fromInstance instanceof AtomicBoolean)
{
return ((AtomicBoolean) fromInstance).get() ? SHORT_ONE : SHORT_ZERO;
}
}
catch(Exception e)
{
throw new IllegalArgumentException("value [" + name(fromInstance) + "] could not be converted to a 'Short'", e);
}
return nope(fromInstance, "Short");
}
private static Object convertInteger(Object fromInstance)
{
try
{
if (fromInstance instanceof Integer)
{
return fromInstance;
}
else if (fromInstance instanceof Number)
{
return ((Number)fromInstance).intValue();
}
else if (fromInstance instanceof String)
{
if (StringUtilities.isEmpty((String)fromInstance))
{
return INTEGER_ZERO;
}
return Integer.valueOf(((String) fromInstance).trim());
}
else if (fromInstance instanceof Boolean)
{
return (Boolean) fromInstance ? INTEGER_ONE : INTEGER_ZERO;
}
else if (fromInstance instanceof AtomicBoolean)
{
return ((AtomicBoolean) fromInstance).get() ? INTEGER_ONE : INTEGER_ZERO;
}
}
catch(Exception e)
{
throw new IllegalArgumentException("value [" + name(fromInstance) + "] could not be converted to an 'Integer'", e);
}
return nope(fromInstance, "Integer");
}
private static Object convertLong(Object fromInstance)
{
try
{
if (fromInstance instanceof Long)
{
return fromInstance;
}
else if (fromInstance instanceof Number)
{
return ((Number)fromInstance).longValue();
}
else if (fromInstance instanceof String)
{
if (StringUtilities.isEmpty((String)fromInstance))
{
return LONG_ZERO;
}
return Long.valueOf(((String) fromInstance).trim());
}
else if (fromInstance instanceof Date)
{
return ((Date)fromInstance).getTime();
}
else if (fromInstance instanceof Boolean)
{
return (Boolean) fromInstance ? LONG_ONE : LONG_ZERO;
}
else if (fromInstance instanceof AtomicBoolean)
{
return ((AtomicBoolean) fromInstance).get() ? LONG_ONE : LONG_ZERO;
}
else if (fromInstance instanceof Calendar)
{
return ((Calendar)fromInstance).getTime().getTime();
}
}
catch(Exception e)
{
throw new IllegalArgumentException("value [" + name(fromInstance) + "] could not be converted to a 'Long'", e);
}
return nope(fromInstance, "Long");
}
private static Object convertFloat(Object fromInstance)
{
try
{
if (fromInstance instanceof String)
{
if (StringUtilities.isEmpty((String)fromInstance))
{
return FLOAT_ZERO;
}
return Float.valueOf(((String) fromInstance).trim());
}
else if (fromInstance instanceof Float)
{
return fromInstance;
}
else if (fromInstance instanceof Number)
{
return ((Number)fromInstance).floatValue();
}
else if (fromInstance instanceof Boolean)
{
return (Boolean) fromInstance ? FLOAT_ONE : FLOAT_ZERO;
}
else if (fromInstance instanceof AtomicBoolean)
{
return ((AtomicBoolean) fromInstance).get() ? FLOAT_ONE : FLOAT_ZERO;
}
}
catch(Exception e)
{
throw new IllegalArgumentException("value [" + name(fromInstance) + "] could not be converted to a 'Float'", e);
}
return nope(fromInstance, "Float");
}
private static Object convertDouble(Object fromInstance)
{
try
{
if (fromInstance instanceof String)
{
if (StringUtilities.isEmpty((String)fromInstance))
{
return DOUBLE_ZERO;
}
return Double.valueOf(((String) fromInstance).trim());
}
else if (fromInstance instanceof Double)
{
return fromInstance;
}
else if (fromInstance instanceof Number)
{
return ((Number)fromInstance).doubleValue();
}
else if (fromInstance instanceof Boolean)
{
return (Boolean) fromInstance ? DOUBLE_ONE : DOUBLE_ZERO;
}
else if (fromInstance instanceof AtomicBoolean)
{
return ((AtomicBoolean) fromInstance).get() ? DOUBLE_ONE : DOUBLE_ZERO;
}
}
catch(Exception e)
{
throw new IllegalArgumentException("value [" + name(fromInstance) + "] could not be converted to a 'Double'", e);
}
return nope(fromInstance, "Double");
}
private static Object convertBoolean(Object fromInstance)
{
if (fromInstance instanceof Boolean)
{
return fromInstance;
}
else if (fromInstance instanceof Number)
{
return ((Number)fromInstance).longValue() != 0;
}
else if (fromInstance instanceof String)
{
if (StringUtilities.isEmpty((String)fromInstance))
{
return Boolean.FALSE;
}
String value = (String) fromInstance;
return "true".equalsIgnoreCase(value) ? Boolean.TRUE : Boolean.FALSE;
}
else if (fromInstance instanceof AtomicBoolean)
{
return ((AtomicBoolean) fromInstance).get();
}
return nope(fromInstance, "Boolean");
}
private static String nope(Object fromInstance, String targetType)
{
throw new IllegalArgumentException("Unsupported value type [" + name(fromInstance) + "] attempting to convert to '" + targetType + "'");
}
private static String name(Object fromInstance)
{
return fromInstance.getClass().getName() + " (" + fromInstance.toString() + ")";
}
}