package com.towel.el.handler; import java.lang.reflect.Method; import java.util.LinkedList; import java.util.List; import com.towel.bean.Formatter; import com.towel.el.NotResolvableFieldException; /** * An implementation of FieldAccessHandler who use the get and set methods * declared in the class of the field. * *@see mark.utisl.el.handler.FieldAccessHandler * *@author Marcos Vasconcelos */ public class MethodHandler implements FieldAccessHandler { private Method setter; private LinkedList<Method> getterTrace; private List<Class<?>> classesTrace; public MethodHandler() { classesTrace = new LinkedList<Class<?>>(); getterTrace = new LinkedList<Method>(); } @Override public Class<?> getFieldType() { return getterTrace.getLast().getReturnType(); } @Override public Object getValue(Object t, Formatter formatter) { if (t == null) return null; Object obj = null; try { obj = getterTrace.get(0).invoke(t); for (int i = 1; i < getterTrace.size(); i++) obj = getterTrace.get(i).invoke(obj); } catch (Exception e) { throw new RuntimeException(e); } if (formatter != null) return formatter.format(obj); else return obj; } public void resolveField(Class<?> clazz, String expression) { classesTrace.add(clazz); String[] trace = expression.split("[.]"); for (int i = 0; i < trace.length; i++) addField(trace[i]); if (getterTrace.size() != trace.length) { getterTrace.clear(); classesTrace.clear(); throw new RuntimeException("Impossible to resolve field."); } setter = getSetterMethod(classesTrace.get(classesTrace.size() - 2), trace[trace.length - 1]); } @Override public void setValue(Object t, Object value, Formatter formatter) { if (t == null) return; Object obj = null; try { obj = t; int size = getterTrace.size() - 1; if (size > -1) for (int i = 0; i < size; i++) obj = getterTrace.get(i).invoke(obj); setter.invoke(obj, value); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } private void addField(String fieldName) { Class<?> clazz = classesTrace.get(classesTrace.size() - 1); // Field next = clazz.getDeclaredField(fieldName); Method m = getGetterMethod(clazz, fieldName); classesTrace.add(m.getReturnType()); getterTrace.add(m); } /** *Search in the class and return the getter method for the given fieldName * */ private Method getSetterMethod(Class<?> clazz, String fieldName) { Method m = null; try { m = clazz.getMethod("set" + String.valueOf(fieldName.charAt(0)).toUpperCase() + fieldName.substring(1), classesTrace.get(classesTrace .size() - 1)); } catch (NoSuchMethodException e) { throw NotResolvableFieldException.create(e, fieldName, clazz); } return m; } /** *Search in the class and return the getter method for the given fieldName * If field is boolean the method search isFieldName if not the method * search getFieldName */ private Method getGetterMethod(Class<?> clazz, String fieldName) { Method m = null; try { m = clazz.getMethod("get" + String.valueOf(fieldName.charAt(0)).toUpperCase() + fieldName.substring(1)); } catch (NoSuchMethodException e) { try { m = clazz.getMethod("is" + String.valueOf(fieldName.charAt(0)).toUpperCase() + fieldName.substring(1)); } catch (NoSuchMethodException ne) { throw NotResolvableFieldException.create(e, fieldName, clazz); } } return m; } @Override public Class<?> getTraceClassAt(int idx) { return classesTrace.get(idx); } }