package com.towel.el.handler;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import com.towel.bean.Formatter;
import com.towel.el.NotResolvableFieldException;
/**
* An implementation of FieldAccessHandler who use the direct access to the
* field.
*
*@see mark.utisl.el.handler.FieldAccessHandler
*
*@author Marcos Vasconcelos
*/
public class FieldHandler implements FieldAccessHandler {
private List<Class<?>> classesTrace;// A trace to the field
private List<Field> fields;// The fields trace.
public FieldHandler() {
classesTrace = new ArrayList<Class<?>>();
fields = new ArrayList<Field>();
}
@Override
public void resolveField(Class<?> clazz, String expression) {
if (clazz == null || expression == null)
throw new IllegalArgumentException("Arguments can't be null!");
classesTrace.add(clazz);
String[] trace = expression.split("[.]");
for (int i = 0; i < trace.length; i++)
addField(trace[i]);
}
@Override
public Object getValue(Object t, Formatter formatter) {
if (t == null)
return null;
Object obj = null;
try {
obj = t;
for (int i = 0; i < fields.size(); i++)
obj = fields.get(i).get(obj);
} catch (Exception e) {
throw new RuntimeException(e);
}
return formatter.format(obj);
}
@Override
public void setValue(Object t, Object value, Formatter formatter) {
if (t == null)
return;
Object obj = null;
Field field = null;
try {
obj = t;
int size = fields.size() - 1;
if (size > -1) {
for (int i = 0; i < size; i++)
obj = fields.get(i).get(obj);
field = fields.get(fields.size() - 1);
} else
field = fields.get(0);
field.set(obj, formatter.parse(value));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private void addField(String fieldName) {
Class<?> clazz = classesTrace.get(classesTrace.size() - 1);
Field f = getAcessibleField(clazz, fieldName);
classesTrace.add(f.getType());
fields.add(f);
}
private Field getAcessibleField(Class<?> clazz, String fieldName) {
Field f = null;
try {
f = clazz.getDeclaredField(fieldName);
} catch (NoSuchFieldException e) {
if(clazz.getSuperclass() == null){
NotResolvableFieldException ex = new NotResolvableFieldException(
fieldName, clazz);
ex.setStackTrace(e.getStackTrace());
throw ex;
}
return getAcessibleField(clazz.getSuperclass(), fieldName);
}
f.setAccessible(true);
return f;
}
@Override
public Class<?> getFieldType() {
return fields.get(fields.size() - 1).getType();
}
@Override
public Class<?> getTraceClassAt(int idx) {
return classesTrace.get(idx);
}
public Field getField() {
return fields.get(fields.size() - 1);
}
public Field getField(int idx) {
return fields.get(idx);
}
public int getFieldTraceSize() {
return fields.size();
}
}