package novoda.android.typewriter.cursor;
import android.database.Cursor;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import novoda.android.typewriter.introspection.RichClass;
public class ReflectionCursorMarshaller<T> implements CursorMarshaller<T> {
private final static int TYPE_INT = 0;
private final static int TYPE_DOUBLE = 1;
private final static int TYPE_LONG = 2;
private final RichClass<T> richClass;
private final Map<String, Method> methodsByName = new HashMap<String, Method>();
public ReflectionCursorMarshaller(Cursor cursor, Class<T> classType) {
richClass = new RichClass<T>(classType);
for (int i = 0; i < cursor.getColumnCount(); i++) {
String name = cursor.getColumnName(i);
if (richClass.hasMethod(name)) {
Method setter = richClass.setter(name);
methodsByName.put(name, setter);
}
}
}
@Override
public T marshall(Cursor cursor) {
if (cursor.getPosition() < 0) {
throw new RuntimeException("Cursor is at position below 0" + cursor.getPosition());
}
T obj;
try {
obj = richClass.newInstance();
for (int i = 0; i < cursor.getColumnCount(); i++) {
String name = cursor.getColumnName(i);
Method setter = methodsByName.get(name);
int type = TYPE_INT;
Class<?> t = setter.getParameterTypes()[0];
if (t.equals(long.class)) {
type = TYPE_LONG;
} else if (t.equals(double.class)) {
type = TYPE_DOUBLE;
}
setter.invoke(obj, getObjectFromCursor(cursor, i, type));
}
return obj;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private Object getObjectFromCursor(Cursor cursor, int index, int type) {
final int cursorType = cursor.getType(index);
final Object obj;
switch (cursorType) {
case Cursor.FIELD_TYPE_FLOAT:
obj = cursor.getFloat(index);
break;
case Cursor.FIELD_TYPE_STRING:
obj = cursor.getString(index);
break;
case Cursor.FIELD_TYPE_INTEGER:
switch (type) {
case TYPE_DOUBLE:
obj = cursor.getDouble(index);
break;
case TYPE_LONG:
obj = cursor.getLong(index);
break;
default:
obj = cursor.getInt(index);
break;
}
break;
default:
obj = "";
}
return obj;
}
}