package org.skife.jdbi.v2;
import org.skife.jdbi.v2.tweak.ResultColumnMapper;
import org.skife.jdbi.v2.tweak.ResultSetMapper;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
public class ReflectionBeanMapper<T> implements ResultSetMapper<T>
{
private final Class<T> type;
private final Map<String, Field> properties = new HashMap<String, Field>();
public ReflectionBeanMapper(Class<T> type)
{
this.type = type;
cacheAllFieldsIncludingSuperClass(type);
}
private void cacheAllFieldsIncludingSuperClass(Class<T> type) {
Class aClass = type;
while(aClass != null) {
for (Field field : aClass.getDeclaredFields()) {
properties.put(field.getName().toLowerCase(), field);
}
aClass = aClass.getSuperclass();
}
}
@Override
@SuppressWarnings({"unchecked", "rawtypes"})
public T map(int row, ResultSet rs, StatementContext ctx)
throws SQLException
{
T bean;
try {
bean = type.newInstance();
}
catch (Exception e) {
throw new IllegalArgumentException(String.format("A bean, %s, was mapped " +
"which was not instantiable", type.getName()), e);
}
ResultSetMetaData metadata = rs.getMetaData();
for (int i = 1; i <= metadata.getColumnCount(); ++i) {
String name = metadata.getColumnLabel(i).toLowerCase();
Field field = properties.get(name);
if (field != null) {
Class type = field.getType();
Object value;
ResultColumnMapper mapper = ctx.columnMapperFor(type);
if (mapper != null) {
value = mapper.mapColumn(rs, i, ctx);
}
else {
value = rs.getObject(i);
}
try
{
field.setAccessible(true);
field.set(bean, value);
}
catch (IllegalAccessException e) {
throw new IllegalArgumentException(String.format("Unable to access " +
"property, %s", name), e);
}
}
}
return bean;
}
}