001/* $Id: Rule.java 471661 2006-11-06 08:09:25Z skitching $
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
020package org.apache.commons.digester;
021
022
023import org.xml.sax.Attributes;
024
025
026/**
027 * Concrete implementations of this class implement actions to be taken when
028 * a corresponding nested pattern of XML elements has been matched.
029 * <p>
030 * Writing a custom Rule is considered perfectly normal when using Digester,
031 * and is encouraged whenever the default set of Rule classes don't meet your
032 * requirements; the digester framework can help process xml even when the
033 * built-in rules aren't quite what is needed. Creating a custom Rule is
034 * just as easy as subclassing javax.servlet.http.HttpServlet for webapps,
035 * or javax.swing.Action for GUI applications.
036 * <p>
037 * If a rule wishes to manipulate a digester stack (the default object stack,
038 * a named stack, or the parameter stack) then it should only ever push
039 * objects in the rule's begin method and always pop exactly the same
040 * number of objects off the stack during the rule's end method. Of course
041 * peeking at the objects on the stacks can be done from anywhere.
042 * <p>
043 * Rule objects should be stateless, ie they should not update any instance
044 * member during the parsing process. A rule instance that changes state
045 * will encounter problems if invoked in a "nested" manner; this can happen
046 * if the same instance is added to digester multiple times or if a 
047 * wildcard pattern is used which can match both an element and a child of the
048 * same element. The digester object stack and named stacks should be used to
049 * store any state that a rule requires, making the rule class safe under all
050 * possible uses.
051 */
052
053public abstract class Rule {
054
055
056    // ----------------------------------------------------------- Constructors
057
058
059    /**
060     * Constructor sets the associated Digester.
061     *
062     * @param digester The digester with which this rule is associated
063     * @deprecated The digester instance is now set in the {@link Digester#addRule} method. Use {@link #Rule()} instead.
064     */
065    public Rule(Digester digester) {
066
067        super();
068        setDigester(digester);
069
070    }
071    
072    /**
073     * <p>Base constructor.
074     * Now the digester will be set when the rule is added.</p>
075     */
076    public Rule() {}
077
078
079    // ----------------------------------------------------- Instance Variables
080
081
082    /**
083     * The Digester with which this Rule is associated.
084     */
085    protected Digester digester = null;
086
087
088    /**
089     * The namespace URI for which this Rule is relevant, if any.
090     */
091    protected String namespaceURI = null;
092
093
094    // ------------------------------------------------------------- Properties
095
096
097    /**
098     * Return the Digester with which this Rule is associated.
099     */
100    public Digester getDigester() {
101
102        return (this.digester);
103
104    }
105    
106    /**
107     * Set the <code>Digester</code> with which this <code>Rule</code> is associated.
108     */
109    public void setDigester(Digester digester) {
110        
111        this.digester = digester;
112        
113    }
114
115    /**
116     * Return the namespace URI for which this Rule is relevant, if any.
117     */
118    public String getNamespaceURI() {
119
120        return (this.namespaceURI);
121
122    }
123
124
125    /**
126     * Set the namespace URI for which this Rule is relevant, if any.
127     *
128     * @param namespaceURI Namespace URI for which this Rule is relevant,
129     *  or <code>null</code> to match independent of namespace.
130     */
131    public void setNamespaceURI(String namespaceURI) {
132
133        this.namespaceURI = namespaceURI;
134
135    }
136
137
138    // --------------------------------------------------------- Public Methods
139
140
141    /**
142     * This method is called when the beginning of a matching XML element
143     * is encountered.
144     *
145     * @param attributes The attribute list of this element
146     * @deprecated Use the {@link #begin(String,String,Attributes) begin}
147     *   method with <code>namespace</code> and <code>name</code>
148     *   parameters instead.
149     */
150    public void begin(Attributes attributes) throws Exception {
151
152        ;  // The default implementation does nothing
153
154    }
155
156
157    /**
158     * This method is called when the beginning of a matching XML element
159     * is encountered. The default implementation delegates to the deprecated
160     * method {@link #begin(Attributes) begin} without the 
161     * <code>namespace</code> and <code>name</code> parameters, to retain 
162     * backwards compatibility.
163     *
164     * @param namespace the namespace URI of the matching element, or an 
165     *   empty string if the parser is not namespace aware or the element has
166     *   no namespace
167     * @param name the local name if the parser is namespace aware, or just 
168     *   the element name otherwise
169     * @param attributes The attribute list of this element
170     * @since Digester 1.4
171     */
172    public void begin(String namespace, String name, Attributes attributes)
173        throws Exception {
174
175        begin(attributes);
176
177    }
178
179
180    /**
181     * This method is called when the body of a matching XML element
182     * is encountered.  If the element has no body, this method is
183     * called with an empty string as the body text.
184     *
185     * @param text The text of the body of this element
186     * @deprecated Use the {@link #body(String,String,String) body} method
187     *   with <code>namespace</code> and <code>name</code> parameters
188     *   instead.
189     */
190    public void body(String text) throws Exception {
191
192        ;  // The default implementation does nothing
193
194    }
195
196
197    /**
198     * This method is called when the body of a matching XML element is 
199     * encountered.  If the element has no body, this method is 
200     * called with an empty string as the body text.
201     * <p>
202     * The default implementation delegates to the deprecated method 
203     * {@link #body(String) body} without the <code>namespace</code> and
204     * <code>name</code> parameters, to retain backwards compatibility.
205     *
206     * @param namespace the namespace URI of the matching element, or an 
207     *   empty string if the parser is not namespace aware or the element has
208     *   no namespace
209     * @param name the local name if the parser is namespace aware, or just 
210     *   the element name otherwise
211     * @param text The text of the body of this element
212     * @since Digester 1.4
213     */
214    public void body(String namespace, String name, String text)
215        throws Exception {
216
217        body(text);
218
219    }
220
221
222    /**
223     * This method is called when the end of a matching XML element
224     * is encountered.
225     * 
226     * @deprecated Use the {@link #end(String,String) end} method with 
227     *   <code>namespace</code> and <code>name</code> parameters instead.
228     */
229    public void end() throws Exception {
230
231        ;  // The default implementation does nothing
232
233    }
234
235
236    /**
237     * This method is called when the end of a matching XML element
238     * is encountered. The default implementation delegates to the deprecated
239     * method {@link #end end} without the 
240     * <code>namespace</code> and <code>name</code> parameters, to retain 
241     * backwards compatibility.
242     *
243     * @param namespace the namespace URI of the matching element, or an 
244     *   empty string if the parser is not namespace aware or the element has
245     *   no namespace
246     * @param name the local name if the parser is namespace aware, or just 
247     *   the element name otherwise
248     * @since Digester 1.4
249     */
250    public void end(String namespace, String name)
251        throws Exception {
252
253        end();
254
255    }
256
257
258    /**
259     * This method is called after all parsing methods have been
260     * called, to allow Rules to remove temporary data.
261     */
262    public void finish() throws Exception {
263
264        ;  // The default implementation does nothing
265
266    }
267
268
269}