##### Coverage Report - org.apache.commons.configuration.tree.DefaultConfigurationNode

Classes in this File | Line Coverage | Branch Coverage | Complexity
DefaultConfigurationNode |
97% | 72/74
100% | 4/4
| 1.5833333333333333;1,583
DefaultConfigurationNode$SubNodes |
100% | 61/61
100% | 18/18
| 1.5833333333333333;1,583

1 |  |
     /*
2 |  |
      * Licensed to the Apache Software Foundation (ASF) under one or more
3 |  |
      * contributor license agreements.  See the NOTICE file distributed with
4 |  |
      * this work for additional information regarding copyright ownership.
5 |  |
      * The ASF licenses this file to You under the Apache License, Version 2.0
6 |  |
      * (the "License"); you may not use this file except in compliance with
7 |  |
      * the License.  You may obtain a copy of the License at
8 |  |
      *
9 |  |
      *     http://www.apache.org/licenses/LICENSE-2.0
10 |  |
      *
11 |  |
      * Unless required by applicable law or agreed to in writing, software
12 |  |
      * distributed under the License is distributed on an "AS IS" BASIS,
13 |  |
      * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 |  |
      * See the License for the specific language governing permissions and
15 |  |
      * limitations under the License.
16 |  |
      */
17 |  |
     package org.apache.commons.configuration.tree;
18 |  |
19 |  |
     import java.util.ArrayList;
20 |  |
     import java.util.Collection;
21 |  |
     import java.util.Collections;
22 |  |
     import java.util.HashMap;
23 |  |
     import java.util.Iterator;
24 |  |
     import java.util.LinkedList;
25 |  |
     import java.util.List;
26 |  |
     import java.util.Map;
27 |  |
28 |  |
     /**
29 |  |
      * <p>
30 |  |
      * A default implementation of the <code>ConfigurationNode</code> interface.
31 |  |
      * </p>
32 |  |
      *
33 |  |
      * @since 1.3
34 |  |
      * @author Oliver Heger
35 |  |
      */
36 |  |
     public class DefaultConfigurationNode implements ConfigurationNode, Cloneable
