1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.commons.betwixt.expression;
17
18 import java.lang.reflect.Method;
19
20 /*** <p><code>MethodExpression</code> evaluates a method on the current bean context.</p>
21 *
22 * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
23 * @version $Revision: 1.8 $
24 */
25 public class MethodExpression implements Expression {
26
27 /*** null arguments */
28 protected static Object[] NULL_ARGUMENTS;
29 /*** null classes */
30 protected static Class[] NULL_CLASSES;
31
32 /*** The method to call on the bean */
33 private Method method;
34
35 /*** Base constructor */
36 public MethodExpression() {
37 }
38
39 /***
40 * Convenience constructor sets method property
41 * @param method the Method whose return value when invoked on the bean
42 * will the value of this expression
43 */
44 public MethodExpression(Method method) {
45 this.method = method;
46 }
47
48 /***
49 * Evaluate by calling the read method on the current bean
50 *
51 * @param context the context against which this expression will be evaluated
52 * @return the value returned by the method when it's invoked on the context's bean,
53 * so long as the method can be invoked.
54 * Otherwise, null.
55 */
56 public Object evaluate(Context context) {
57 Object bean = context.getBean();
58 if ( bean != null ) {
59 Object[] arguments = getArguments();
60 try {
61 return method.invoke( bean, arguments );
62
63 } catch (IllegalAccessException e) {
64
65 try {
66 Class type = bean.getClass();
67 Method alternate = findAlternateMethod( type, method );
68 if ( alternate != null ) {
69 return alternate.invoke( bean, arguments );
70 }
71 } catch (Exception e2) {
72 handleException(context, e2);
73 }
74 } catch (Exception e) {
75 handleException(context, e);
76 }
77 }
78 return null;
79 }
80
81 /***
82 * Do nothing.
83 * @see org.apache.commons.betwixt.expression.Expression
84 */
85 public void update(Context context, String newValue) {
86
87 }
88
89 /***
90 * Gets the method used to evaluate this expression.
91 * @return the method whose value (when invoked against the context's bean) will be used
92 * to evaluate this expression.
93 */
94 public Method getMethod() {
95 return method;
96 }
97
98 /***
99 * Sets the method used to evaluate this expression
100 * @param method method whose value (when invoked against the context's bean) will be used
101 * to evaluate this expression
102 */
103 public void setMethod(Method method) {
104 this.method = method;
105 }
106
107
108
109
110 /***
111 * Allows derived objects to create arguments for the method call
112 * @return {@link #NULL_ARGUMENTS}
113 */
114 protected Object[] getArguments() {
115 return NULL_ARGUMENTS;
116 }
117
118 /*** Tries to find an alternate method for the given type using interfaces
119 * which gets around the problem of inner classes,
120 * such as on Map.Entry implementations.
121 *
122 * @param type the Class whose methods are to be searched
123 * @param method the Method for which an alternative is to be search for
124 * @return the alternative Method, if one can be found. Otherwise null.
125 */
126 protected Method findAlternateMethod(
127 Class type,
128 Method method ) {
129
130
131
132
133 Class[] interfaces = type.getInterfaces();
134 if ( interfaces != null ) {
135 String name = method.getName();
136 for ( int i = 0, size = interfaces.length; i < size; i++ ) {
137 Class otherType = interfaces[i];
138
139
140 try {
141 Method alternate = otherType.getMethod( name, NULL_CLASSES );
142 if ( alternate != null && alternate != method ) {
143 return alternate;
144 }
145 } catch (NoSuchMethodException e) {
146
147 }
148 }
149 }
150 return null;
151 }
152
153 /***
154 * <p>Log error to context's logger.</p>
155 *
156 * <p>Allows derived objects to handle exceptions differently.</p>
157 *
158 * @param context the Context being evaluated when the exception occured
159 * @param e the exception to handle
160 */
161 protected void handleException(Context context, Exception e) {
162
163 context.getLog().error("[MethodExpression] Cannot evaluate expression ", e);
164 }
165
166 /***
167 * Returns something useful for logging.
168 * @return something useful for logging
169 */
170 public String toString() {
171 return "MethodExpression [method=" + method + "]";
172 }
173 }