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