Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: ddec40db33c4ff7629ea4c9ffeb83b650bed11b8 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
/**
 * <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.18 2009/07/31 00:38:16 mtaal Exp $
 */

package org.eclipse.emf.teneo.util;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Hashtable;
import java.util.concurrent.ConcurrentHashMap;

import org.eclipse.emf.teneo.TeneoException;

/**
 * Contains different util methods.
 * 
 * @author <a href="mailto:mtaal@elver.org">Martin Taal</a>
 * @version $Revision: 1.18 $
 */

public class FieldUtil {
	/** The hashtable caches clazz field name combinations */
	private static final ConcurrentHashMap<String, Object> fieldMethodCache = new ConcurrentHashMap<String, Object>();

	/** Sets a field and wraps the exceptions */
	public static Object callMethod(Object obj, String methodName, Object[] params) {
		Method method;
		try {
			method = getMethodInternal(obj.getClass(), methodName, (params == null ? 0 : params.length));
			if (method != null) {
				fieldMethodCache.put(obj.getClass().getName() + "." + methodName + "."
						+ (params == null ? 0 : params.length), 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, 0);
			if (method == null) {
				method = getMethodInternal(target.getClass(), "is" + fieldName, 0);
			}
			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, 1);
			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, int numOfParams)
			throws Exception {
		if (clazz == null) {
			return null;
		}

		final Method method = (Method) fieldMethodCache.get(clazz.getName() + "." + methodName + "."
				+ numOfParams);
		if (method != null) {
			return method;
		}
		final Method[] methods = clazz.getDeclaredMethods();
		for (Method element : methods) {
			if (element.getName().compareToIgnoreCase(methodName) == 0
					&& element.getParameterTypes().length == numOfParams) {
				element.setAccessible(true);
				fieldMethodCache.put(clazz.getName() + "." + methodName + "." + numOfParams, element);
				return element;
			}
		}

		return getMethodInternal(clazz.getSuperclass(), methodName, numOfParams);
	}
}

Back to the top