001: /* $Id: CallParamRule.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.xml.sax.Attributes;
022:
023: /**
024: * <p>Rule implementation that saves a parameter for use by a surrounding
025: * <code>CallMethodRule<code>.</p>
026: *
027: * <p>This parameter may be:
028: * <ul>
029: * <li>from an attribute of the current element
030: * See {@link #CallParamRule(int paramIndex, String attributeName)}
031: * <li>from current the element body
032: * See {@link #CallParamRule(int paramIndex)}
033: * <li>from the top object on the stack.
034: * See {@link #CallParamRule(int paramIndex, boolean fromStack)}
035: * <li>the current path being processed (separate <code>Rule</code>).
036: * See {@link PathCallParamRule}
037: * </ul>
038: * </p>
039: */
040:
041: public class CallParamRule extends Rule {
042:
043: // ----------------------------------------------------------- Constructors
044:
045: /**
046: * Construct a "call parameter" rule that will save the body text of this
047: * element as the parameter value.
048: *
049: * @param digester The associated Digester
050: * @param paramIndex The zero-relative parameter number
051: *
052: * @deprecated The digester instance is now set in the {@link Digester#addRule} method.
053: * Use {@link #CallParamRule(int paramIndex)} instead.
054: */
055: public CallParamRule(Digester digester, int paramIndex) {
056:
057: this (paramIndex);
058:
059: }
060:
061: /**
062: * Construct a "call parameter" rule that will save the value of the
063: * specified attribute as the parameter value.
064: *
065: * @param digester The associated Digester
066: * @param paramIndex The zero-relative parameter number
067: * @param attributeName The name of the attribute to save
068: *
069: * @deprecated The digester instance is now set in the {@link Digester#addRule} method.
070: * Use {@link #CallParamRule(int paramIndex, String attributeName)} instead.
071: */
072: public CallParamRule(Digester digester, int paramIndex,
073: String attributeName) {
074:
075: this (paramIndex, attributeName);
076:
077: }
078:
079: /**
080: * Construct a "call parameter" rule that will save the body text of this
081: * element as the parameter value.
082: *
083: * @param paramIndex The zero-relative parameter number
084: */
085: public CallParamRule(int paramIndex) {
086:
087: this (paramIndex, null);
088:
089: }
090:
091: /**
092: * Construct a "call parameter" rule that will save the value of the
093: * specified attribute as the parameter value.
094: *
095: * @param paramIndex The zero-relative parameter number
096: * @param attributeName The name of the attribute to save
097: */
098: public CallParamRule(int paramIndex, String attributeName) {
099:
100: this .paramIndex = paramIndex;
101: this .attributeName = attributeName;
102:
103: }
104:
105: /**
106: * Construct a "call parameter" rule.
107: *
108: * @param paramIndex The zero-relative parameter number
109: * @param fromStack should this parameter be taken from the top of the stack?
110: */
111: public CallParamRule(int paramIndex, boolean fromStack) {
112:
113: this .paramIndex = paramIndex;
114: this .fromStack = fromStack;
115:
116: }
117:
118: /**
119: * Constructs a "call parameter" rule which sets a parameter from the stack.
120: * If the stack contains too few objects, then the parameter will be set to null.
121: *
122: * @param paramIndex The zero-relative parameter number
123: * @param stackIndex the index of the object which will be passed as a parameter.
124: * The zeroth object is the top of the stack, 1 is the next object down and so on.
125: */
126: public CallParamRule(int paramIndex, int stackIndex) {
127:
128: this .paramIndex = paramIndex;
129: this .fromStack = true;
130: this .stackIndex = stackIndex;
131: }
132:
133: // ----------------------------------------------------- Instance Variables
134:
135: /**
136: * The attribute from which to save the parameter value
137: */
138: protected String attributeName = null;
139:
140: /**
141: * The zero-relative index of the parameter we are saving.
142: */
143: protected int paramIndex = 0;
144:
145: /**
146: * Is the parameter to be set from the stack?
147: */
148: protected boolean fromStack = false;
149:
150: /**
151: * The position of the object from the top of the stack
152: */
153: protected int stackIndex = 0;
154:
155: /**
156: * Stack is used to allow nested body text to be processed.
157: * Lazy creation.
158: */
159: protected ArrayStack bodyTextStack;
160:
161: // --------------------------------------------------------- Public Methods
162:
163: /**
164: * Process the start of this element.
165: *
166: * @param attributes The attribute list for this element
167: */
168: public void begin(Attributes attributes) throws Exception {
169:
170: Object param = null;
171:
172: if (attributeName != null) {
173:
174: param = attributes.getValue(attributeName);
175:
176: } else if (fromStack) {
177:
178: param = digester.peek(stackIndex);
179:
180: if (digester.log.isDebugEnabled()) {
181:
182: StringBuffer sb = new StringBuffer("[CallParamRule]{");
183: sb.append(digester.match);
184: sb.append("} Save from stack; from stack?").append(
185: fromStack);
186: sb.append("; object=").append(param);
187: digester.log.debug(sb.toString());
188: }
189: }
190:
191: // Have to save the param object to the param stack frame here.
192: // Can't wait until end(). Otherwise, the object will be lost.
193: // We can't save the object as instance variables, as
194: // the instance variables will be overwritten
195: // if this CallParamRule is reused in subsequent nesting.
196:
197: if (param != null) {
198: Object parameters[] = (Object[]) digester.peekParams();
199: parameters[paramIndex] = param;
200: }
201: }
202:
203: /**
204: * Process the body text of this element.
205: *
206: * @param bodyText The body text of this element
207: */
208: public void body(String bodyText) throws Exception {
209:
210: if (attributeName == null && !fromStack) {
211: // We must wait to set the parameter until end
212: // so that we can make sure that the right set of parameters
213: // is at the top of the stack
214: if (bodyTextStack == null) {
215: bodyTextStack = new ArrayStack();
216: }
217: bodyTextStack.push(bodyText.trim());
218: }
219:
220: }
221:
222: /**
223: * Process any body texts now.
224: */
225: public void end(String namespace, String name) {
226: if (bodyTextStack != null && !bodyTextStack.empty()) {
227: // what we do now is push one parameter onto the top set of parameters
228: Object parameters[] = (Object[]) digester.peekParams();
229: parameters[paramIndex] = bodyTextStack.pop();
230: }
231: }
232:
233: /**
234: * Render a printable version of this Rule.
235: */
236: public String toString() {
237:
238: StringBuffer sb = new StringBuffer("CallParamRule[");
239: sb.append("paramIndex=");
240: sb.append(paramIndex);
241: sb.append(", attributeName=");
242: sb.append(attributeName);
243: sb.append(", from stack=");
244: sb.append(fromStack);
245: sb.append("]");
246: return (sb.toString());
247:
248: }
249:
250: }
|