package com.ctrip.platform.dal.dao.helper;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import com.ctrip.platform.dal.dao.DalRowMapper;

/**
 * In case you need get Short cloumn value from Db, use ShortRowMapper 
 * instead of this, because the default getObject will return Interger instead of Short for such column.
 * 
 * @author jhhe
 *
 * @param <T>
 */
public class DalObjectRowMapper<T> implements DalRowMapper<T> {
	private static final Map<Class<?>, TypeConverter<?>> typeConverterCache = new ConcurrentHashMap<>();
	
	private static TypeConverter<?> sameTypeConverter = new TypeConverter<Object>() {
		public Object convert(Object value) {
			return value;
		}
	};

	private Class<T> type;
	private TypeConverter<T> converter;
	
	public DalObjectRowMapper() {
	}
	
	public DalObjectRowMapper(Class<T> type) {
		this.type = type;
		converter = (TypeConverter<T>)typeConverterCache.get(type);
	}

	@SuppressWarnings("unchecked")
	public T map(ResultSet rs, int rowNum) throws SQLException {
		Object value = rs.getObject(1);
		
		if(value == null || converter == null || type.isInstance(value))
			return (T)value;

		return converter.convert(value);
	}
	
	
	private static interface TypeConverter<T> {
		T convert(Object value);
	}
	
	static {
		typeConverterCache.put(Short.class, new TypeConverter<Short>(){ public Short convert(Object value) {
			return ((Number)value).shortValue();}});

		typeConverterCache.put(Byte.class, new TypeConverter<Byte>(){ public Byte convert(Object value) {
			return ((Number)value).byteValue();}});

		typeConverterCache.put(Integer.class, new TypeConverter<Integer>(){ public Integer convert(Object value) {
			return ((Number)value).intValue();}});

		typeConverterCache.put(Long.class, new TypeConverter<Long>(){ public Long convert(Object value) {
			return ((Number)value).longValue();}});

		typeConverterCache.put(Float.class, new TypeConverter<Float>(){ public Float convert(Object value) {
			return ((Number)value).floatValue();}});

		typeConverterCache.put(Double.class, new TypeConverter<Double>(){ public Double convert(Object value) {
			return ((Number)value).doubleValue();}});
	}
}
@@ -98,16 +98,44 @@
 ption;%0D%0A
+import java.sql.Timestamp;%0D%0A
 import j
@@ -751,32 +751,46 @@
  Object convert(
+ResultSet rs, 
 Object value) %7B%0D
@@ -1313,16 +1313,20 @@
 convert(
+rs, 
 value);%0D
@@ -1394,29 +1394,63 @@
 convert(
-Object value)
+ResultSet rs, Object value) throws SQLException
 ;%0D%0A%09%7D%0D%0A%09
@@ -1541,32 +1541,46 @@
 c Short convert(
+ResultSet rs, 
 Object value) %7B%0D
@@ -1703,32 +1703,46 @@
 ic Byte convert(
+ResultSet rs, 
 Object value) %7B%0D
@@ -1873,32 +1873,46 @@
 Integer convert(
+ResultSet rs, 
 Object value) %7B%0D
@@ -2033,32 +2033,46 @@
 ic Long convert(
+ResultSet rs, 
 Object value) %7B%0D
@@ -2197,32 +2197,46 @@
 c Float convert(
+ResultSet rs, 
 Object value) %7B%0D
@@ -2373,16 +2373,30 @@
 convert(
+ResultSet rs, 
 Object v
@@ -2446,17 +2446,315 @@
 lue();%7D%7D);%0D%0A
+%09%09/**%0D%0A%09%09 * This is because oracle returns its own Timestamp type instead of standard java.sql.Timestamp%0D%0A%09%09 */%0D%0A%09%09typeConverterCache.put(Timestamp.class, new TypeConverter%3CTimestamp%3E()%7B public Timestamp convert(ResultSet rs, Object value) throws SQLException %7B%0D%0A%09%09%09return rs.getTimestamp(1);%7D%7D);%0D%0A
 %09%7D%0D%0A%7D

add support for timestamp