/** * <copyright> Copyright (c) 2005, 2006, 2007, 2008 Springsite BV (The Netherlands) and others All rights * reserved. This program and the accompanying materials are made available under the terms of the * Eclipse Public License v1.0 which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html Contributors: Martin Taal - Initial API and * implementation </copyright> $Id: FieldUtil.java,v 1.15 2008/06/02 07:15:29 mtaal Exp $ */ package org.eclipse.emf.teneo.util; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.Hashtable; import org.eclipse.emf.teneo.TeneoException; /** * Contains different util methods. * * @author <a href="mailto:mtaal@elver.org">Martin Taal</a> * @version $Revision: 1.15 $ */ public class FieldUtil { /** The hashtable caches clazz field name combinations */ private static final Hashtable<String, Object> fieldMethodCache = new Hashtable<String, Object>(); /** Sets a field and wraps the exceptions */ public static Object callMethod(Object obj, String methodName, Object[] params) { Method method = (Method) fieldMethodCache.get(obj.getClass().getName() + "." + methodName); try { if (method == null) { method = getMethodInternal(obj.getClass(), methodName); } if (method != null) { fieldMethodCache.put(obj.getClass().getName() + "." + methodName, method); } else { throw new TeneoException("Method does not exist " + obj.getClass().getName() + " method; "); } return method.invoke(obj, params); } catch (Exception e) { final StringBuffer paramStr = new StringBuffer(); if (params != null) { for (Object param : params) { paramStr.append(" - " + param + " (" + param.getClass().getName() + ")"); } } throw new TeneoException("Exception " + obj.getClass().getName() + " method; " + methodName + " with parameters: " + paramStr.toString(), e); } } /** Sets a field and wraps the exceptions */ public static void setField(Field field, Object obj, Object value) { try { field.set(obj, value); } catch (IllegalAccessException e) { throw new TeneoException("IllegalAccessException " + obj.getClass().getName() + " field; " + field.getName()); } } /** * Get the value for a field, first the field is accessed directly if not found then the getter * is called. */ public static Object callGetter(Object target, String fieldName) { try { Method method = getMethodInternal(target.getClass(), "get" + fieldName); if (method == null) { method = getMethodInternal(target.getClass(), "is" + fieldName); } if (method == null) { final Field field = getField(target.getClass(), fieldName); return field.get(target); } return callMethod(target, method.getName(), new Object[0]); } catch (Exception e) { throw new TeneoException("Exception getting " + fieldName + " from " + target.getClass().getName(), e); } } /** Set the field directly or through the set method */ public static void callSetter(Object target, String fieldName, Object value) { try { final Method method = getMethodInternal(target.getClass(), "get" + fieldName); if (method != null) { callMethod(target, "set" + fieldName, new Object[] { value }); return; } final Field field = getField(target.getClass(), fieldName); field.set(target, value); } catch (Exception e) { throw new TeneoException("Exception setting " + fieldName + " from " + target.getClass().getName() + " to value " + value + " of type " + (value != null ? value.getClass().getName() : ""), e); } } /** * Returns a field using a certain name, walks up the class hierarchy to find the field, will * make the field accessible also. Is a bit rough because it does a case insensitive search. * Note if the field is not found an exception is thrown. */ public static Field getField(Class<?> clazz, String fieldName) { Field field = (Field) fieldMethodCache.get(clazz.getName() + "." + fieldName); if (field != null) { return field; } try { field = getFieldInternal(clazz, fieldName); if (field == null) { field = getFieldInternal(clazz, fieldName + "_"); // the way // emf // escapes // fields } } catch (Exception e) // todo replace with specific exception { throw new TeneoException("Field " + fieldName + " not accessible for class: " + clazz.getName(), e); } if (field == null) { return null; } fieldMethodCache.put(clazz.getName() + "." + fieldName, field); field.setAccessible(true); return field; } /** Does the actual search for the field */ private static Field getFieldInternal(Class<?> clazz, String fieldName) throws Exception { if (clazz == null) { return null; } final Field[] fields = clazz.getDeclaredFields(); for (Field element : fields) { if (element.getName().compareToIgnoreCase(fieldName) == 0) { element.setAccessible(true); return element; } } return getFieldInternal(clazz.getSuperclass(), fieldName); } /** Does the actual search for the method */ private static Method getMethodInternal(Class<?> clazz, String methodName) throws Exception { if (clazz == null) { return null; } final Method method = (Method) fieldMethodCache.get(clazz.getName() + "." + methodName); if (method != null) { return method; } final Method[] methods = clazz.getDeclaredMethods(); for (Method element : methods) { if (element.getName().compareToIgnoreCase(methodName) == 0) { element.setAccessible(true); fieldMethodCache.put(clazz.getName() + "." + methodName, element); return element; } } return getMethodInternal(clazz.getSuperclass(), methodName); } }