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.Array;
19 import java.lang.reflect.Method;
20 import java.util.Collection;
21
22 import org.apache.commons.logging.Log;
23 import org.apache.commons.logging.LogFactory;
24
25 /*** <p><code>MethodUpdater</code> updates the current bean context
26 * by calling a WriteMethod with the String value from the XML attribute
27 * or element.</p>
28 *
29 * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
30 * @version $Revision: 1.13 $
31 */
32 public class MethodUpdater implements Updater {
33
34 /*** Logger */
35 private static Log log = LogFactory.getLog( MethodUpdater.class );
36
37 /***
38 * Programmatically set log
39 * @param aLog the implementation to which this class should log
40 */
41 public static void setLog( Log aLog ) {
42 log = aLog;
43 }
44
45 /*** The method to call on the bean */
46 private Method method;
47 /*** The type of the first parameter of the method */
48 private Class valueType;
49
50 /*** Base constructor */
51 public MethodUpdater() {
52 }
53
54 /***
55 * Convenience constructor sets method property
56 * @param method the Method to be invoked on the context's bean in the update
57 */
58 public MethodUpdater(Method method) {
59 setMethod( method );
60 }
61
62 /***
63 * Updates the current bean context with the given String value
64 * @param context the Context to be updated
65 * @param newValue the update to this new value
66 */
67 public void update(Context context, Object newValue) {
68 Object bean = context.getBean();
69 if ( bean != null ) {
70 if ( newValue instanceof String ) {
71
72 if ( log.isTraceEnabled() ) {
73 log.trace("Converting primitive to " + valueType);
74 }
75 newValue = context.getObjectStringConverter()
76 .stringToObject( (String) newValue, valueType, null, context );
77 }
78 if ( newValue != null ) {
79
80
81
82
83
84
85
86
87
88
89
90
91 }
92
93 if (newValue instanceof Collection && valueType.isArray()) {
94 Collection valuesAsCollection = (Collection) newValue;
95 Class componentType = valueType.getComponentType();
96 if (componentType != null) {
97 Object[] valuesAsArray =
98 (Object[]) Array.newInstance(componentType, valuesAsCollection.size());
99 newValue = valuesAsCollection.toArray(valuesAsArray);
100 }
101 }
102
103 Object[] arguments = { newValue };
104 try {
105 if ( log.isDebugEnabled() ) {
106 log.debug(
107 "Calling setter method: " + method.getName() + " on bean: " + bean
108 + " with new value: " + newValue
109 );
110 }
111 method.invoke( bean, arguments );
112
113 } catch (Exception e) {
114 String valueTypeName = (newValue != null) ? newValue.getClass().getName() : "null";
115 log.warn(
116 "Cannot evaluate method: " + method.getName() + " on bean: " + bean
117 + " of type: " + bean.getClass().getName() + " with value: " + newValue
118 + " of type: " + valueTypeName
119 );
120 handleException(context, e);
121 }
122 }
123 }
124
125 /***
126 * Gets the method which will be invoked by the update
127 *
128 * @return the Method to be invoked by the update
129 */
130 public Method getMethod() {
131 return method;
132 }
133
134 /***
135 * Sets the constant value of this expression
136 * @param method the Method to be invoked by the update
137 */
138 public void setMethod(Method method) {
139 this.method = method;
140 Class[] types = method.getParameterTypes();
141 if ( types == null || types.length <= 0 ) {
142 throw new IllegalArgumentException( "The Method must have at least one parameter" );
143 }
144 this.valueType = types[0];
145 }
146
147
148
149
150 /***
151 * Strategy method to allow derivations to handle exceptions differently.
152 * @param context the Context being updated when this exception occured
153 * @param e the Exception that occured during the update
154 */
155 protected void handleException(Context context, Exception e) {
156 log.info( "Caught exception: " + e, e );
157 }
158
159 /***
160 * Returns something useful for logging.
161 * @return something useful for logging
162 */
163 public String toString() {
164 return "MethodUpdater [method=" + method + "]";
165 }
166 }