001    /* $Id: Rule.java 992060 2010-09-02 19:09:47Z simonetripodi $
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        @Deprecated
066        public Rule(Digester digester) {
067    
068            super();
069            setDigester(digester);
070    
071        }
072        
073        /**
074         * <p>Base constructor.
075         * Now the digester will be set when the rule is added.</p>
076         */
077        public Rule() {}
078    
079    
080        // ----------------------------------------------------- Instance Variables
081    
082    
083        /**
084         * The Digester with which this Rule is associated.
085         */
086        protected Digester digester = null;
087    
088    
089        /**
090         * The namespace URI for which this Rule is relevant, if any.
091         */
092        protected String namespaceURI = null;
093    
094    
095        // ------------------------------------------------------------- Properties
096    
097    
098        /**
099         * Return the Digester with which this Rule is associated.
100         */
101        public Digester getDigester() {
102    
103            return (this.digester);
104    
105        }
106        
107        /**
108         * Set the <code>Digester</code> with which this <code>Rule</code> is associated.
109         */
110        public void setDigester(Digester digester) {
111            
112            this.digester = digester;
113            
114        }
115    
116        /**
117         * Return the namespace URI for which this Rule is relevant, if any.
118         */
119        public String getNamespaceURI() {
120    
121            return (this.namespaceURI);
122    
123        }
124    
125    
126        /**
127         * Set the namespace URI for which this Rule is relevant, if any.
128         *
129         * @param namespaceURI Namespace URI for which this Rule is relevant,
130         *  or <code>null</code> to match independent of namespace.
131         */
132        public void setNamespaceURI(String namespaceURI) {
133    
134            this.namespaceURI = namespaceURI;
135    
136        }
137    
138    
139        // --------------------------------------------------------- Public Methods
140    
141    
142        /**
143         * This method is called when the beginning of a matching XML element
144         * is encountered.
145         *
146         * @param attributes The attribute list of this element
147         * @deprecated Use the {@link #begin(String,String,Attributes) begin}
148         *   method with <code>namespace</code> and <code>name</code>
149         *   parameters instead.
150         */
151        @Deprecated
152        public void begin(Attributes attributes) throws Exception {
153    
154            // The default implementation does nothing
155    
156        }
157    
158    
159        /**
160         * This method is called when the beginning of a matching XML element
161         * is encountered. The default implementation delegates to the deprecated
162         * method {@link #begin(Attributes) begin} without the 
163         * <code>namespace</code> and <code>name</code> parameters, to retain 
164         * backwards compatibility.
165         *
166         * @param namespace the namespace URI of the matching element, or an 
167         *   empty string if the parser is not namespace aware or the element has
168         *   no namespace
169         * @param name the local name if the parser is namespace aware, or just 
170         *   the element name otherwise
171         * @param attributes The attribute list of this element
172         * @since Digester 1.4
173         */
174        public void begin(String namespace, String name, Attributes attributes)
175            throws Exception {
176    
177            begin(attributes);
178    
179        }
180    
181    
182        /**
183         * This method is called when the body of a matching XML element
184         * is encountered.  If the element has no body, this method is
185         * called with an empty string as the body text.
186         *
187         * @param text The text of the body of this element
188         * @deprecated Use the {@link #body(String,String,String) body} method
189         *   with <code>namespace</code> and <code>name</code> parameters
190         *   instead.
191         */
192        @Deprecated
193        public void body(String text) throws Exception {
194    
195            // The default implementation does nothing
196    
197        }
198    
199    
200        /**
201         * This method is called when the body of a matching XML element is 
202         * encountered.  If the element has no body, this method is 
203         * called with an empty string as the body text.
204         * <p>
205         * The default implementation delegates to the deprecated method 
206         * {@link #body(String) body} without the <code>namespace</code> and
207         * <code>name</code> parameters, to retain backwards compatibility.
208         *
209         * @param namespace the namespace URI of the matching element, or an 
210         *   empty string if the parser is not namespace aware or the element has
211         *   no namespace
212         * @param name the local name if the parser is namespace aware, or just 
213         *   the element name otherwise
214         * @param text The text of the body of this element
215         * @since Digester 1.4
216         */
217        public void body(String namespace, String name, String text)
218            throws Exception {
219    
220            body(text);
221    
222        }
223    
224    
225        /**
226         * This method is called when the end of a matching XML element
227         * is encountered.
228         * 
229         * @deprecated Use the {@link #end(String,String) end} method with 
230         *   <code>namespace</code> and <code>name</code> parameters instead.
231         */
232        @Deprecated
233        public void end() throws Exception {
234    
235            // The default implementation does nothing
236    
237        }
238    
239    
240        /**
241         * This method is called when the end of a matching XML element
242         * is encountered. The default implementation delegates to the deprecated
243         * method {@link #end end} without the 
244         * <code>namespace</code> and <code>name</code> parameters, to retain 
245         * backwards compatibility.
246         *
247         * @param namespace the namespace URI of the matching element, or an 
248         *   empty string if the parser is not namespace aware or the element has
249         *   no namespace
250         * @param name the local name if the parser is namespace aware, or just 
251         *   the element name otherwise
252         * @since Digester 1.4
253         */
254        public void end(String namespace, String name)
255            throws Exception {
256    
257            end();
258    
259        }
260    
261    
262        /**
263         * This method is called after all parsing methods have been
264         * called, to allow Rules to remove temporary data.
265         */
266        public void finish() throws Exception {
267    
268            // The default implementation does nothing
269    
270        }
271    
272    
273    }