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    
020    package org.apache.commons.digester;
021    
022    
023    import 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    
053    public 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    }