@Validate
@SuppressWarnings("unchecked")
public static <T> T changeType(@NotNull final Object value, @NotNull final Class<T> targetType)
throws InstantiationException, IllegalAccessException
{
val sourceType = value.getClass();
// check that we're not working with incompatible types
if (sourceType.isAnnotation() || targetType.isAnnotation())
throw new IllegalArgumentException("This conversion process does not support annotations.");
if (sourceType.isArray() || targetType.isArray())
throw new IllegalArgumentException("This conversion process does not support arrays.");
// handle conversion to String
if (targetType.equals(String.class))
return (T) value.toString();
// handle parsing from String
if (sourceType.equals(String.class))
return (T) changeTypeParseFromString(value, targetType);
// handle simple casting scenario
if (sourceType.isAssignableFrom(targetType))
return targetType.cast(value);
// handle number conversion
if (value instanceof Number)
return (T) changeTypeFromNumber(value, targetType);
// handle primitive conversion
PrimitiveType primitiveType = ReflectionUtils.getPrimitiveType(sourceType);
if (primitiveType != PrimitiveType.NotPrimitive)
return (T) changeTypeFromPrimitive(value, primitiveType, targetType);
// handle number-like Character and Boolean conversion (these don't implement Number)
if (value instanceof Character)
return (T) changeTypeFromCharacter(value, targetType);
if (value instanceof Boolean)
return (T) changeTypeFromBoolean(value, targetType);
// all attempts have failed
throw new IllegalArgumentException("The provided object of type '" + sourceType.getSimpleName() + "' could not be converted to '"
+ targetType.getSimpleName());
}