1   
2   
3   
4   
5   
6   
7   
8   package org.dom4j.io;
9   
10  import java.util.ArrayList;
11  import java.util.HashMap;
12  
13  import org.dom4j.Element;
14  import org.dom4j.ElementHandler;
15  import org.dom4j.ElementPath;
16  
17  /***
18   * <p>
19   * <code>DispatchHandler</code> implements the <code>ElementHandler</code>
20   * interface and provides a means to register multiple
21   * <code>ElementHandler</code> instances to be used by an event based
22   * processor. This is a special <code>ElementHandler</code> in that it's
23   * <b>onStart </b> and <b>onEnd </b> implementation methods are called for every
24   * element encountered during the parse. It then delegates to other
25   * <code>ElementHandler</code> instances registered with it to process the
26   * elements encountered.
27   * </p>
28   * 
29   * @author <a href="mailto:dwhite@equipecom.com">Dave White </a>
30   * @version $Revision: 1.11 $
31   */
32  class DispatchHandler implements ElementHandler {
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      /***
46       * <code>HashMap</code> maintains the mapping between element paths and
47       * handlers
48       */
49      private HashMap handlers;
50  
51      /***
52       * <code>ElementHandler</code> to use by default for element paths with no
53       * handlers registered
54       */
55      private ElementHandler defaultHandler;
56  
57      public DispatchHandler() {
58          atRoot = true;
59          path = "/";
60          pathStack = new ArrayList();
61          handlerStack = new ArrayList();
62          handlers = new HashMap();
63      }
64  
65      /***
66       * Adds the <code>ElementHandler</code> to be called when the specified
67       * path is encounted.
68       * 
69       * @param handlerPath
70       *            is the path to be handled
71       * @param handler
72       *            is the <code>ElementHandler</code> to be called by the event
73       *            based processor.
74       */
75      public void addHandler(String handlerPath, ElementHandler handler) {
76          handlers.put(handlerPath, handler);
77      }
78  
79      /***
80       * Removes the <code>ElementHandler</code> from the event based processor,
81       * for the specified path.
82       * 
83       * @param handlerPath
84       *            is the path to remove the <code>ElementHandler</code> for.
85       * 
86       * @return DOCUMENT ME!
87       */
88      public ElementHandler removeHandler(String handlerPath) {
89          return (ElementHandler) handlers.remove(handlerPath);
90      }
91  
92      /***
93       * DOCUMENT ME!
94       * 
95       * @param handlerPath
96       *            DOCUMENT ME!
97       * 
98       * @return true when an <code>ElementHandler</code> is registered for the
99       *         specified path.
100      */
101     public boolean containsHandler(String handlerPath) {
102         return handlers.containsKey(handlerPath);
103     }
104 
105     /***
106      * Get the registered {@link ElementHandler}for the specified path.
107      * 
108      * @param handlerPath
109      *            XML path to get the handler for
110      * 
111      * @return the registered handler
112      */
113     public ElementHandler getHandler(String handlerPath) {
114         return (ElementHandler) handlers.get(handlerPath);
115     }
116 
117     /***
118      * Returns the number of {@link ElementHandler}objects that are waiting for
119      * their elements closing tag.
120      * 
121      * @return number of active handlers
122      */
123     public int getActiveHandlerCount() {
124         return handlerStack.size();
125     }
126 
127     /***
128      * When multiple <code>ElementHandler</code> instances have been
129      * registered, this will set a default <code>ElementHandler</code> to be
130      * called for any path which does <b>NOT </b> have a handler registered.
131      * 
132      * @param handler
133      *            is the <code>ElementHandler</code> to be called by the event
134      *            based processor.
135      */
136     public void setDefaultHandler(ElementHandler handler) {
137         defaultHandler = handler;
138     }
139 
140     /***
141      * Used to remove all the Element Handlers and return things back to the way
142      * they were when object was created.
143      */
144     public void resetHandlers() {
145         atRoot = true;
146         path = "/";
147         pathStack.clear();
148         handlerStack.clear();
149         handlers.clear();
150         defaultHandler = null;
151     }
152 
153     /***
154      * DOCUMENT ME!
155      * 
156      * @return the current path for the parse
157      */
158     public String getPath() {
159         return path;
160     }
161 
162     
163     public void onStart(ElementPath elementPath) {
164         Element element = elementPath.getCurrent();
165 
166         
167         pathStack.add(path);
168 
169         
170         if (atRoot) {
171             path = path + element.getName();
172             atRoot = false;
173         } else {
174             path = path + "/" + element.getName();
175         }
176 
177         if ((handlers != null) && (handlers.containsKey(path))) {
178             
179             
180             ElementHandler handler = (ElementHandler) handlers.get(path);
181             handlerStack.add(handler);
182 
183             
184             handler.onStart(elementPath);
185         } else {
186             
187             
188             if (handlerStack.isEmpty() && (defaultHandler != null)) {
189                 defaultHandler.onStart(elementPath);
190             }
191         }
192     }
193 
194     public void onEnd(ElementPath elementPath) {
195         if ((handlers != null) && (handlers.containsKey(path))) {
196             
197             
198             ElementHandler handler = (ElementHandler) handlers.get(path);
199             handlerStack.remove(handlerStack.size() - 1);
200 
201             
202             handler.onEnd(elementPath);
203         } else {
204             
205             
206             if (handlerStack.isEmpty() && (defaultHandler != null)) {
207                 defaultHandler.onEnd(elementPath);
208             }
209         }
210 
211         
212         path = (String) pathStack.remove(pathStack.size() - 1);
213 
214         if (pathStack.size() == 0) {
215             atRoot = true;
216         }
217     }
218 }
219 
220 
221 
222 
223 
224 
225 
226 
227 
228 
229 
230 
231 
232 
233 
234 
235 
236 
237 
238 
239 
240 
241 
242 
243 
244 
245 
246 
247 
248 
249 
250 
251 
252 
253 
254 
255