Clover coverage report - dom4j - 1.6.1 Coverage timestamp: ma mei 16 2005 14:23:01 GMT+01:00 FRAMES NO FRAMES |
file stats: | LOC: | 306 |  | Methods: | 10
| NCLOC: | 159 |  | Classes: | 1
Source file | Conditionals | Statements | Methods | TOTAL
Mode.java | 39,2% | 47,3% | 70% | 45,1% |

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.rule;
9 |  |
10 |  | import java.util.HashMap;
11 |  | import java.util.Map;
12 |  |
13 |  | import org.dom4j.Attribute;
14 |  | import org.dom4j.Document;
15 |  | import org.dom4j.Element;
16 |  | import org.dom4j.Node;
17 |  |
18 |  | /**
19 |  | * <p>
20 |  | * <code>Mode</code> manages a number of RuleSet instances for the mode in a
21 |  | * stylesheet. It is responsible for finding the correct rule for a given DOM4J
22 |  | * Node using the XSLT processing model uses the smallest possible RuleSet to
23 |  | * reduce the number of Rule evaluations.
24 |  | * </p>
25 |  | *
26 |  | * @author <a href="mailto:james.strachan@metastuff.com">James Strachan </a>
27 |  | * @version $Revision: 1.9 $
28 |  | */
29 |  | public class Mode {
30 |  | private RuleSet[] ruleSets = new RuleSet[Pattern.NUMBER_OF_TYPES];
31 |  |
32 |  | /** Map of exact (local) element names to RuleSet instances */
33 |  | private Map elementNameRuleSets;
34 |  |
35 |  | /** Map of exact (local) attribute names to RuleSet instances */
36 |  | private Map attributeNameRuleSets;
37 |  |
38 | 4 | public Mode() {
39 |  | }
40 |  |
41 |  | /**
42 |  | * Runs the actions associated with the given node
43 |  | *
44 |  | * @param node
45 |  | * DOCUMENT ME!
46 |  | *
47 |  | * @throws Exception
48 |  | * DOCUMENT ME!
49 |  | */
50 | 30 | public void fireRule(Node node) throws Exception {
51 | 30 | if (node != null) {
52 | 30 | Rule rule = getMatchingRule(node);
53 |  |
54 | 30 | if (rule != null) {
55 | 28 | Action action = rule.getAction();
56 |  |
57 | 28 | if (action != null) {
58 | 28 | action.run(node);
59 |  | }
60 |  | }
61 |  | }
62 |  | }
63 |  |
64 | 5 | public void applyTemplates(Element element) throws Exception {
65 | 5 | for (int i = 0, size = element.attributeCount(); i < size; i++) {
66 | 1 | Attribute attribute = element.attribute(i);
67 | 1 | fireRule(attribute);
68 |  | }
69 |  |
70 | 5 | for (int i = 0, size = element.nodeCount(); i < size; i++) {
71 | 13 | Node node = element.node(i);
72 | 13 | fireRule(node);
73 |  | }
74 |  | }
75 |  |
76 | 1 | public void applyTemplates(Document document) throws Exception {
77 | 1 | for (int i = 0, size = document.nodeCount(); i < size; i++) {
78 | 1 | Node node = document.node(i);
79 | 1 | fireRule(node);
80 |  | }
81 |  | }
82 |  |
83 | 28 | public void addRule(Rule rule) {
84 | 28 | int matchType = rule.getMatchType();
85 | 28 | String name = rule.getMatchesNodeName();
86 |  |
87 | 28 | if (name != null) {
88 | 0 | if (matchType == Node.ELEMENT_NODE) {
89 | 0 | elementNameRuleSets = addToNameMap(elementNameRuleSets, name,
90 |  | rule);
91 | 0 | } else if (matchType == Node.ATTRIBUTE_NODE) {
92 | 0 | attributeNameRuleSets = addToNameMap(attributeNameRuleSets,
93 |  | name, rule);
94 |  | }
95 |  | }
96 |  |
97 | 28 | if (matchType >= Pattern.NUMBER_OF_TYPES) {
98 | 0 | matchType = Pattern.ANY_NODE;
99 |  | }
100 |  |
101 | 28 | if (matchType == Pattern.ANY_NODE) {
102 |  | // add rule to all other RuleSets if they exist
103 | 0 | for (int i = 1, size = ruleSets.length; i < size; i++) {
104 | 0 | RuleSet ruleSet = ruleSets[i];
105 |  |
106 | 0 | if (ruleSet != null) {
107 | 0 | ruleSet.addRule(rule);
108 |  | }
109 |  | }
110 |  | }
111 |  |
112 | 28 | getRuleSet(matchType).addRule(rule);
113 |  | }
114 |  |
115 | 0 | public void removeRule(Rule rule) {
116 | 0 | int matchType = rule.getMatchType();
117 | 0 | String name = rule.getMatchesNodeName();
118 |  |
119 | 0 | if (name != null) {
120 | 0 | if (matchType == Node.ELEMENT_NODE) {
121 | 0 | removeFromNameMap(elementNameRuleSets, name, rule);
122 | 0 | } else if (matchType == Node.ATTRIBUTE_NODE) {
123 | 0 | removeFromNameMap(attributeNameRuleSets, name, rule);
124 |  | }
125 |  | }
126 |  |
127 | 0 | if (matchType >= Pattern.NUMBER_OF_TYPES) {
128 | 0 | matchType = Pattern.ANY_NODE;
129 |  | }
130 |  |
131 | 0 | getRuleSet(matchType).removeRule(rule);
132 |  |
133 | 0 | if (matchType != Pattern.ANY_NODE) {
134 | 0 | getRuleSet(Pattern.ANY_NODE).removeRule(rule);
135 |  | }
136 |  | }
137 |  |
138 |  | /**
139 |  | * Performs an XSLT processing model match for the rule which matches the
140 |  | * given Node the best.
141 |  | *
142 |  | * @param node
143 |  | * is the DOM4J Node to match against
144 |  | *
145 |  | * @return the matching Rule or no rule if none matched
146 |  | */
147 | 30 | public Rule getMatchingRule(Node node) {
148 | 30 | int matchType = node.getNodeType();
149 |  |
150 | 30 | if (matchType == Node.ELEMENT_NODE) {
151 | 12 | if (elementNameRuleSets != null) {
152 | 0 | String name = node.getName();
153 | 0 | RuleSet ruleSet = (RuleSet) elementNameRuleSets.get(name);
154 |  |
155 | 0 | if (ruleSet != null) {
156 | 0 | Rule answer = ruleSet.getMatchingRule(node);
157 |  |
158 | 0 | if (answer != null) {
159 | 0 | return answer;
160 |  | }
161 |  | }
162 |  | }
163 | 18 | } else if (matchType == Node.ATTRIBUTE_NODE) {
164 | 1 | if (attributeNameRuleSets != null) {
165 | 0 | String name = node.getName();
166 | 0 | RuleSet ruleSet = (RuleSet) attributeNameRuleSets.get(name);
167 |  |
168 | 0 | if (ruleSet != null) {
169 | 0 | Rule answer = ruleSet.getMatchingRule(node);
170 |  |
171 | 0 | if (answer != null) {
172 | 0 | return answer;
173 |  | }
174 |  | }
175 |  | }
176 |  | }
177 |  |
178 | 30 | if ((matchType < 0) || (matchType >= ruleSets.length)) {
179 | 0 | matchType = Pattern.ANY_NODE;
180 |  | }
181 |  |
182 | 30 | Rule answer = null;
183 | 30 | RuleSet ruleSet = ruleSets[matchType];
184 |  |
185 | 30 | if (ruleSet != null) {
186 |  | // try rules that match this kind of node first
187 | 28 | answer = ruleSet.getMatchingRule(node);
188 |  | }
189 |  |
190 | 30 | if ((answer == null) && (matchType != Pattern.ANY_NODE)) {
191 |  | // try general rules that match any kind of node
192 | 2 | ruleSet = ruleSets[Pattern.ANY_NODE];
193 |  |
194 | 2 | if (ruleSet != null) {
195 | 0 | answer = ruleSet.getMatchingRule(node);
196 |  | }
197 |  | }
198 |  |
199 | 30 | return answer;
200 |  | }
201 |  |
202 |  | /**
203 |  | * DOCUMENT ME!
204 |  | *
205 |  | * @param matchType
206 |  | * DOCUMENT ME!
207 |  | *
208 |  | * @return the RuleSet for the given matching type. This method will never
209 |  | * return null, a new instance will be created.
210 |  | */
211 | 28 | protected RuleSet getRuleSet(int matchType) {
212 | 28 | RuleSet ruleSet = ruleSets[matchType];
213 |  |
214 | 28 | if (ruleSet == null) {
215 | 14 | ruleSet = new RuleSet();
216 | 14 | ruleSets[matchType] = ruleSet;
217 |  |
218 |  | // add the patterns that match any node
219 | 14 | if (matchType != Pattern.ANY_NODE) {
220 | 14 | RuleSet allRules = ruleSets[Pattern.ANY_NODE];
221 |  |
222 | 14 | if (allRules != null) {
223 | 0 | ruleSet.addAll(allRules);
224 |  | }
225 |  | }
226 |  | }
227 |  |
228 | 28 | return ruleSet;
229 |  | }
230 |  |
231 |  | /**
232 |  | * Adds the Rule to a RuleSet for the given name.
233 |  | *
234 |  | * @param map
235 |  | * DOCUMENT ME!
236 |  | * @param name
237 |  | * DOCUMENT ME!
238 |  | * @param rule
239 |  | * DOCUMENT ME!
240 |  | *
241 |  | * @return the Map (which will be created if the given map was null
242 |  | */
243 | 0 | protected Map addToNameMap(Map map, String name, Rule rule) {
244 | 0 | if (map == null) {
245 | 0 | map = new HashMap();
246 |  | }
247 |  |
248 | 0 | RuleSet ruleSet = (RuleSet) map.get(name);
249 |  |
250 | 0 | if (ruleSet == null) {
251 | 0 | ruleSet = new RuleSet();
252 | 0 | map.put(name, ruleSet);
253 |  | }
254 |  |
255 | 0 | ruleSet.addRule(rule);
256 |  |
257 | 0 | return map;
258 |  | }
259 |  |
260 | 0 | protected void removeFromNameMap(Map map, String name, Rule rule) {
261 | 0 | if (map != null) {
262 | 0 | RuleSet ruleSet = (RuleSet) map.get(name);
263 |  |
264 | 0 | if (ruleSet != null) {
265 | 0 | ruleSet.removeRule(rule);
266 |  | }
267 |  | }
268 |  | }
269 |  | }
270 |  |
271 |  | /*
272 |  | * Redistribution and use of this software and associated documentation
273 |  | * ("Software"), with or without modification, are permitted provided that the
274 |  | * following conditions are met:
275 |  | *
276 |  | * 1. Redistributions of source code must retain copyright statements and
277 |  | * notices. Redistributions must also contain a copy of this document.
278 |  | *
279 |  | * 2. Redistributions in binary form must reproduce the above copyright notice,
280 |  | * this list of conditions and the following disclaimer in the documentation
281 |  | * and/or other materials provided with the distribution.
282 |  | *
283 |  | * 3. The name "DOM4J" must not be used to endorse or promote products derived
284 |  | * from this Software without prior written permission of MetaStuff, Ltd. For
285 |  | * written permission, please contact dom4j-info@metastuff.com.
286 |  | *
287 |  | * 4. Products derived from this Software may not be called "DOM4J" nor may
288 |  | * "DOM4J" appear in their names without prior written permission of MetaStuff,
289 |  | * Ltd. DOM4J is a registered trademark of MetaStuff, Ltd.
290 |  | *
291 |  | * 5. Due credit should be given to the DOM4J Project - http://www.dom4j.org
292 |  | *
293 |  | * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND
294 |  | * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
295 |  | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
296 |  | * ARE DISCLAIMED. IN NO EVENT SHALL METASTUFF, LTD. OR ITS CONTRIBUTORS BE
297 |  | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
298 |  | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
299 |  | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
300 |  | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
301 |  | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
302 |  | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
303 |  | * POSSIBILITY OF SUCH DAMAGE.
304 |  | *
305 |  | * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved.
306 |  | */