|
|||||||||||||||||||
Source file | Conditionals | Statements | Methods | TOTAL | |||||||||||||||
DispatchHandler.java | 83,3% | 64,1% | 36,4% | 62,9% |
|
1 | /* | |
2 | * Copyright 2001-2005 (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 | ||
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 | 21 | public DispatchHandler() { |
58 | 21 | atRoot = true; |
59 | 21 | path = "/"; |
60 | 21 | pathStack = new ArrayList(); |
61 | 21 | handlerStack = new ArrayList(); |
62 | 21 | 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 | 21 | public void addHandler(String handlerPath, ElementHandler handler) { |
76 | 21 | 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 | 0 | public ElementHandler removeHandler(String handlerPath) { |
89 | 0 | 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 | 0 | public boolean containsHandler(String handlerPath) { |
102 | 0 | 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 | 0 | public ElementHandler getHandler(String handlerPath) { |
114 | 0 | 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 | 0 | public int getActiveHandlerCount() { |
124 | 0 | 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 | 0 | public void setDefaultHandler(ElementHandler handler) { |
137 | 0 | 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 | 0 | public void resetHandlers() { |
145 | 0 | atRoot = true; |
146 | 0 | path = "/"; |
147 | 0 | pathStack.clear(); |
148 | 0 | handlerStack.clear(); |
149 | 0 | handlers.clear(); |
150 | 0 | defaultHandler = null; |
151 | } | |
152 | ||
153 | /** | |
154 | * DOCUMENT ME! | |
155 | * | |
156 | * @return the current path for the parse | |
157 | */ | |
158 | 0 | public String getPath() { |
159 | 0 | return path; |
160 | } | |
161 | ||
162 | // The following methods implement the ElementHandler interface | |
163 | 78 | public void onStart(ElementPath elementPath) { |
164 | 78 | Element element = elementPath.getCurrent(); |
165 | ||
166 | // Save the location of the last (i.e. parent) path | |
167 | 78 | pathStack.add(path); |
168 | ||
169 | // Calculate the new path | |
170 | 78 | if (atRoot) { |
171 | 18 | path = path + element.getName(); |
172 | 18 | atRoot = false; |
173 | } else { | |
174 | 60 | path = path + "/" + element.getName(); |
175 | } | |
176 | ||
177 | 78 | if ((handlers != null) && (handlers.containsKey(path))) { |
178 | // The current node has a handler associated with it. | |
179 | // Find the handler and save it on the handler stack. | |
180 | 54 | ElementHandler handler = (ElementHandler) handlers.get(path); |
181 | 54 | handlerStack.add(handler); |
182 | ||
183 | // Call the handlers onStart method. | |
184 | 54 | handler.onStart(elementPath); |
185 | } else { | |
186 | // No handler is associated with this node, so use the | |
187 | // defaultHandler it it exists. | |
188 | 24 | if (handlerStack.isEmpty() && (defaultHandler != null)) { |
189 | 0 | defaultHandler.onStart(elementPath); |
190 | } | |
191 | } | |
192 | } | |
193 | ||
194 | 78 | public void onEnd(ElementPath elementPath) { |
195 | 78 | if ((handlers != null) && (handlers.containsKey(path))) { |
196 | // This node has a handler associated with it. | |
197 | // Find the handler and pop it from the handler stack. | |
198 | 54 | ElementHandler handler = (ElementHandler) handlers.get(path); |
199 | 54 | handlerStack.remove(handlerStack.size() - 1); |
200 | ||
201 | // Call the handlers onEnd method | |
202 | 54 | handler.onEnd(elementPath); |
203 | } else { | |
204 | // No handler is associated with this node, so use the | |
205 | // defaultHandler it it exists. | |
206 | 24 | if (handlerStack.isEmpty() && (defaultHandler != null)) { |
207 | 0 | defaultHandler.onEnd(elementPath); |
208 | } | |
209 | } | |
210 | ||
211 | // Set path back to its parent | |
212 | 78 | path = (String) pathStack.remove(pathStack.size() - 1); |
213 | ||
214 | 78 | if (pathStack.size() == 0) { |
215 | 18 | atRoot = true; |
216 | } | |
217 | } | |
218 | } | |
219 | ||
220 | /* | |
221 | * Redistribution and use of this software and associated documentation | |
222 | * ("Software"), with or without modification, are permitted provided that the | |
223 | * following conditions are met: | |
224 | * | |
225 | * 1. Redistributions of source code must retain copyright statements and | |
226 | * notices. Redistributions must also contain a copy of this document. | |
227 | * | |
228 | * 2. Redistributions in binary form must reproduce the above copyright notice, | |
229 | * this list of conditions and the following disclaimer in the documentation | |
230 | * and/or other materials provided with the distribution. | |
231 | * | |
232 | * 3. The name "DOM4J" must not be used to endorse or promote products derived | |
233 | * from this Software without prior written permission of MetaStuff, Ltd. For | |
234 | * written permission, please contact dom4j-info@metastuff.com. | |
235 | * | |
236 | * 4. Products derived from this Software may not be called "DOM4J" nor may | |
237 | * "DOM4J" appear in their names without prior written permission of MetaStuff, | |
238 | * Ltd. DOM4J is a registered trademark of MetaStuff, Ltd. | |
239 | * | |
240 | * 5. Due credit should be given to the DOM4J Project - http://www.dom4j.org | |
241 | * | |
242 | * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND | |
243 | * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
244 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
245 | * ARE DISCLAIMED. IN NO EVENT SHALL METASTUFF, LTD. OR ITS CONTRIBUTORS BE | |
246 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
247 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
248 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
249 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
250 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
251 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
252 | * POSSIBILITY OF SUCH DAMAGE. | |
253 | * | |
254 | * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved. | |
255 | */ |
|