1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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 import org.apache.commons.configuration.ConfigurationRuntimeException;
29
30
31
32
33
34
35
36
37
38
39
40
41 public class DefaultConfigurationNode implements ConfigurationNode, Cloneable
42 {
43
44 private SubNodes children;
45
46
47 private SubNodes attributes;
48
49
50 private ConfigurationNode parent;
51
52
53 private Object value;
54
55
56 private Object reference;
57
58
59 private String name;
60
61
62 private boolean attribute;
63
64
65
66
67 public DefaultConfigurationNode()
68 {
69 this(null);
70 }
71
72
73
74
75
76
77
78 public DefaultConfigurationNode(String name)
79 {
80 this(name, null);
81 }
82
83
84
85
86
87
88
89
90 public DefaultConfigurationNode(String name, Object value)
91 {
92 setName(name);
93 setValue(value);
94 initSubNodes();
95 }
96
97
98
99
100
101
102 public String getName()
103 {
104 return name;
105 }
106
107
108
109
110
111
112 public void setName(String name)
113 {
114 checkState();
115 this.name = name;
116 }
117
118
119
120
121
122
123 public Object getValue()
124 {
125 return value;
126 }
127
128
129
130
131
132
133 public void setValue(Object val)
134 {
135 value = val;
136 }
137
138
139
140
141
142
143 public Object getReference()
144 {
145 return reference;
146 }
147
148
149
150
151
152
153 public void setReference(Object reference)
154 {
155 this.reference = reference;
156 }
157
158
159
160
161
162
163 public ConfigurationNode getParentNode()
164 {
165 return parent;
166 }
167
168
169
170
171
172
173 public void setParentNode(ConfigurationNode parent)
174 {
175 this.parent = parent;
176 }
177
178
179
180
181
182
183 public void addChild(ConfigurationNode child)
184 {
185 children.addNode(child);
186 child.setAttribute(false);
187 child.setParentNode(this);
188 }
189
190
191
192
193
194
195 public List<ConfigurationNode> getChildren()
196 {
197 return children.getSubNodes();
198 }
199
200
201
202
203
204
205 public int getChildrenCount()
206 {
207 return children.getSubNodes().size();
208 }
209
210
211
212
213
214
215
216 public List<ConfigurationNode> getChildren(String name)
217 {
218 return children.getSubNodes(name);
219 }
220
221
222
223
224
225
226
227
228 public int getChildrenCount(String name)
229 {
230 return children.getSubNodes(name).size();
231 }
232
233
234
235
236
237
238
239 public ConfigurationNode getChild(int index)
240 {
241 return children.getNode(index);
242 }
243
244
245
246
247
248
249
250 public boolean removeChild(ConfigurationNode child)
251 {
252 return children.removeNode(child);
253 }
254
255
256
257
258
259
260
261 public boolean removeChild(String childName)
262 {
263 return children.removeNodes(childName);
264 }
265
266
267
268
269 public void removeChildren()
270 {
271 children.clear();
272 }
273
274
275
276
277
278
279 public boolean isAttribute()
280 {
281 return attribute;
282 }
283
284
285
286
287
288
289
290 public void setAttribute(boolean f)
291 {
292 checkState();
293 attribute = f;
294 }
295
296
297
298
299
300
301 public void addAttribute(ConfigurationNode attr)
302 {
303 attributes.addNode(attr);
304 attr.setAttribute(true);
305 attr.setParentNode(this);
306 }
307
308
309
310
311
312
313
314 public List<ConfigurationNode> getAttributes()
315 {
316 return attributes.getSubNodes();
317 }
318
319
320
321
322
323
324 public int getAttributeCount()
325 {
326 return attributes.getSubNodes().size();
327 }
328
329
330
331
332
333
334
335 public List<ConfigurationNode> getAttributes(String name)
336 {
337 return attributes.getSubNodes(name);
338 }
339
340
341
342
343
344
345
346 public int getAttributeCount(String name)
347 {
348 return getAttributes(name).size();
349 }
350
351
352
353
354
355
356
357 public boolean removeAttribute(ConfigurationNode node)
358 {
359 return attributes.removeNode(node);
360 }
361
362
363
364
365
366
367
368 public boolean removeAttribute(String name)
369 {
370 return attributes.removeNodes(name);
371 }
372
373
374
375
376
377
378
379 public ConfigurationNode getAttribute(int index)
380 {
381 return attributes.getNode(index);
382 }
383
384
385
386
387 public void removeAttributes()
388 {
389 attributes.clear();
390 }
391
392
393
394
395
396
397
398 public boolean isDefined()
399 {
400 return getValue() != null || getChildrenCount() > 0
401 || getAttributeCount() > 0;
402 }
403
404
405
406
407
408
409 public void visit(ConfigurationNodeVisitor visitor)
410 {
411 if (visitor == null)
412 {
413 throw new IllegalArgumentException("Visitor must not be null!");
414 }
415
416 if (!visitor.terminate())
417 {
418 visitor.visitBeforeChildren(this);
419 children.visit(visitor);
420 attributes.visit(visitor);
421 visitor.visitAfterChildren(this);
422 }
423 }
424
425
426
427
428
429
430
431 @Override
432 public Object clone()
433 {
434 try
435 {
436 DefaultConfigurationNode copy = (DefaultConfigurationNode) super
437 .clone();
438 copy.initSubNodes();
439 return copy;
440 }
441 catch (CloneNotSupportedException cex)
442 {
443
444 throw new ConfigurationRuntimeException("Cannot clone " + getClass());
445 }
446 }
447
448
449
450
451
452
453 protected void checkState()
454 {
455 if (getParentNode() != null)
456 {
457 throw new IllegalStateException(
458 "Node cannot be modified when added to a parent!");
459 }
460 }
461
462
463
464
465
466
467
468
469
470 protected SubNodes createSubNodes(boolean attributes)
471 {
472 return new SubNodes();
473 }
474
475
476
477
478
479
480
481
482 protected void removeReference()
483 {
484 }
485
486
487
488
489 private void initSubNodes()
490 {
491 children = createSubNodes(false);
492 attributes = createSubNodes(true);
493 }
494
495
496
497
498 protected static class SubNodes
499 {
500
501 private List<ConfigurationNode> nodes;
502
503
504 private Map<String, List<ConfigurationNode>> namedNodes;
505
506
507
508
509
510
511 public void addNode(ConfigurationNode node)
512 {
513 if (node == null || node.getName() == null)
514 {
515 throw new IllegalArgumentException(
516 "Node to add must have a defined name!");
517 }
518 node.setParentNode(null);
519
520 if (nodes == null)
521 {
522 nodes = new ArrayList<ConfigurationNode>();
523 namedNodes = new HashMap<String, List<ConfigurationNode>>();
524 }
525
526 nodes.add(node);
527 List<ConfigurationNode> lst = namedNodes.get(node.getName());
528 if (lst == null)
529 {
530 lst = new LinkedList<ConfigurationNode>();
531 namedNodes.put(node.getName(), lst);
532 }
533 lst.add(node);
534 }
535
536
537
538
539
540
541
542 public boolean removeNode(ConfigurationNode node)
543 {
544 if (nodes != null && node != null && nodes.contains(node))
545 {
546 detachNode(node);
547 nodes.remove(node);
548
549 List<ConfigurationNode> lst = namedNodes.get(node.getName());
550 if (lst != null)
551 {
552 lst.remove(node);
553 if (lst.isEmpty())
554 {
555 namedNodes.remove(node.getName());
556 }
557 }
558 return true;
559 }
560
561 else
562 {
563 return false;
564 }
565 }
566
567
568
569
570
571
572
573 public boolean removeNodes(String name)
574 {
575 if (nodes != null && name != null)
576 {
577 List<ConfigurationNode> lst = namedNodes.remove(name);
578 if (lst != null)
579 {
580 detachNodes(lst);
581 nodes.removeAll(lst);
582 return true;
583 }
584 }
585 return false;
586 }
587
588
589
590
591 public void clear()
592 {
593 if (nodes != null)
594 {
595 detachNodes(nodes);
596 nodes = null;
597 namedNodes = null;
598 }
599 }
600
601
602
603
604
605
606
607
608 public ConfigurationNode getNode(int index)
609 {
610 if (nodes == null)
611 {
612 throw new IndexOutOfBoundsException("No sub nodes available!");
613 }
614 return nodes.get(index);
615 }
616
617
618
619
620
621
622
623 public List<ConfigurationNode> getSubNodes()
624 {
625 if (nodes == null)
626 {
627 return Collections.emptyList();
628 }
629 else
630 {
631 return Collections.unmodifiableList(nodes);
632 }
633 }
634
635
636
637
638
639
640
641
642
643 public List<ConfigurationNode> getSubNodes(String name)
644 {
645 if (name == null)
646 {
647 return getSubNodes();
648 }
649
650 List<ConfigurationNode> result;
651 if (nodes == null)
652 {
653 result = null;
654 }
655 else
656 {
657 result = namedNodes.get(name);
658 }
659
660 if (result == null)
661 {
662 return Collections.emptyList();
663 }
664 else
665 {
666 return Collections.unmodifiableList(result);
667 }
668 }
669
670
671
672
673
674
675 public void visit(ConfigurationNodeVisitor visitor)
676 {
677 if (nodes != null)
678 {
679 for (Iterator<ConfigurationNode> it = nodes.iterator(); it.hasNext()
680 && !visitor.terminate();)
681 {
682 it.next().visit(visitor);
683 }
684 }
685 }
686
687
688
689
690
691
692
693
694 protected void detachNode(ConfigurationNode subNode)
695 {
696 subNode.setParentNode(null);
697 if (subNode instanceof DefaultConfigurationNode)
698 {
699 ((DefaultConfigurationNode) subNode).removeReference();
700 }
701 }
702
703
704
705
706
707
708
709 protected void detachNodes(Collection<? extends ConfigurationNode> subNodes)
710 {
711 for (ConfigurationNode nd : subNodes)
712 {
713 detachNode(nd);
714 }
715 }
716 }
717 }