package org.handwerkszeug.common.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.MalformedURLException;
import java.net.URL;
import java.sql.Time;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;
/**
* ConverterUtil is an utility class that converts object.
*
* @author shot
* @author taichi
*/
public class ConverterUtil {
static final Logger LOG = Logger.getLogger(ConverterUtil.class.getName());
public static final Pattern YES_PATTERN = Pattern.compile("(yes|true|y|1)",
Pattern.CASE_INSENSITIVE);
private static Map<Class<?>, Converter<?>> map = new HashMap<Class<?>, Converter<?>>(
19);
private static void init() {
map.put(BigDecimal.class, BIGDECIMAL_CONVERTER);
map.put(BigInteger.class, BIGINTEGER_CONVERTER);
map.put(Byte.class, BYTE_CONVERTER);
map.put(byte[].class, BINARY_CONVERTER);
map.put(Boolean.class, BOOLEAN_CONVERTER);
map.put(Calendar.class, CALENDAR_CONVERTER);
map.put(java.util.Date.class, DATE_CONVERTER);
map.put(Double.class, DOUBLE_CONVERTER);
map.put(Float.class, FLOAT_CONVERTER);
map.put(Integer.class, INTEGER_CONVERTER);
map.put(Long.class, LONG_CONVERTER);
map.put(Short.class, SHORT_CONVERTER);
map.put(java.sql.Date.class, SQLDATE_CONVERTER);
map.put(String.class, STRING_CONVERTER);
map.put(Time.class, TIME_CONVERTER);
map.put(Timestamp.class, TIMESTAMP_CONVERTER);
map.put(URL.class, URL_CONVERTER);
map.put(InputStream.class, INPUTSTREAM_CONVERTER);
map.put(Reader.class, READER_CONVERTER);
}
public static <T> T convert(Object target, Class<T> convertClass) {
return convert(target, convertClass, null);
}
@SuppressWarnings("unchecked")
public static <T> T convert(Object target, Class<T> convertClass,
String pattern) {
Converter<T> converter = (Converter<T>) map.get(convertClass);
if (converter == null) {
if (convertClass.isInstance(target)) {
return (T) target;
}
return null;
}
return converter.convert(target, pattern);
}
public static interface Converter<T> {
/**
* convert to T from o. if conversion is failed, return null.
*
* @param o
* @return
* */
T convert(Object o);
/**
* convert to T from o. if conversion is failed, return null.
*
* @param o
* @param pattern
* some of type needly conversion format.
* @return converted object, or null.
*/
T convert(Object o, String pattern);
}
public static final Converter<BigDecimal> BIGDECIMAL_CONVERTER = new Converter<BigDecimal>() {
@Override
public BigDecimal convert(Object o, String pattern) {
if (o == null) {
return null;
} else if (BigDecimal.class.isInstance(o)) {
return (BigDecimal) o;
} else if (o instanceof java.util.Date) {
return new BigDecimal(((java.util.Date) o).getTime());
} else if (Integer.class.isInstance(o)) {
int i = Integer.class.cast(o).intValue();
return new BigDecimal(i);
} else if (Double.class.isInstance(o)) {
double d = Double.class.cast(o).doubleValue();
return new BigDecimal(d);
} else if (Long.class.isInstance(o)) {
long l = Long.class.cast(o).longValue();
return new BigDecimal(l);
} else if (Float.class.isInstance(o)) {
float f = Float.class.cast(o).floatValue();
return new BigDecimal(f);
} else if (Byte.class.isInstance(o)) {
byte b = Byte.class.cast(o).byteValue();
return new BigDecimal(b);
} else if (BigInteger.class.isInstance(o)) {
BigInteger bi = BigInteger.class.cast(o);
return new BigDecimal(bi);
} else if (String.class.isInstance(o)) {
String s = DecimalFormatUtil.normalize(String.class.cast(o));
if (StringUtil.isEmpty(s) == false) {
return new BigDecimal(s);
}
return null;
} else {
return null;
}
}
@Override
public BigDecimal convert(Object o) {
return convert(o, null);
}
};
public static final Converter<BigInteger> BIGINTEGER_CONVERTER = new Converter<BigInteger>() {
@Override
public BigInteger convert(Object o, String pattern) {
if (o == null) {
return null;
} else if (o instanceof BigInteger) {
return (BigInteger) o;
} else if (o instanceof String) {
String s = DecimalFormatUtil.normalize(String.class.cast(o));
if (StringUtil.isEmpty(s) == false) {
return new BigInteger(s);
}
}
return null;
}
@Override
public BigInteger convert(Object o) {
return convert(o, null);
}
};
public static final Converter<Byte> BYTE_CONVERTER = new Converter<Byte>() {
@Override
public Byte convert(Object o) {
return convert(o, null);
}
@Override
public Byte convert(Object o, String pattern) {
if (o == null) {
return null;
} else if (o instanceof Byte) {
return (Byte) o;
} else if (o instanceof Number) {
return new Byte(((Number) o).byteValue());
} else if (o instanceof String) {
String s = DecimalFormatUtil.normalize(String.class.cast(o));
if (StringUtil.isEmpty(s) == false) {
return Byte.valueOf(s);
}
return null;
}
return null;
}
};
public static final Converter<byte[]> BINARY_CONVERTER = new Converter<byte[]>() {
@Override
public byte[] convert(Object o) {
if (o == null) {
return null;
} else if (o instanceof byte[]) {
return (byte[]) o;
} else if (o instanceof String) {
return Base64Util.decode(String.class.cast(o));
}
return null;
}
@Override
public byte[] convert(Object o, String pattern) {
return convert(o);
}
};
public static final Converter<Boolean> BOOLEAN_CONVERTER = new Converter<Boolean>() {
@Override
public Boolean convert(Object o) {
if (o == null) {
return null;
} else if (Boolean.class.isInstance(o)) {
return Boolean.class.cast(o);
} else if (String.class.isInstance(o)) {
String s = String.class.cast(o);
return Boolean.valueOf(YES_PATTERN.matcher(s).matches());
} else if (Number.class.isInstance(o)) {
Number n = Number.class.cast(o);
return Boolean.valueOf(n.intValue() != 0);
}
return null;
}
@Override
public Boolean convert(Object o, String pattern) {
return convert(o);
}
};
public static final Converter<Calendar> CALENDAR_CONVERTER = new Converter<Calendar>() {
@Override
public Calendar convert(Object o, String pattern) {
if (o == null) {
return null;
} else if (o instanceof Calendar) {
return (Calendar) o;
}
java.util.Date date = DATE_CONVERTER.convert(o, pattern);
if (date != null) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
return cal;
}
return null;
}
@Override
public Calendar convert(Object o) {
return convert(o, null);
}
};
public abstract static class DateConverter implements
Converter<java.util.Date> {
public java.util.Date toDate(String s, String pattern) {
return toDate(s, pattern, Locale.getDefault());
}
public java.util.Date toDate(String s, String pattern, Locale locale) {
SimpleDateFormat sdf = getDateFormat(s, pattern, locale);
try {
return sdf.parse(s);
} catch (ParseException ex) {
LOG.log(Level.CONFIG, ex.getMessage(), ex);
return null;
}
}
public SimpleDateFormat getDateFormat(String s, String pattern,
Locale locale) {
if (pattern != null) {
return createSimpleDateFormat(pattern);
}
return getDateFormat(s, locale);
}
public SimpleDateFormat getDateFormat(String s, Locale locale) {
String pattern = getPattern(locale);
String shortPattern = removeDelimiter(pattern);
String delimitor = findDelimiter(s);
if (delimitor == null) {
if (s.length() == shortPattern.length()) {
return createSimpleDateFormat(shortPattern);
}
if (s.length() == shortPattern.length() + 2) {
return createSimpleDateFormat(StringUtil.replace(
shortPattern, "yy", "yyyy"));
}
} else {
String[] array = s.split(delimitor);
for (int i = 0; i < array.length; ++i) {
if (array[i].length() == 4) {
pattern = StringUtil.replace(pattern, "yy", "yyyy");
break;
}
}
return createSimpleDateFormat(pattern);
}
return createSimpleDateFormat();
}
public SimpleDateFormat getDateFormat(Locale locale) {
return createSimpleDateFormat(getPattern(locale));
}
public SimpleDateFormat getY4DateFormat(Locale locale) {
return createSimpleDateFormat(getY4Pattern(locale));
}
public String getY4Pattern(Locale locale) {
String pattern = getPattern(locale);
if (pattern.indexOf("yyyy") < 0) {
pattern = StringUtil.replace(pattern, "yy", "yyyy");
}
return pattern;
}
public String getPattern(Locale locale) {
SimpleDateFormat df = (SimpleDateFormat) DateFormat
.getDateInstance(DateFormat.SHORT, locale);
String pattern = df.toPattern();
int index = pattern.indexOf(' ');
if (index > 0) {
pattern = pattern.substring(0, index);
}
if (pattern.indexOf("MM") < 0) {
pattern = StringUtil.replace(pattern, "M", "MM");
}
if (pattern.indexOf("dd") < 0) {
pattern = StringUtil.replace(pattern, "d", "dd");
}
return pattern;
}
public String findDelimiter(String value) {
for (int i = 0; i < value.length(); ++i) {
char c = value.charAt(i);
if (Character.isDigit(c)) {
continue;
}
return Character.toString(c);
}
return null;
}
public String removeDelimiter(String pattern) {
StringBuilder builder = new StringBuilder(pattern.length());
for (int i = 0; i < pattern.length(); ++i) {
char c = pattern.charAt(i);
if (c == 'y' || c == 'M' || c == 'd') {
builder.append(c);
}
}
return builder.toString();
}
protected SimpleDateFormat createSimpleDateFormat(String pattern) {
return new SimpleDateFormat(pattern);
}
protected SimpleDateFormat createSimpleDateFormat() {
return new SimpleDateFormat();
}
}
public static final DateConverter DATE_CONVERTER = new DateConverter() {
@Override
public java.util.Date convert(Object o, String pattern) {
if (o == null) {
return null;
} else if (o instanceof String) {
return toDate((String) o, pattern);
} else if (o instanceof java.util.Date) {
return (java.util.Date) o;
} else if (o instanceof Calendar) {
return ((Calendar) o).getTime();
} else if (o instanceof Number) {
return new java.util.Date(((Number) o).longValue());
}
return null;
}
@Override
public java.util.Date convert(Object o) {
return convert(o, null);
}
};
public static final Converter<Double> DOUBLE_CONVERTER = new Converter<Double>() {
@Override
public Double convert(Object o) {
return convert(o, null);
}
@Override
public Double convert(Object o, String pattern) {
if (o == null) {
return null;
} else if (o instanceof Double) {
return (Double) o;
} else if (o instanceof Number) {
return ((Number) o).doubleValue();
} else if (o instanceof String) {
String s = DecimalFormatUtil.normalize(String.class.cast(o));
if (StringUtil.isEmpty(s) == false) {
return Double.valueOf(s);
}
return null;
} else if (o instanceof Boolean) {
return ((Boolean) o).booleanValue() ? 1.0 : 0.0;
}
return null;
}
};
public static final Converter<Float> FLOAT_CONVERTER = new Converter<Float>() {
@Override
public Float convert(Object o, String pattern) {
if (o == null) {
return null;
} else if (o instanceof Float) {
return (Float) o;
} else if (o instanceof Number) {
return new Float(((Number) o).floatValue());
} else if (o instanceof String) {
String s = DecimalFormatUtil.normalize(String.class.cast(o));
if (StringUtil.isEmpty(s) == false) {
return Float.valueOf(s);
}
return null;
} else if (o instanceof Boolean) {
return ((Boolean) o).booleanValue() ? 1.0f : 0.0f;
}
return null;
}
@Override
public Float convert(Object o) {
return convert(o, null);
}
};
public static final Converter<Integer> INTEGER_CONVERTER = new Converter<Integer>() {
@Override
public Integer convert(Object o, String pattern) {
if (o == null) {
return null;
} else if (o instanceof Integer) {
return (Integer) o;
} else if (o instanceof Number) {
return ((Number) o).intValue();
} else if (o instanceof String) {
String s = DecimalFormatUtil.normalize(String.class.cast(o));
if (StringUtil.isEmpty(s) == false) {
return Integer.valueOf(s);
}
return null;
} else if (o instanceof Boolean) {
return ((Boolean) o).booleanValue() ? 1 : 0;
}
return null;
}
@Override
public Integer convert(Object o) {
return convert(o, null);
}
};
public static final Converter<Long> LONG_CONVERTER = new Converter<Long>() {
@Override
public Long convert(Object o, String pattern) {
if (o == null) {
return null;
} else if (o instanceof Long) {
return (Long) o;
} else if (o instanceof Number) {
return ((Number) o).longValue();
} else if (o instanceof String) {
String s = DecimalFormatUtil.normalize(String.class.cast(o));
if (StringUtil.isEmpty(s) == false) {
return Long.valueOf(s);
}
return null;
} else if (o instanceof java.util.Date) {
return ((java.util.Date) o).getTime();
} else if (o instanceof Boolean) {
return ((Boolean) o).booleanValue() ? 1L : 0L;
}
return null;
}
@Override
public Long convert(Object o) {
return convert(o, null);
}
};
public static final Converter<Short> SHORT_CONVERTER = new Converter<Short>() {
@Override
public Short convert(Object o, String pattern) {
if (o == null) {
return null;
} else if (o instanceof Short) {
return (Short) o;
} else if (o instanceof Number) {
return new Short(((Number) o).shortValue());
} else if (o instanceof String) {
String s = DecimalFormatUtil.normalize(String.class.cast(o));
if (StringUtil.isEmpty(s) == false) {
return Short.valueOf(s);
}
return null;
} else if (o instanceof Boolean) {
return ((Boolean) o).booleanValue() ? (short) 1 : (short) 0;
}
return null;
}
@Override
public Short convert(Object o) {
return convert(o, null);
}
};
public static final Converter<java.sql.Date> SQLDATE_CONVERTER = new Converter<java.sql.Date>() {
@Override
public java.sql.Date convert(Object o, String pattern) {
if (o instanceof java.sql.Date) {
return (java.sql.Date) o;
}
java.util.Date date = DATE_CONVERTER.convert(o, pattern);
if (date != null) {
Calendar c = Calendar.getInstance();
c.setTime(date);
c.set(Calendar.HOUR_OF_DAY, 0);
c.set(Calendar.HOUR, 0);
c.set(Calendar.MINUTE, 0);
c.set(Calendar.SECOND, 0);
c.set(Calendar.MILLISECOND, 0);
return new java.sql.Date(c.getTimeInMillis());
}
return null;
}
@Override
public java.sql.Date convert(Object o) {
return convert(o, null);
}
};
public static final Converter<String> STRING_CONVERTER = new Converter<String>() {
@Override
public String convert(Object value, String pattern) {
if (value == null) {
return null;
} else if (value instanceof String) {
return (String) value;
} else if (value instanceof java.util.Date) {
return toString((java.util.Date) value, pattern);
} else if (value instanceof Number) {
return toString((Number) value, pattern);
} else if (value instanceof byte[]) {
return Base64Util.encode((byte[]) value);
} else if (value instanceof URL) {
return ((URL) value).toExternalForm();
} else {
return value.toString();
}
}
protected String toString(Number value, String pattern) {
if (value != null) {
if (pattern != null) {
return new DecimalFormat(pattern).format(value);
}
return value.toString();
}
return null;
}
protected String toString(java.util.Date value, String pattern) {
if (pattern != null) {
return new SimpleDateFormat(pattern).format(value);
}
return value.toString();
}
@Override
public String convert(Object o) {
return convert(o, null);
}
};
public static final Converter<Time> TIME_CONVERTER = new Converter<Time>() {
@Override
public Time convert(Object o) {
return convert(o, null);
}
@Override
public Time convert(Object o, String pattern) {
if (o instanceof Time) {
return (Time) o;
}
java.util.Date date = DATE_CONVERTER.convert(o, pattern);
if (date != null) {
return new Time(date.getTime());
}
return null;
}
};
public static final Converter<Timestamp> TIMESTAMP_CONVERTER = new Converter<Timestamp>() {
@Override
public Timestamp convert(Object o) {
return convert(o, null);
}
@Override
public Timestamp convert(Object o, String pattern) {
if (o instanceof Timestamp) {
return (Timestamp) o;
}
java.util.Date date = DATE_CONVERTER.convert(o, pattern);
if (date != null) {
return new Timestamp(date.getTime());
}
return null;
}
};
public static final Converter<URL> URL_CONVERTER = new Converter<URL>() {
@Override
public URL convert(Object o) {
if (o instanceof URL) {
return (URL) o;
}
try {
if (o instanceof File) {
return ((File) o).toURI().toURL();
}
String url = STRING_CONVERTER.convert(o);
if (url != null) {
return new URL(url);
}
return null;
} catch (MalformedURLException ex) {
LOG.log(Level.CONFIG, ex.getMessage(), ex);
return null;
}
}
@Override
public URL convert(Object o, String pattern) {
return convert(o);
}
};
public static final Converter<InputStream> INPUTSTREAM_CONVERTER = new Converter<InputStream>() {
@Override
public InputStream convert(Object o) {
if (o == null) {
return null;
}
if (o instanceof InputStream) {
return (InputStream) o;
}
try {
if (o instanceof File) {
return new FileInputStream((File) o);
}
URL url = URL_CONVERTER.convert(o);
if (url != null) {
return url.openStream();
}
} catch (IOException ex) {
LOG.log(Level.CONFIG, ex.getMessage(), ex);
}
return null;
}
@Override
public InputStream convert(Object o, String pattern) {
return convert(o);
}
};
public static final Converter<Reader> READER_CONVERTER = new Converter<Reader>() {
@Override
public Reader convert(Object o) {
if (o == null) {
return null;
}
if (o instanceof Reader) {
return (Reader) o;
}
InputStream in = INPUTSTREAM_CONVERTER.convert(o);
if (in != null) {
return new InputStreamReader(in);
}
return null;
}
@Override
public Reader convert(Object o, String pattern) {
return convert(o);
}
};
static {
init();
}
}