37 |  |
     {
38 |  |
         /** Stores the children of this node. */
39 |  |
         private SubNodes children;
40 |  |
41 |  |
         /** Stores the attributes of this node. */
42 |  |
         private SubNodes attributes;
43 |  |
44 |  |
         /** Stores a reference to this node's parent. */
45 |  |
         private ConfigurationNode parent;
46 |  |
47 |  |
         /** Stores the value of this node. */
48 |  |
         private Object value;
49 |  |
50 |  |
         /** Stores the reference. */
51 |  |
         private Object reference;
52 |  |
53 |  |
         /** Stores the name of this node. */
54 |  |
         private String name;
55 |  |
56 |  |
         /** Stores a flag if this is an attribute. */
57 |  |
         private boolean attribute;
58 |  |
59 |  |
         /**
60 |  |
          * Creates a new uninitialized instance of
61 |  |
          * <code>DefaultConfigurationNode</code>.
62 |  |
          */
63 |  |
         public DefaultConfigurationNode()
64 |  |
         {
65 | 3080 |
             this(null);
66 | 3080 |
         }
67 |  |
68 |  |
         /**
69 |  |
          * Creates a new instance of <code>DefaultConfigurationNode</code> and
70 |  |
          * initializes it with the node name.
71 |  |
          *
72 |  |
          * @param name the name of this node
73 |  |
          */
74 |  |
         public DefaultConfigurationNode(String name)
75 |  |
         {
76 | 29213 |
             this(name, null);
77 | 29213 |
         }
78 |  |
79 |  |
         /**
80 |  |
          * Creates a new instance of <code>DefaultConfigurationNode</code> and
81 |  |
          * initializes it with the name and a value.
82 |  |
          *
83 |  |
          * @param name the node's name
84 |  |
          * @param value the node's value
85 |  |
          */
86 |  |
         public DefaultConfigurationNode(String name, Object value)
87 | 75131 |
         {
88 | 75131 |
             setName(name);
89 | 75131 |
             setValue(value);
90 | 75131 |
             initSubNodes();
91 | 75131 |
         }
92 |  |
93 |  |
         /**
94 |  |
          * Returns the name of this node.
95 |  |
          *
96 |  |
          * @return the name of this node
97 |  |
          */
98 |  |
         public String getName()
99 |  |
         {
100 | 223319 |
             return name;
101 |  |
         }
102 |  |
103 |  |
         /**
104 |  |
          * Sets the name of this node.
105 |  |
          *
106 |  |
          * @param name the new name
107 |  |
          */
108 |  |
         public void setName(String name)
109 |  |
         {
110 | 76776 |
             checkState();
111 | 76776 |
             this.name = name;
112 | 76776 |
         }
113 |  |
114 |  |
         /**
115 |  |
          * Returns the value of this node.
116 |  |
          *
117 |  |
          * @return the value of this node
118 |  |
          */
119 |  |
         public Object getValue()
120 |  |
         {
121 | 53295 |
             return value;
122 |  |
         }
123 |  |
124 |  |
         /**
125 |  |
          * Sets the value of this node.
126 |  |
          *
127 |  |
          * @param val the value of this node
128 |  |
          */
129 |  |
         public void setValue(Object val)
130 |  |
         {
131 | 106098 |
             value = val;
132 | 106098 |
         }
133 |  |
134 |  |
         /**
135 |  |
          * Returns the reference.
136 |  |
          *
137 |  |
          * @return the reference
138 |  |
          */
139 |  |
         public Object getReference()
140 |  |
         {
141 | 59231 |
             return reference;
142 |  |
         }
143 |  |
144 |  |
         /**
145 |  |
          * Sets the reference.
146 |  |
          *
147 |  |
          * @param reference the reference object
148 |  |
          */
149 |  |
         public void setReference(Object reference)
150 |  |
         {
151 | 25074 |
             this.reference = reference;
152 | 25074 |
         }
153 |  |
154 |  |
         /**
155 |  |
          * Returns a reference to this node's parent.
156 |  |
          *
157 |  |
          * @return the parent node or <b>null </b> if this is the root
158 |  |
          */
159 |  |
         public ConfigurationNode getParentNode()
160 |  |
         {
161 | 157133 |
             return parent;
162 |  |
         }
163 |  |
164 |  |
         /**
165 |  |
          * Sets the parent of this node.
166 |  |
          *
167 |  |
          * @param parent the parent of this node
168 |  |
          */
169 |  |
         public void setParentNode(ConfigurationNode parent)
170 |  |
         {
171 | 157543 |
             this.parent = parent;
172 | 157543 |
         }
173 |  |
174 |  |
         /**
175 |  |
          * Adds a new child to this node.
176 |  |
          *
177 |  |
          * @param child the new child
178 |  |
          */
179 |  |
         public void addChild(ConfigurationNode child)
180 |  |
         {
181 | 48247 |
             children.addNode(child);
182 | 48245 |
             child.setAttribute(false);
183 | 48245 |
             child.setParentNode(this);
184 | 48245 |
         }
185 |  |
186 |  |
         /**
187 |  |
          * Returns a list with all children of this node.
188 |  |
          *
189 |  |
          * @return a list with all child nodes
190 |  |
          */
191 |  |
         public List getChildren()
192 |  |
         {
193 | 12574 |
             return children.getSubNodes();
194 |  |
         }
195 |  |
196 |  |
         /**
197 |  |
          * Returns the number of all children of this node.
198 |  |
          *
199 |  |
          * @return the number of all children
200 |  |
          */
201 |  |
         public int getChildrenCount()
202 |  |
         {
203 | 9266 |
             return children.getSubNodes().size();
204 |  |
         }
205 |  |
206 |  |
         /**
207 |  |
          * Returns a list of all children with the given name.
208 |  |
          *
209 |  |
          * @param name the name; can be <b>null </b>, then all children are returned
210 |  |
          * @return a list of all children with the given name
211 |  |
          */
212 |  |
         public List getChildren(String name)
213 |  |
         {
214 | 13740 |
             return children.getSubNodes(name);
215 |  |
         }
216 |  |
217 |  |
         /**
218 |  |
          * Returns the number of children with the given name.
219 |  |
          *
220 |  |
          * @param name the name; can be <b>null </b>, then the number of all
221 |  |
          * children is returned
222 |  |
          * @return the number of child nodes with this name
223 |  |
          */
224 |  |
         public int getChildrenCount(String name)
225 |  |
         {
226 | 6364 |
             return children.getSubNodes(name).size();
227 |  |
         }
228 |  |
229 |  |
         /**
230 |  |
          * Returns the child node with the given index.
231 |  |
          *
232 |  |
          * @param index the index (0-based)
233 |  |
          * @return the child with this index
234 |  |
          */
235 |  |
         public ConfigurationNode getChild(int index)
236 |  |
         {
237 | 861 |
             return children.getNode(index);
238 |  |
         }
239 |  |
240 |  |
         /**
241 |  |
          * Removes the specified child node from this node.
242 |  |
          *
243 |  |
          * @param child the node to be removed
244 |  |
          * @return a flag if a node was removed
245 |  |
          */
246 |  |
         public boolean removeChild(ConfigurationNode child)
247 |  |
         {
248 | 2223 |
             return children.removeNode(child);
249 |  |
         }
250 |  |
251 |  |
         /**
252 |  |
          * Removes all children with the given name.
253 |  |
          *
254 |  |
          * @param childName the name of the children to be removed
255 |  |
          * @return a flag if at least one child node was removed
256 |  |
          */
257 |  |
         public boolean removeChild(String childName)
258 |  |
         {
259 | 9 |
             return children.removeNodes(childName);
260 |  |
         }
261 |  |
262 |  |
         /**
263 |  |
          * Removes all child nodes of this node.
264 |  |
          */
265 |  |
         public void removeChildren()
266 |  |
         {
267 | 3 |
             children.clear();
268 | 3 |
         }
269 |  |
270 |  |
         /**
271 |  |
          * Checks if this node is an attribute node.
272 |  |
          *
273 |  |
          * @return a flag if this is an attribute node
274 |  |
          */
275 |  |
         public boolean isAttribute()
276 |  |
         {
277 | 10451 |
             return attribute;
278 |  |
         }
279 |  |
280 |  |
         /**
281 |  |
          * Sets the attribute flag. Note: this method can only be called if the node
282 |  |
          * is not already part of a node hierarchy.
283 |  |
          *
284 |  |
          * @param f the attribute flag
285 |  |
          */
286 |  |
         public void setAttribute(boolean f)
287 |  |
         {
288 | 76615 |
             checkState();
289 | 76614 |
             attribute = f;
290 | 76614 |
         }
291 |  |
292 |  |
         /**
293 |  |
          * Adds the specified attribute to this node.
294 |  |
          *
295 |  |
          * @param attr the attribute to be added
296 |  |
          */
297 |  |
         public void addAttribute(ConfigurationNode attr)
298 |  |
         {
299 | 28365 |
             attributes.addNode(attr);
300 | 28365 |
             attr.setAttribute(true);
301 | 28365 |
             attr.setParentNode(this);
302 | 28365 |
         }
303 |  |
304 |  |
         /**
305 |  |
          * Returns a list with the attributes of this node. This list contains
306 |  |
          * <code>ConfigurationNode</code> objects, too.
307 |  |
          *
308 |  |
          * @return the attribute list, never <b>null </b>
309 |  |
          */
310 |  |
         public List getAttributes()
311 |  |
         {
312 | 9226 |
             return attributes.getSubNodes();
313 |  |
         }
314 |  |
315 |  |
         /**
316 |  |
          * Returns the number of attributes contained in this node.
317 |  |
          *
318 |  |
          * @return the number of attributes
319 |  |
          */
320 |  |
         public int getAttributeCount()
321 |  |
         {
322 | 2903 |
             return attributes.getSubNodes().size();
323 |  |
         }
324 |  |
325 |  |
         /**
326 |  |
          * Returns a list with all attributes of this node with the given name.
327 |  |
          *
328 |  |
          * @param name the attribute's name
329 |  |
          * @return all attributes with this name
330 |  |
          */
331 |  |
         public List getAttributes(String name)
332 |  |
         {
333 | 3518 |
             return attributes.getSubNodes(name);
334 |  |
         }
335 |  |
336 |  |
         /**
337 |  |
          * Returns the number of attributes of this node with the given name.
338 |  |
          *
339 |  |
          * @param name the name
340 |  |
          * @return the number of attributes with this name
341 |  |
          */
342 |  |
         public int getAttributeCount(String name)
343 |  |
         {
344 | 39 |
             return getAttributes(name).size();
345 |  |
         }
346 |  |
347 |  |
         /**
348 |  |
          * Removes the specified attribute.
349 |  |
          *
350 |  |
          * @param node the attribute node to be removed
351 |  |
          * @return a flag if the attribute could be removed
352 |  |
          */
353 |  |
         public boolean removeAttribute(ConfigurationNode node)
354 |  |
         {
355 | 1 |
             return attributes.removeNode(node);
356 |  |
         }
357 |  |
358 |  |
         /**
359 |  |
          * Removes all attributes with the specified name.
360 |  |
          *
361 |  |
          * @param name the name
362 |  |
          * @return a flag if at least one attribute was removed
363 |  |
          */
364 |  |
         public boolean removeAttribute(String name)
365 |  |
         {
366 | 7 |
             return attributes.removeNodes(name);
367 |  |
         }
368 |  |
369 |  |
         /**
370 |  |
          * Returns the attribute with the given index.
371 |  |
          *
372 |  |
          * @param index the index (0-based)
373 |  |
          * @return the attribute with this index
374 |  |
          */
375 |  |
         public ConfigurationNode getAttribute(int index)
376 |  |
         {
377 | 791 |
             return attributes.getNode(index);
378 |  |
         }
379 |  |
380 |  |
         /**
381 |  |
          * Removes all attributes of this node.
382 |  |
          */
383 |  |
         public void removeAttributes()
384 |  |
         {
385 | 1 |
             attributes.clear();
386 | 1 |
         }
387 |  |
388 |  |
         /**
389 |  |
          * Returns a flag if this node is defined. This means that the node contains
390 |  |
          * some data.
391 |  |
          *
392 |  |
          * @return a flag whether this node is defined
393 |  |
          */
394 |  |
         public boolean isDefined()
395 |  |
         {
396 | 1 |
             return getValue() != null || getChildrenCount() > 0
397 |  |
                     || getAttributeCount() > 0;
398 |  |
         }
399 |  |
400 |  |
         /**
401 |  |
          * Visits this node and all its sub nodes.
402 |  |
          *
403 |  |
          * @param visitor the visitor
404 |  |
          */
405 |  |
         public void visit(ConfigurationNodeVisitor visitor)
406 |  |
         {
407 | 11121 |
             if (visitor == null)
408 |  |
             {
409 | 1 |
                 throw new IllegalArgumentException("Visitor must not be null!");
410 |  |
             }
411 |  |
412 | 11120 |
             if (!visitor.terminate())
413 |  |
             {
414 | 11120 |
                 visitor.visitBeforeChildren(this);
415 | 11120 |
                 children.visit(visitor);
416 | 11120 |
                 attributes.visit(visitor);
417 | 11120 |
                 visitor.visitAfterChildren(this);
418 |  |
             } /* if */
419 | 11120 |
         }
420 |  |
421 |  |
         /**
422 |  |
          * Creates a copy of this object. This is not a deep copy, the children are
423 |  |
          * not cloned.
424 |  |
          *
425 |  |
          * @return a copy of this object
426 |  |
          */
427 |  |
         public Object clone()
428 |  |
         {
429 |  |
             try
430 |  |
             {
431 | 789 |
                 DefaultConfigurationNode copy = (DefaultConfigurationNode) super
432 |  |
                         .clone();
433 | 789 |
                 copy.initSubNodes();
434 | 789 |
                 return copy;
435 |  |
             }
436 | 0 |
             catch (CloneNotSupportedException cex)
437 |  |
             {
438 | 0 |
                 return null; // should not happen
439 |  |
             }
440 |  |
         }
441 |  |
442 |  |
         /**
443 |  |
          * Checks if a modification of this node is allowed. Some properties of a
444 |  |
          * node must not be changed when the node has a parent. This method checks
445 |  |
          * this and throws a runtime exception if necessary.
446 |  |
          */
447 |  |
         protected void checkState()
448 |  |
         {
449 | 153391 |
             if (getParentNode() != null)
450 |  |
             {
451 | 1 |
                 throw new IllegalStateException(
452 |  |
                         "Node cannot be modified when added to a parent!");
453 |  |
             } /* if */
454 | 153390 |
         }
455 |  |
456 |  |
         /**
457 |  |
          * Creates a <code>SubNodes</code> instance that is used for storing
458 |  |
          * either this node's children or attributes.
459 |  |
          *
460 |  |
          * @param attributes <b>true</b> if the returned instance is used for
461 |  |
          * storing attributes, <b>false</b> for storing child nodes
462 |  |
          * @return the <code>SubNodes</code> object to use
463 |  |
          */
464 |  |
         protected SubNodes createSubNodes(boolean attributes)
465 |  |
         {
466 | 151840 |
             return new SubNodes();
467 |  |
         }
468 |  |
469 |  |
         /**
470 |  |
          * Deals with the reference when a node is removed. This method is called
471 |  |
          * for each removed child node or attribute. It can be overloaded in sub
472 |  |
          * classes, for which the reference has a concrete meaning and remove
473 |  |
          * operations need some update actions. This default implementation is
474 |  |
          * empty.
475 |  |
          */
476 |  |
         protected void removeReference()
477 |  |
         {
478 | 250 |
         }
479 |  |
480 |  |
         /**
481 |  |
          * Helper method for initializing the sub nodes objects.
482 |  |
          */
483 |  |
         private void initSubNodes()
484 |  |
         {
485 | 75920 |
             children = createSubNodes(false);
486 | 75920 |
             attributes = createSubNodes(true);
487 | 75920 |
         }
488 |  |
489 |  |
         /**
490 |  |
          * An internally used helper class for managing a collection of sub nodes.
491 |  |
          */
492 | 151840 |
         protected static class SubNodes
493 |  |
         {
494 |  |
             /** Stores a list for the sub nodes. */
495 |  |
             private List nodes;
496 |  |
497 |  |
             /** Stores a map for accessing subnodes by name. */
498 |  |
             private Map namedNodes;
499 |  |
500 |  |
             /**
501 |  |
              * Adds a new sub node.
502 |  |
              *
503 |  |
              * @param node the node to add
504 |  |
              */
505 |  |
             public void addNode(ConfigurationNode node)
506 |  |
             {
507 | 76612 |
                 if (node == null || node.getName() == null)
508 |  |
                 {
509 | 2 |
                     throw new IllegalArgumentException(
510 |  |
                             "Node to add must have a defined name!");
511 |  |
                 }
512 | 76610 |
                 node.setParentNode(null);  // reset, will later be set
513 |  |
514 | 76610 |
                 if (nodes == null)
515 |  |
                 {
516 | 39142 |
                     nodes = new ArrayList();
517 | 39142 |
                     namedNodes = new HashMap();
518 |  |
                 }
519 |  |
520 | 76610 |
                 nodes.add(node);
521 | 76610 |
                 List lst = (List) namedNodes.get(node.getName());
522 | 76610 |
                 if (lst == null)
523 |  |
                 {
524 | 53770 |
                     lst = new LinkedList();
525 | 53770 |
                     namedNodes.put(node.getName(), lst);
526 |  |
                 }
527 | 76610 |
                 lst.add(node);
528 | 76610 |
             }
529 |  |
530 |  |
             /**
531 |  |
              * Removes a sub node.
532 |  |
              *
533 |  |
              * @param node the node to remove
534 |  |
              * @return a flag if the node could be removed
535 |  |
              */
536 |  |
             public boolean removeNode(ConfigurationNode node)
537 |  |
             {
538 | 2224 |
                 if (nodes != null && node != null && nodes.contains(node))
539 |  |
                 {
540 | 1878 |
                     detachNode(node);
541 | 1878 |
                     nodes.remove(node);
542 |  |
543 | 1878 |
                     List lst = (List) namedNodes.get(node.getName());
544 | 1878 |
                     if (lst != null)
545 |  |
                     {
546 | 1878 |
                         lst.remove(node);
547 | 1878 |
                         if (lst.isEmpty())
548 |  |
                         {
549 | 1088 |
                             namedNodes.remove(node.getName());
550 |  |
                         }
551 |  |
                     }
552 | 1878 |
                     return true;
553 |  |
                 }
554 |  |
555 |  |
                 else
556 |  |
                 {
557 | 346 |
                     return false;
558 |  |
                 }
559 |  |
             }
560 |  |
561 |  |
             /**
562 |  |
              * Removes all sub nodes with the given name.
563 |  |
              *
564 |  |
              * @param name the name
565 |  |
              * @return a flag if at least on sub node was removed
566 |  |
              */
567 |  |
             public boolean removeNodes(String name)
568 |  |
             {
569 | 16 |
                 if (nodes != null && name != null)
570 |  |
                 {
571 | 9 |
                     List lst = (List) namedNodes.remove(name);
572 | 9 |
                     if (lst != null)
573 |  |
                     {
574 | 7 |
                         detachNodes(lst);
575 | 7 |
                         nodes.removeAll(lst);
576 | 7 |
                         return true;
577 |  |
                     }
578 |  |
                 }
579 | 9 |
                 return false;
580 |  |
             }
581 |  |
582 |  |
             /**
583 |  |
              * Removes all sub nodes.
584 |  |
              */
585 |  |
             public void clear()
586 |  |
             {
587 | 4 |
                 if (nodes != null)
588 |  |
                 {
589 | 3 |
                     detachNodes(nodes);
590 | 3 |
                     nodes = null;
591 | 3 |
                     namedNodes = null;
592 |  |
                 }
593 | 4 |
             }
594 |  |
595 |  |
             /**
596 |  |
              * Returns the node with the given index. If this index cannot be found,
597 |  |
              * an <code>IndexOutOfBoundException</code> exception will be thrown.
598 |  |
              *
599 |  |
              * @param index the index (0-based)
600 |  |
              * @return the sub node at the specified index
601 |  |
              */
602 |  |
             public ConfigurationNode getNode(int index)
603 |  |
             {
604 | 1652 |
                 if (nodes == null)
605 |  |
                 {
606 | 1 |
                     throw new IndexOutOfBoundsException("No sub nodes available!");
607 |  |
                 }
608 | 1651 |
                 return (ConfigurationNode) nodes.get(index);
609 |  |
             }
610 |  |
611 |  |
             /**
612 |  |
              * Returns a list with all stored sub nodes. The return value is never
613 |  |
              * <b>null</b>.
614 |  |
              *
615 |  |
              * @return a list with the sub nodes
616 |  |
              */
617 |  |
             public List getSubNodes()
618 |  |
             {
619 | 33970 |
                 return (nodes == null) ? Collections.EMPTY_LIST : Collections
620 |  |
                         .unmodifiableList(nodes);
621 |  |
             }
622 |  |
623 |  |
             /**
624 |  |
              * Returns a list of the sub nodes with the given name. The return value
625 |  |
              * is never <b>null</b>.
626 |  |
              *
627 |  |
              * @param name the name; if <b>null</b> is passed, all sub nodes will
628 |  |
              * be returned
629 |  |
              * @return all sub nodes with this name
630 |  |
              */
631 |  |
             public List getSubNodes(String name)
632 |  |
             {
633 | 23622 |
                 if (name == null)
634 |  |
                 {
635 | 1 |
                     return getSubNodes();
636 |  |
                 }
637 |  |
638 |  |
                 List result;
639 | 23621 |
                 if (nodes == null)
640 |  |
                 {
641 | 1119 |
                     result = null;
642 | 1119 |
                 }
643 |  |
                 else
644 |  |
                 {
645 | 22502 |
                     result = (List) namedNodes.get(name);
646 |  |
                 }
647 |  |
648 | 23621 |
                 return (result == null) ? Collections.EMPTY_LIST : Collections
649 |  |
                         .unmodifiableList(result);
650 |  |
             }
651 |  |
652 |  |
             /**
653 |  |
              * Let the passed in visitor visit all sub nodes.
654 |  |
              *
655 |  |
              * @param visitor the visitor
656 |  |
              */
657 |  |
             public void visit(ConfigurationNodeVisitor visitor)
658 |  |
             {
659 | 22240 |
                 if (nodes != null)
660 |  |
                 {
661 | 5251 |
                     for (Iterator it = nodes.iterator(); it.hasNext()
662 | 13062 |
                             && !visitor.terminate();)
663 |  |
                     {
664 | 7811 |
                         ((ConfigurationNode) it.next()).visit(visitor);
665 | 7811 |
                     }
666 |  |
                 }
667 | 22240 |
             }
668 |  |
669 |  |
             /**
670 |  |
              * This method is called whenever a sub node is removed from this
671 |  |
              * object. It ensures that the removed node's parent is reset and its
672 |  |
              * <code>removeReference()</code> method gets called.
673 |  |
              *
674 |  |
              * @param subNode the node to be removed
675 |  |
              */
676 |  |
             protected void detachNode(ConfigurationNode subNode)
677 |  |
             {
678 | 1903 |
                 subNode.setParentNode(null);
679 | 1903 |
                 if (subNode instanceof DefaultConfigurationNode)
680 |  |
                 {
681 | 1903 |
                     ((DefaultConfigurationNode) subNode).removeReference();
682 |  |
                 }
683 | 1903 |
             }
684 |  |
685 |  |
             /**
686 |  |
              * Detaches a list of sub nodes. This method calls
687 |  |
              * <code>detachNode()</code> for each node contained in the list.
688 |  |
              *
689 |  |
              * @param subNodes the list with nodes to be detached
690 |  |
              */
691 |  |
             protected void detachNodes(Collection subNodes)
692 |  |
             {
693 | 10 |
                 for (Iterator it = subNodes.iterator(); it.hasNext();)
694 |  |
                 {
695 | 25 |
                     detachNode((ConfigurationNode) it.next());
696 | 25 |
                 }
697 | 10 |
             }
698 |  |
         }
699 |  |
     }