View Javadoc

1   /*
2    * Copyright 2001-2004 (C) MetaStuff, Ltd. All Rights Reserved.
3    * 
4    * This software is open source. 
5    * See the bottom of this file for the licence.
6    * 
7    * $Id: DispatchHandler.java,v 1.9 2004/08/02 18:44:07 maartenc Exp $
8    */
9   
10  package org.dom4j.io;
11  
12  import java.util.ArrayList;
13  import java.util.HashMap;
14  
15  import org.dom4j.Element;
16  import org.dom4j.ElementHandler;
17  import org.dom4j.ElementPath;
18  
19  /*** <p><code>DispatchHandler</code> implements the <code>ElementHandler</code>
20    * interface and provides a means to register multiple <code>ElementHandler</code>
21    * instances to be used by an event based processor.  This is a special
22    * <code>ElementHandler</code> in that it's <b>onStart</b> and <b>onEnd</b>
23    * implementation methods are called for every element encountered during
24    * the parse.  It then delegates to other <code>ElementHandler</code> instances
25    * registered with it to process the elements encountered.
26    *
27    * @author <a href="mailto:dwhite@equipecom.com">Dave White</a>
28    * @version $Revision: 1.9 $
29    */
30  
31  class DispatchHandler implements ElementHandler
32  {
33      /*** Whether the parser is at the root element or not */
34      private boolean        atRoot;
35      
36      /*** The current path in the XML tree (i.e. /a/b/c) */
37      private String         path;
38      
39      /*** maintains a stack of previously encountered paths */
40      private ArrayList      pathStack;
41      
42      /*** maintains a stack of previously encountered handlers */
43      private ArrayList      handlerStack;
44      
45      /*** <code>HashMap</code> maintains the mapping between element paths and handlers */
46      private HashMap        handlers;
47      
48      /*** <code>ElementHandler</code> to use by default for element paths with no handlers registered */
49      private ElementHandler defaultHandler;
50      
51      public DispatchHandler()
52      {
53          atRoot          = true;
54          path            = "/";
55          pathStack       = new ArrayList();
56          handlerStack    = new ArrayList();
57          handlers        = new HashMap();
58      }
59      
60      /*** Adds the <code>ElementHandler</code> to be called when the 
61        * specified path is encounted.
62        *
63        * @param path is the path to be handled
64        * @param handler is the <code>ElementHandler</code> to be called
65        * by the event based processor.
66        */
67      public void addHandler(String path, ElementHandler handler)
68      {
69          handlers.put(path, handler);   
70      }
71      
72      /*** Removes the <code>ElementHandler</code> from the event based
73        * processor, for the specified path.
74        *
75        * @param path is the path to remove the <code>ElementHandler</code> for.
76        */
77      public ElementHandler removeHandler(String path)
78      {
79          return (ElementHandler)handlers.remove(path);   
80      }
81      
82       /*** @return true when an <code>ElementHandler</code> is registered for
83         * the specified path.
84         */
85      public boolean containsHandler(String path) {
86          return handlers.containsKey(path);
87      }
88       
89      /***
90       * Get the registered {@link ElementHandler} for the specified path.
91       * @param path XML path to get the handler for
92       * @return the registered handler
93       */
94      public ElementHandler getHandler(String path){
95          return (ElementHandler)handlers.get(path);
96      }
97      
98      /***
99       * Returns the number of {@link ElementHandler} objects that are waiting for their elements
100      * closing tag.
101      * @return number of active handlers
102      */
103     public int getActiveHandlerCount(){
104        return handlerStack.size();
105     }
106 
107     /*** When multiple <code>ElementHandler</code> instances have been 
108       * registered, this will set a default <code>ElementHandler</code>
109       * to be called for any path which does <b>NOT</b> have a handler
110       * registered.
111       * @param handler is the <code>ElementHandler</code> to be called
112       * by the event based processor.
113       */
114     public void setDefaultHandler(ElementHandler handler)
115     {
116         defaultHandler = handler;
117     }
118     
119     /***
120      * Used to remove all the Element Handlers and return things back to the way
121      * they were when object was created.
122      */
123     public void resetHandlers() {
124         atRoot          = true;
125         path            = "/";
126         pathStack.clear();
127         handlerStack.clear();
128         handlers.clear();
129 	defaultHandler=null;
130     }
131 
132     /*** @return the current path for the parse */
133     public String getPath() { return path; }
134     
135     // The following methods implement the ElementHandler interface
136     
137     public void onStart(ElementPath elementPath)
138     {
139         Element element = elementPath.getCurrent();
140         // Save the location of the last (i.e. parent) path 
141         pathStack.add(path);
142         // Calculate the new path
143         if (atRoot)
144         {
145             path = path + element.getName();   
146             atRoot = false;
147         }
148         else 
149         {
150             path = path + "/" + element.getName();
151         }
152         
153         if ((handlers != null) && (handlers.containsKey(path)))
154         {
155             // The current node has a handler associated with it.
156             // Find the handler and save it on the handler stack.
157             ElementHandler handler = (ElementHandler)handlers.get(path);
158             handlerStack.add(handler);
159             // Call the handlers onStart method.
160             handler.onStart(elementPath);
161         }
162         else
163         {
164             // No handler is associated with this node, so use the
165             // defaultHandler it it exists.
166             if (handlerStack.isEmpty() && (defaultHandler != null))
167             {
168                 defaultHandler.onStart(elementPath);
169             }
170         }
171     }
172     
173     public void onEnd(ElementPath elementPath)
174     {   
175         if ((handlers != null) && (handlers.containsKey(path)))
176         {
177             // This node has a handler associated with it.
178             // Find the handler and pop it from the handler stack.
179             ElementHandler handler = (ElementHandler)handlers.get(path);
180             handlerStack.remove( handlerStack.size() - 1 );
181             // Call the handlers onEnd method
182             handler.onEnd(elementPath);
183         }
184         else
185         {
186             // No handler is associated with this node, so use the
187             // defaultHandler it it exists.
188             if (handlerStack.isEmpty() && (defaultHandler != null))
189             {
190                 defaultHandler.onEnd(elementPath);
191             }
192         }
193         
194         // Set path back to its parent
195         path = (String) pathStack.remove( pathStack.size() - 1 );
196         
197         if (pathStack.size() == 0) {
198             atRoot = true;
199         }
200     }   
201 }
202 
203 
204 
205 
206 /*
207  * Redistribution and use of this software and associated documentation
208  * ("Software"), with or without modification, are permitted provided
209  * that the following conditions are met:
210  *
211  * 1. Redistributions of source code must retain copyright
212  *    statements and notices.  Redistributions must also contain a
213  *    copy of this document.
214  *
215  * 2. Redistributions in binary form must reproduce the
216  *    above copyright notice, this list of conditions and the
217  *    following disclaimer in the documentation and/or other
218  *    materials provided with the distribution.
219  *
220  * 3. The name "DOM4J" must not be used to endorse or promote
221  *    products derived from this Software without prior written
222  *    permission of MetaStuff, Ltd.  For written permission,
223  *    please contact dom4j-info@metastuff.com.
224  *
225  * 4. Products derived from this Software may not be called "DOM4J"
226  *    nor may "DOM4J" appear in their names without prior written
227  *    permission of MetaStuff, Ltd. DOM4J is a registered
228  *    trademark of MetaStuff, Ltd.
229  *
230  * 5. Due credit should be given to the DOM4J Project - 
231  *    http://www.dom4j.org
232  *
233  * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS
234  * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
235  * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
236  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
237  * METASTUFF, LTD. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
238  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
239  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
240  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
241  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
242  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
243  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
244  * OF THE POSSIBILITY OF SUCH DAMAGE.
245  *
246  * Copyright 2001-2004 (C) MetaStuff, Ltd. All Rights Reserved.
247  *
248  * $Id: DispatchHandler.java,v 1.9 2004/08/02 18:44:07 maartenc Exp $
249  */