001: /* $Id: SetTopRule.java 467222 2006-10-24 03:17:11Z markt $
002: *
003: * Licensed to the Apache Software Foundation (ASF) under one or more
004: * contributor license agreements. See the NOTICE file distributed with
005: * this work for additional information regarding copyright ownership.
006: * The ASF licenses this file to You under the Apache License, Version 2.0
007: * (the "License"); you may not use this file except in compliance with
008: * the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS,
014: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: * See the License for the specific language governing permissions and
016: * limitations under the License.
017: */
018:
019: package org.apache.tomcat.util.digester;
020:
021: import org.apache.tomcat.util.IntrospectionUtils;
022:
023: /**
024: * <p>Rule implementation that calls a "set parent" method on the top (child)
025: * object, passing the (top-1) (parent) object as an argument.</p>
026: *
027: * <p>This rule now supports more flexible method matching by default.
028: * It is possible that this may break (some) code
029: * written against release 1.1.1 or earlier.
030: * See {@link #isExactMatch()} for more details.</p>
031: */
032:
033: public class SetTopRule extends Rule {
034:
035: // ----------------------------------------------------------- Constructors
036:
037: /**
038: * Construct a "set parent" rule with the specified method name. The
039: * "set parent" method's argument type is assumed to be the class of the
040: * parent object.
041: *
042: * @param digester The associated Digester
043: * @param methodName Method name of the "set parent" method to call
044: *
045: * @deprecated The digester instance is now set in the {@link Digester#addRule} method.
046: * Use {@link #SetTopRule(String methodName)} instead.
047: */
048: public SetTopRule(Digester digester, String methodName) {
049:
050: this (methodName);
051:
052: }
053:
054: /**
055: * Construct a "set parent" rule with the specified method name.
056: *
057: * @param digester The associated Digester
058: * @param methodName Method name of the "set parent" method to call
059: * @param paramType Java class of the "set parent" method's argument
060: * (if you wish to use a primitive type, specify the corresonding
061: * Java wrapper class instead, such as <code>java.lang.Boolean</code>
062: * for a <code>boolean</code> parameter)
063: *
064: * @deprecated The digester instance is now set in the {@link Digester#addRule} method.
065: * Use {@link #SetTopRule(String methodName, String paramType)} instead.
066: */
067: public SetTopRule(Digester digester, String methodName,
068: String paramType) {
069:
070: this (methodName, paramType);
071:
072: }
073:
074: /**
075: * Construct a "set parent" rule with the specified method name. The
076: * "set parent" method's argument type is assumed to be the class of the
077: * parent object.
078: *
079: * @param methodName Method name of the "set parent" method to call
080: */
081: public SetTopRule(String methodName) {
082:
083: this (methodName, null);
084:
085: }
086:
087: /**
088: * Construct a "set parent" rule with the specified method name.
089: *
090: * @param methodName Method name of the "set parent" method to call
091: * @param paramType Java class of the "set parent" method's argument
092: * (if you wish to use a primitive type, specify the corresonding
093: * Java wrapper class instead, such as <code>java.lang.Boolean</code>
094: * for a <code>boolean</code> parameter)
095: */
096: public SetTopRule(String methodName, String paramType) {
097:
098: this .methodName = methodName;
099: this .paramType = paramType;
100:
101: }
102:
103: // ----------------------------------------------------- Instance Variables
104:
105: /**
106: * The method name to call on the child object.
107: */
108: protected String methodName = null;
109:
110: /**
111: * The Java class name of the parameter type expected by the method.
112: */
113: protected String paramType = null;
114:
115: /**
116: * Should we use exact matching. Default is no.
117: */
118: protected boolean useExactMatch = false;
119:
120: // --------------------------------------------------------- Public Methods
121:
122: /**
123: * <p>Is exact matching being used.</p>
124: *
125: * <p>This rule uses <code>org.apache.commons.beanutils.MethodUtils</code>
126: * to introspect the relevent objects so that the right method can be called.
127: * Originally, <code>MethodUtils.invokeExactMethod</code> was used.
128: * This matches methods very strictly
129: * and so may not find a matching method when one exists.
130: * This is still the behaviour when exact matching is enabled.</p>
131: *
132: * <p>When exact matching is disabled, <code>MethodUtils.invokeMethod</code> is used.
133: * This method finds more methods but is less precise when there are several methods
134: * with correct signatures.
135: * So, if you want to choose an exact signature you might need to enable this property.</p>
136: *
137: * <p>The default setting is to disable exact matches.</p>
138: *
139: * @return true iff exact matching is enabled
140: * @since Digester Release 1.1.1
141: */
142: public boolean isExactMatch() {
143:
144: return useExactMatch;
145: }
146:
147: /**
148: * <p>Set whether exact matching is enabled.</p>
149: *
150: * <p>See {@link #isExactMatch()}.</p>
151: *
152: * @param useExactMatch should this rule use exact method matching
153: * @since Digester Release 1.1.1
154: */
155: public void setExactMatch(boolean useExactMatch) {
156:
157: this .useExactMatch = useExactMatch;
158: }
159:
160: /**
161: * Process the end of this element.
162: */
163: public void end() throws Exception {
164:
165: // Identify the objects to be used
166: Object child = digester.peek(0);
167: Object parent = digester.peek(1);
168:
169: if (digester.log.isDebugEnabled()) {
170: if (child == null) {
171: digester.log.debug("[SetTopRule]{" + digester.match
172: + "} Call [NULL CHILD]." + methodName + "("
173: + parent + ")");
174: } else {
175: digester.log.debug("[SetTopRule]{" + digester.match
176: + "} Call " + child.getClass().getName() + "."
177: + methodName + "(" + parent + ")");
178: }
179: }
180:
181: // Call the specified method
182: IntrospectionUtils.callMethod1(child, methodName, parent,
183: paramType, digester.getClassLoader());
184:
185: }
186:
187: /**
188: * Render a printable version of this Rule.
189: */
190: public String toString() {
191:
192: StringBuffer sb = new StringBuffer("SetTopRule[");
193: sb.append("methodName=");
194: sb.append(methodName);
195: sb.append(", paramType=");
196: sb.append(paramType);
197: sb.append("]");
198: return (sb.toString());
199:
200: }
201:
202: }
|