package haotian.core.orm;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.*;
import org.apache.commons.dbutils.RowProcessor;
import org.apache.ddlutils.model.Column;
import org.apache.ddlutils.model.Table;
/**
*
* @author
* Apache Dbutils ORM, JPA Annotation
*
*/
public class AnnotationRowProcessor implements RowProcessor {
protected static final int PROPERTY_NOT_FOUND = -1;
private static final Map<Class<?>, Object> primitiveDefaults = new HashMap<Class<?>, Object>();
static {
primitiveDefaults.put(Integer.TYPE, 0);
primitiveDefaults.put(Short.TYPE, (Short) ((short) 0));
primitiveDefaults.put(Byte.TYPE, (Byte) ((byte) 0));
primitiveDefaults.put(Float.TYPE, (Float) (float) (0));
primitiveDefaults.put(Double.TYPE, (Double) (double) (0));
primitiveDefaults.put(Long.TYPE, (Long) (0L));
primitiveDefaults.put(Boolean.TYPE, Boolean.FALSE);
primitiveDefaults.put(Character.TYPE, '\u0000');
}
public AnnotationRowProcessor() {
super();
}
/**
*
*/
public <T> T toBean(ResultSet rs, Class<T> clazz) throws SQLException {
T bean = this.newInstance(clazz);
Table table = EntityFactory.getTable(clazz);
ResultSetMetaData rsmd = rs.getMetaData();
int cols = rsmd.getColumnCount();
for (int col = 1; col <= cols; col++) {
String columnName = rsmd.getColumnLabel(col);
if (null == columnName || 0 == columnName.length()) {
columnName = rsmd.getColumnName(col);
}
Column column = mapColumnToFiled(table, columnName);
if (column == null) {
continue;
}
PropertyDescriptor prop;
try {
prop = new PropertyDescriptor(column.getJavaName(), clazz);
} catch (IntrospectionException e) {
e.printStackTrace();
throw new SQLException(e.getMessage());
}
Class<?> propType = prop.getPropertyType();
Object value = this.processColumn(rs, col, propType);
if (propType != null && value == null && propType.isPrimitive()) {
value = primitiveDefaults.get(propType);
}
this.callSetter(bean, prop, value);
}
return bean;
}
/**
*
*/
public <T> List<T> toBeanList(ResultSet rs, Class<T> type)
throws SQLException {
List<T> results = new ArrayList<T>();
if (!rs.next()) {
return results;
}
do {
results.add(this.toBean(rs, type));
} while (rs.next());
return results;
}
/**
* , column field
*/
private Column mapColumnToFiled(Table table, String columnName) {
Column column = null;
for (int i = 0; i < table.getColumnCount(); i++) {
column = table.getColumn(i);
if (columnName.equalsIgnoreCase(column.getName())) {
return column;
}
}
return null;
}
private void callSetter(Object target, PropertyDescriptor prop, Object value)
throws SQLException {
Method setter = prop.getWriteMethod();
if (setter == null) {
return;
}
Class<?>[] params = setter.getParameterTypes();
try {
// convert types for some popular ones
if (value != null) {
if (value instanceof java.util.Date) {
if (params[0].getName().equals("java.sql.Date")) {
value = new java.sql.Date(((java.util.Date) value)
.getTime());
} else if (params[0].getName().equals("java.sql.Time")) {
value = new java.sql.Time(((java.util.Date) value)
.getTime());
} else if (params[0].getName().equals("java.sql.Timestamp")) {
value = new java.sql.Timestamp(((java.util.Date) value)
.getTime());
}
}
}
// Don't call setter if the value object isn't the right type
if (this.isCompatibleType(value, params[0])) {
setter.invoke(target, new Object[] { value });
} else {
throw new SQLException("Cannot set " + prop.getName()
+ ": incompatible types.");
}
} catch (IllegalArgumentException e) {
throw new SQLException("Cannot set " + prop.getName() + ": "
+ e.getMessage());
} catch (IllegalAccessException e) {
throw new SQLException("Cannot set " + prop.getName() + ": "
+ e.getMessage());
} catch (InvocationTargetException e) {
throw new SQLException("Cannot set " + prop.getName() + ": "
+ e.getMessage());
}
}
private boolean isCompatibleType(Object value, Class<?> type) {
// Do object check first, then primitives
if (value == null || type.isInstance(value)) {
return true;
} else if (type.equals(Integer.TYPE) && Integer.class.isInstance(value)) {
return true;
} else if (type.equals(Long.TYPE) && Long.class.isInstance(value)) {
return true;
} else if (type.equals(Double.TYPE) && Double.class.isInstance(value)) {
return true;
} else if (type.equals(Float.TYPE) && Float.class.isInstance(value)) {
return true;
} else if (type.equals(Short.TYPE) && Short.class.isInstance(value)) {
return true;
} else if (type.equals(Byte.TYPE) && Byte.class.isInstance(value)) {
return true;
} else if (type.equals(Character.TYPE)
&& Character.class.isInstance(value)) {
return true;
} else if (type.equals(Boolean.TYPE) && Boolean.class.isInstance(value)) {
return true;
} else {
return false;
}
}
protected <T> T newInstance(Class<T> c) throws SQLException {
try {
return c.newInstance();
} catch (InstantiationException e) {
throw new SQLException("Cannot create " + c.getName() + ": "
+ e.getMessage());
} catch (IllegalAccessException e) {
throw new SQLException("Cannot create " + c.getName() + ": "
+ e.getMessage());
}
}
protected Object processColumn(ResultSet rs, int index, Class<?> propType)
throws SQLException {
if (propType.equals(String.class)) {
return rs.getString(index);
} else if (propType.equals(Integer.TYPE)
|| propType.equals(Integer.class)) {
return (rs.getInt(index));
} else if (propType.equals(Boolean.TYPE)
|| propType.equals(Boolean.class)) {
return (rs.getBoolean(index));
} else if (propType.equals(Long.TYPE) || propType.equals(Long.class)) {
return (rs.getLong(index));
} else if (propType.equals(Double.TYPE)
|| propType.equals(Double.class)) {
return (rs.getDouble(index));
} else if (propType.equals(Float.TYPE) || propType.equals(Float.class)) {
return (rs.getFloat(index));
} else if (propType.equals(Short.TYPE) || propType.equals(Short.class)) {
return (rs.getShort(index));
} else if (propType.equals(Byte.TYPE) || propType.equals(Byte.class)) {
return (rs.getByte(index));
} else if (propType.equals(Timestamp.class)) {
return rs.getTimestamp(index);
} else if (propType.isAnnotationPresent(javax.persistence.Entity.class)
&& EntityFactory.getTable(propType) != null) {
BeanProxy bean = new BeanProxy();
bean.setKey((java.io.Serializable) rs.getObject(index));
return bean.getBean(propType);
} else {
return rs.getObject(index);
}
}
public Object[] toArray(ResultSet rs) throws SQLException {
ResultSetMetaData meta = rs.getMetaData();
int cols = meta.getColumnCount();
Object[] result = new Object[cols];
for (int i = 0; i < cols; i++) {
result[i] = rs.getObject(i + 1);
}
return result;
}
public Map<String, Object> toMap(ResultSet rs) throws SQLException {
Map<String, Object> result = new HashMap<String, Object>();
ResultSetMetaData rsmd = rs.getMetaData();
int cols = rsmd.getColumnCount();
for (int i = 1; i <= cols; i++) {
result.put(rsmd.getColumnName(i), rs.getObject(i));
}
return result;
}
}