KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > digester > SetNextRule


1 /* $Id: SetNextRule.java 157820 2005-03-16 22:46:19Z skitching $
2  *
3  * Copyright 2001-2004 The Apache Software Foundation.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17
18
19 package org.apache.commons.digester;
20
21
22 import org.apache.commons.beanutils.MethodUtils;
23
24
25 /**
26  * <p>Rule implementation that calls a method on the (top-1) (parent)
27  * object, passing the top object (child) as an argument. It is
28  * commonly used to establish parent-child relationships.</p>
29  *
30  * <p>This rule now supports more flexible method matching by default.
31  * It is possible that this may break (some) code
32  * written against release 1.1.1 or earlier.
33  * See {@link #isExactMatch()} for more details.</p>
34  *
35  * <p>Note that while CallMethodRule uses commons-beanutils' data-conversion
36  * functionality (ConvertUtils class) to convert parameter values into
37  * the appropriate type for the parameter to the called method, this
38  * rule does not. Needing to use ConvertUtils functionality when building
39  * parent-child relationships is expected to be very rare; however if you
40  * do need this then instead of using this rule, create a CallMethodRule
41  * specifying targetOffset of 1 in the constructor.</p>
42  */

43
44 public class SetNextRule extends Rule {
45
46
47     // ----------------------------------------------------------- Constructors
48

49
50     /**
51      * Construct a "set next" rule with the specified method name. The
52      * method's argument type is assumed to be the class of the
53      * child object.
54      *
55      * @param digester The associated Digester
56      * @param methodName Method name of the parent method to call
57      *
58      * @deprecated The digester instance is now set in the {@link Digester#addRule} method.
59      * Use {@link #SetNextRule(String methodName)} instead.
60      */

61     public SetNextRule(Digester digester, String JavaDoc methodName) {
62
63         this(methodName);
64
65     }
66
67
68     /**
69      * Construct a "set next" rule with the specified method name.
70      *
71      * @param digester The associated Digester
72      * @param methodName Method name of the parent method to call
73      * @param paramType Java class of the parent method's argument
74      * (if you wish to use a primitive type, specify the corresonding
75      * Java wrapper class instead, such as <code>java.lang.Boolean</code>
76      * for a <code>boolean</code> parameter)
77      *
78      * @deprecated The digester instance is now set in the {@link Digester#addRule} method.
79      * Use {@link #SetNextRule(String methodName,String paramType)} instead.
80      */

81     public SetNextRule(Digester digester, String JavaDoc methodName,
82                        String JavaDoc paramType) {
83
84         this(methodName, paramType);
85
86     }
87
88     /**
89      * Construct a "set next" rule with the specified method name. The
90      * method's argument type is assumed to be the class of the
91      * child object.
92      *
93      * @param methodName Method name of the parent method to call
94      */

95     public SetNextRule(String JavaDoc methodName) {
96
97         this(methodName, null);
98
99     }
100
101
102     /**
103      * Construct a "set next" rule with the specified method name.
104      *
105      * @param methodName Method name of the parent method to call
106      * @param paramType Java class of the parent method's argument
107      * (if you wish to use a primitive type, specify the corresonding
108      * Java wrapper class instead, such as <code>java.lang.Boolean</code>
109      * for a <code>boolean</code> parameter)
110      */

111     public SetNextRule(String JavaDoc methodName,
112                        String JavaDoc paramType) {
113
114         this.methodName = methodName;
115         this.paramType = paramType;
116
117     }
118
119
120     // ----------------------------------------------------- Instance Variables
121

122
123     /**
124      * The method name to call on the parent object.
125      */

126     protected String JavaDoc methodName = null;
127
128
129     /**
130      * The Java class name of the parameter type expected by the method.
131      */

132     protected String JavaDoc paramType = null;
133
134     /**
135      * Should we use exact matching. Default is no.
136      */

137     protected boolean useExactMatch = false;
138
139     // --------------------------------------------------------- Public Methods
140

141
142     /**
143      * <p>Is exact matching being used.</p>
144      *
145      * <p>This rule uses <code>org.apache.commons.beanutils.MethodUtils</code>
146      * to introspect the relevent objects so that the right method can be called.
147      * Originally, <code>MethodUtils.invokeExactMethod</code> was used.
148      * This matches methods very strictly
149      * and so may not find a matching method when one exists.
150      * This is still the behaviour when exact matching is enabled.</p>
151      *
152      * <p>When exact matching is disabled, <code>MethodUtils.invokeMethod</code> is used.
153      * This method finds more methods but is less precise when there are several methods
154      * with correct signatures.
155      * So, if you want to choose an exact signature you might need to enable this property.</p>
156      *
157      * <p>The default setting is to disable exact matches.</p>
158      *
159      * @return true iff exact matching is enabled
160      * @since Digester Release 1.1.1
161      */

162     public boolean isExactMatch() {
163     
164         return useExactMatch;
165     }
166     
167     /**
168      * <p>Set whether exact matching is enabled.</p>
169      *
170      * <p>See {@link #isExactMatch()}.</p>
171      *
172      * @param useExactMatch should this rule use exact method matching
173      * @since Digester Release 1.1.1
174      */

175     public void setExactMatch(boolean useExactMatch) {
176
177         this.useExactMatch = useExactMatch;
178     }
179
180     /**
181      * Process the end of this element.
182      */

183     public void end() throws Exception JavaDoc {
184
185         // Identify the objects to be used
186
Object JavaDoc child = digester.peek(0);
187         Object JavaDoc parent = digester.peek(1);
188         if (digester.log.isDebugEnabled()) {
189             if (parent == null) {
190                 digester.log.debug("[SetNextRule]{" + digester.match +
191                         "} Call [NULL PARENT]." +
192                         methodName + "(" + child + ")");
193             } else {
194                 digester.log.debug("[SetNextRule]{" + digester.match +
195                         "} Call " + parent.getClass().getName() + "." +
196                         methodName + "(" + child + ")");
197             }
198         }
199
200         // Call the specified method
201
Class JavaDoc paramTypes[] = new Class JavaDoc[1];
202         if (paramType != null) {
203             paramTypes[0] =
204                     digester.getClassLoader().loadClass(paramType);
205         } else {
206             paramTypes[0] = child.getClass();
207         }
208         
209         if (useExactMatch) {
210         
211             MethodUtils.invokeExactMethod(parent, methodName,
212                 new Object JavaDoc[]{ child }, paramTypes);
213                 
214         } else {
215         
216             MethodUtils.invokeMethod(parent, methodName,
217                 new Object JavaDoc[]{ child }, paramTypes);
218         
219         }
220     }
221
222
223     /**
224      * Render a printable version of this Rule.
225      */

226     public String JavaDoc toString() {
227
228         StringBuffer JavaDoc sb = new StringBuffer JavaDoc("SetNextRule[");
229         sb.append("methodName=");
230         sb.append(methodName);
231         sb.append(", paramType=");
232         sb.append(paramType);
233         sb.append("]");
234         return (sb.toString());
235
236     }
237
238
239 }
240
Popular Tags