1
2
3
4
5
6
7
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
136
137 public void onStart(ElementPath elementPath)
138 {
139 Element element = elementPath.getCurrent();
140
141 pathStack.add(path);
142
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
156
157 ElementHandler handler = (ElementHandler)handlers.get(path);
158 handlerStack.add(handler);
159
160 handler.onStart(elementPath);
161 }
162 else
163 {
164
165
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
178
179 ElementHandler handler = (ElementHandler)handlers.get(path);
180 handlerStack.remove( handlerStack.size() - 1 );
181
182 handler.onEnd(elementPath);
183 }
184 else
185 {
186
187
188 if (handlerStack.isEmpty() && (defaultHandler != null))
189 {
190 defaultHandler.onEnd(elementPath);
191 }
192 }
193
194
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
208
209
210
211
212
213
214
215
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