1 16 17 package org.apache.commons.configuration; 18 19 import java.io.Serializable ; 20 import java.util.ArrayList ; 21 import java.util.Collection ; 22 import java.util.HashSet ; 23 import java.util.Iterator ; 24 import java.util.LinkedList ; 25 import java.util.List ; 26 import java.util.Set ; 27 import java.util.Stack ; 28 29 import org.apache.commons.collections.map.LinkedMap; 30 import org.apache.commons.lang.StringUtils; 31 32 95 public class HierarchicalConfiguration extends AbstractConfiguration 96 { 97 98 private static final String NEW_KEY = "newKey"; 99 100 101 private Node root = new Node(); 102 103 106 public HierarchicalConfiguration() 107 { 108 super(); 109 } 110 111 116 public Node getRoot() 117 { 118 return root; 119 } 120 121 126 public void setRoot(Node node) 127 { 128 if (node == null) 129 { 130 throw new IllegalArgumentException ("Root node must not be null!"); 131 } 132 root = node; 133 } 134 135 142 public Object getProperty(String key) 143 { 144 List nodes = fetchNodeList(key); 145 146 if (nodes.size() == 0) 147 { 148 return null; 149 } 150 else 151 { 152 List list = new ArrayList (); 153 for (Iterator it = nodes.iterator(); it.hasNext();) 154 { 155 Node node = (Node) it.next(); 156 if (node.getValue() != null) 157 { 158 list.add(node.getValue()); 159 } 160 } 161 162 if (list.size() < 1) 163 { 164 return null; 165 } 166 else 167 { 168 return (list.size() == 1) ? list.get(0) : list; 169 } 170 } 171 } 172 173 245 protected void addPropertyDirect(String key, Object obj) 246 { 247 ConfigurationKey.KeyIterator it = new ConfigurationKey(key).iterator(); 248 Node parent = fetchAddNode(it, getRoot()); 249 250 Node child = createNode(it.currentKey(true)); 251 child.setValue(obj); 252 parent.addChild(child); 253 } 254 255 268 public void addNodes(String key, Collection nodes) 269 { 270 if (nodes == null || nodes.isEmpty()) 271 { 272 return; 273 } 274 275 Node parent; 276 if (StringUtils.isEmpty(key)) 277 { 278 parent = getRoot(); 279 } 280 else 281 { 282 ConfigurationKey.KeyIterator kit = new ConfigurationKey(key).iterator(); 283 parent = fetchAddNode(kit, getRoot()); 284 285 ConfigurationKey keyNew = new ConfigurationKey(kit.currentKey(true)); 288 keyNew.append(NEW_KEY); 289 parent = fetchAddNode(keyNew.iterator(), parent); 290 } 291 292 for (Iterator it = nodes.iterator(); it.hasNext();) 293 { 294 parent.addChild((Node) it.next()); 295 } 296 } 297 298 304 public boolean isEmpty() 305 { 306 return !nodeDefined(getRoot()); 307 } 308 309 318 public Configuration subset(String prefix) 319 { 320 Collection nodes = fetchNodeList(prefix); 321 if (nodes.isEmpty()) 322 { 323 return new HierarchicalConfiguration(); 324 } 325 326 HierarchicalConfiguration result = new HierarchicalConfiguration(); 327 CloneVisitor visitor = new CloneVisitor(); 328 329 for (Iterator it = nodes.iterator(); it.hasNext();) 330 { 331 Node nd = (Node) it.next(); 332 nd.visit(visitor, null); 333 334 List children = visitor.getClone().getChildren(); 335 if (children.size() > 0) 336 { 337 for (int i = 0; i < children.size(); i++) 338 { 339 result.getRoot().addChild((Node) children.get(i)); 340 } 341 } 342 } 343 344 return (result.isEmpty()) ? new HierarchicalConfiguration() : result; 345 } 346 347 357 public boolean containsKey(String key) 358 { 359 return getProperty(key) != null; 360 } 361 362 365 public void setProperty(String key, Object value) 366 { 367 Iterator itNodes = fetchNodeList(key).iterator(); 368 Iterator itValues = PropertyConverter.toIterator(value, getDelimiter()); 369 while (itNodes.hasNext() && itValues.hasNext()) 370 { 371 ((Node) itNodes.next()).setValue(itValues.next()); 372 } 373 374 while (itValues.hasNext()) 376 { 377 addPropertyDirect(key, itValues.next()); 378 } 379 380 while (itNodes.hasNext()) 382 { 383 clearNode((Node) itNodes.next()); 384 } 385 } 386 387 395 public void clearTree(String key) 396 { 397 List nodes = fetchNodeList(key); 398 399 for (Iterator it = nodes.iterator(); it.hasNext();) 400 { 401 removeNode((Node) it.next()); 402 } 403 } 404 405 412 public void clearProperty(String key) 413 { 414 List nodes = fetchNodeList(key); 415 416 for (Iterator it = nodes.iterator(); it.hasNext();) 417 { 418 clearNode((Node) it.next()); 419 } 420 } 421 422 429 public Iterator getKeys() 430 { 431 DefinedKeysVisitor visitor = new DefinedKeysVisitor(); 432 getRoot().visit(visitor, new ConfigurationKey()); 433 return visitor.getKeyList().iterator(); 434 } 435 436 444 public Iterator getKeys(String prefix) 445 { 446 DefinedKeysVisitor visitor = new DefinedKeysVisitor(prefix); 447 List nodes = fetchNodeList(prefix); 448 ConfigurationKey key = new ConfigurationKey(); 449 450 for (Iterator itNodes = nodes.iterator(); itNodes.hasNext();) 451 { 452 Node node = (Node) itNodes.next(); 453 for (Iterator it = node.getChildren().iterator(); it.hasNext();) 454 { 455 ((Node) it.next()).visit(visitor, key); 456 } 457 } 458 459 return visitor.getKeyList().iterator(); 460 } 461 462 471 public int getMaxIndex(String key) 472 { 473 return fetchNodeList(key).size() - 1; 474 } 475 476 483 protected List fetchNodeList(String key) 484 { 485 List nodes = new LinkedList (); 486 findPropertyNodes(new ConfigurationKey(key).iterator(), getRoot(), nodes); 487 return nodes; 488 } 489 490 499 protected void findPropertyNodes(ConfigurationKey.KeyIterator keyPart, Node node, Collection data) 500 { 501 if (!keyPart.hasNext()) 502 { 503 data.add(node); 504 } 505 else 506 { 507 String key = keyPart.nextKey(true); 508 List children = node.getChildren(key); 509 if (keyPart.hasIndex()) 510 { 511 if (keyPart.getIndex() < children.size() && keyPart.getIndex() >= 0) 512 { 513 findPropertyNodes((ConfigurationKey.KeyIterator) keyPart.clone(), (Node) children.get(keyPart 514 .getIndex()), data); 515 } 516 } 517 else 518 { 519 for (Iterator it = children.iterator(); it.hasNext();) 520 { 521 findPropertyNodes((ConfigurationKey.KeyIterator) keyPart.clone(), (Node) it.next(), data); 522 } 523 } 524 } 525 } 526 527 533 protected boolean nodeDefined(Node node) 534 { 535 DefinedVisitor visitor = new DefinedVisitor(); 536 node.visit(visitor, null); 537 return visitor.isDefined(); 538 } 539 540 547 protected void removeNode(Node node) 548 { 549 Node parent = node.getParent(); 550 if (parent != null) 551 { 552 parent.remove(node); 553 if (!nodeDefined(parent)) 554 { 555 removeNode(parent); 556 } 557 } 558 } 559 560 566 protected void clearNode(Node node) 567 { 568 node.setValue(null); 569 if (!nodeDefined(node)) 570 { 571 removeNode(node); 572 } 573 } 574 575 584 protected Node fetchAddNode(ConfigurationKey.KeyIterator keyIt, Node startNode) 585 { 586 if (!keyIt.hasNext()) 587 { 588 throw new IllegalArgumentException ("Key must be defined!"); 589 } 590 591 return createAddPath(keyIt, findLastPathNode(keyIt, startNode)); 592 } 593 594 603 protected Node findLastPathNode(ConfigurationKey.KeyIterator keyIt, Node node) 604 { 605 String keyPart = keyIt.nextKey(true); 606 607 if (keyIt.hasNext()) 608 { 609 List list = node.getChildren(keyPart); 610 int idx = (keyIt.hasIndex()) ? keyIt.getIndex() : list.size() - 1; 611 if (idx < 0 || idx >= list.size()) 612 { 613 return node; 614 } 615 else 616 { 617 return findLastPathNode(keyIt, (Node) list.get(idx)); 618 } 619 } 620 621 else 622 { 623 return node; 624 } 625 } 626 627 636 protected Node createAddPath(ConfigurationKey.KeyIterator keyIt, Node root) 637 { 638 if (keyIt.hasNext()) 639 { 640 Node child = createNode(keyIt.currentKey(true)); 641 root.addChild(child); 642 keyIt.next(); 643 return createAddPath(keyIt, child); 644 } 645 else 646 { 647 return root; 648 } 649 } 650 651 660 protected Node createNode(String name) 661 { 662 return new Node(name); 663 } 664 665 670 public static class Node implements Serializable , Cloneable 671 { 672 673 private Node parent; 674 675 676 private String name; 677 678 679 private Object value; 680 681 682 private Object reference; 683 684 685 private LinkedMap children; 687 691 694 public Node() 695 { 696 this(null); 697 } 698 699 704 public Node(String name) 705 { 706 setName(name); 707 } 708 709 714 public String getName() 715 { 716 return name; 717 } 718 719 724 public Object getValue() 725 { 726 return value; 727 } 728 729 734 public Node getParent() 735 { 736 return parent; 737 } 738 739 744 public void setName(String string) 745 { 746 name = string; 747 } 748 749 754 public void setValue(Object object) 755 { 756 value = object; 757 } 758 759 764 public void setParent(Node node) 765 { 766 parent = node; 767 } 768 769 774 public Object getReference() 775 { 776 return reference; 777 } 778 779 789 public void setReference(Object ref) 790 { 791 reference = ref; 792 } 793 794 800 public void addChild(Node child) 801 { 802 if (children == null) 803 { 804 children = new LinkedMap(); 805 } 806 807 List c = (List ) children.get(child.getName()); 808 if (c == null) 809 { 810 c = new ArrayList (); 811 children.put(child.getName(), c); 812 } 813 814 c.add(child); 815 child.setParent(this); 816 } 817 818 824 public List getChildren() 825 { 826 List result = new ArrayList (); 827 828 if (children != null) 829 { 830 for (Iterator it = children.values().iterator(); it.hasNext();) 831 { 832 result.addAll((Collection ) it.next()); 833 } 834 } 835 836 return result; 837 } 838 839 846 public List getChildren(String name) 847 { 848 if (name == null || children == null) 849 { 850 return getChildren(); 851 } 852 853 List list = new ArrayList (); 854 List c = (List ) children.get(name); 855 if (c != null) 856 { 857 list.addAll(c); 858 } 859 860 return list; 861 } 862 863 869 public boolean remove(Node child) 870 { 871 if (children == null) 872 { 873 return false; 874 } 875 876 List c = (List ) children.get(child.getName()); 877 if (c == null) 878 { 879 return false; 880 } 881 882 else 883 { 884 if (c.remove(child)) 885 { 886 child.removeReference(); 887 if (c.isEmpty()) 888 { 889 children.remove(child.getName()); 890 } 891 return true; 892 } 893 else 894 { 895 return false; 896 } 897 } 898 } 899 900 906 public boolean remove(String name) 907 { 908 if (children == null) 909 { 910 return false; 911 } 912 913 List nodes = (List ) children.remove(name); 914 if (nodes != null) 915 { 916 nodesRemoved(nodes); 917 return true; 918 } 919 else 920 { 921 return false; 922 } 923 } 924 925 928 public void removeChildren() 929 { 930 if (children != null) 931 { 932 Iterator it = children.values().iterator(); 933 children = null; 934 while (it.hasNext()) 935 { 936 nodesRemoved((Collection ) it.next()); 937 } 938 } 939 } 940 941 952 public void visit(NodeVisitor visitor, ConfigurationKey key) 953 { 954 int length = 0; 955 if (key != null) 956 { 957 length = key.length(); 958 if (getName() != null) 959 { 960 key.append(getName()); 961 } 962 } 963 964 visitor.visitBeforeChildren(this, key); 965 966 if (children != null) 967 { 968 for (Iterator it = children.values().iterator(); it.hasNext() && !visitor.terminate();) 969 { 970 Collection col = (Collection ) it.next(); 971 for (Iterator it2 = col.iterator(); it2.hasNext() && !visitor.terminate();) 972 { 973 ((Node) it2.next()).visit(visitor, key); 974 } 975 } 976 } 977 978 if (key != null) 979 { 980 key.setLength(length); 981 } 982 visitor.visitAfterChildren(this, key); 983 } 984 985 991 public Object clone() 992 { 993 try 994 { 995 return super.clone(); 996 } 997 catch (CloneNotSupportedException cex) 998 { 999 return null; } 1001 } 1002 1003 1010 protected void removeReference() 1011 { 1012 } 1013 1014 1021 private void nodesRemoved(Collection nodes) 1022 { 1023 for (Iterator it = nodes.iterator(); it.hasNext();) 1024 { 1025 ((Node) it.next()).removeReference(); 1026 } 1027 } 1028 } 1029 1030 1040 public static class NodeVisitor 1041 { 1042 1049 public void visitBeforeChildren(Node node, ConfigurationKey key) 1050 { 1051 } 1052 1053 1061 public void visitAfterChildren(Node node, ConfigurationKey key) 1062 { 1063 } 1064 1065 1074 public boolean terminate() 1075 { 1076 return false; 1077 } 1078 } 1079 1080 1086 static class DefinedVisitor extends NodeVisitor 1087 { 1088 1089 private boolean defined; 1090 1091 1097 public boolean terminate() 1098 { 1099 return isDefined(); 1100 } 1101 1102 1108 public void visitBeforeChildren(Node node, ConfigurationKey key) 1109 { 1110 defined = node.getValue() != null; 1111 } 1112 1113 1118 public boolean isDefined() 1119 { 1120 return defined; 1121 } 1122 } 1123 1124 1129 static class DefinedKeysVisitor extends NodeVisitor 1130 { 1131 1132 private Set keyList; 1133 1134 1135 private String prefix; 1136 1137 1140 public DefinedKeysVisitor() 1141 { 1142 keyList = new HashSet (); 1143 } 1144 1145 1151 public DefinedKeysVisitor(String prefix) 1152 { 1153 this(); 1154 this.prefix = prefix; 1155 } 1156 1157 1162 public Set getKeyList() 1163 { 1164 return keyList; 1165 } 1166 1167 1174 public void visitBeforeChildren(Node node, ConfigurationKey key) 1175 { 1176 if (node.getValue() != null && key != null) 1177 { 1178 addKey(key); 1179 } 1180 } 1181 1182 1187 protected void addKey(ConfigurationKey key) 1188 { 1189 if (prefix == null) 1190 { 1191 keyList.add(key.toString()); 1192 } 1193 else 1194 { 1195 StringBuffer buf = new StringBuffer (prefix); 1196 if (!key.isAttributeKey()) 1197 { 1198 buf.append(ConfigurationKey.PROPERTY_DELIMITER); 1199 } 1200 buf.append(key); 1201 keyList.add(buf.toString()); 1202 } 1203 } 1204 } 1205 1206 1211 static class CloneVisitor extends NodeVisitor 1212 { 1213 1214 private Stack copyStack; 1215 1216 1217 private Node result; 1218 1219 1222 public CloneVisitor() 1223 { 1224 copyStack = new Stack (); 1225 } 1226 1227 1233 public void visitAfterChildren(Node node, ConfigurationKey key) 1234 { 1235 copyStack.pop(); 1236 if (copyStack.isEmpty()) 1237 { 1238 result = node; 1239 } 1240 } 1241 1242 1248 public void visitBeforeChildren(Node node, ConfigurationKey key) 1249 { 1250 Node copy = (Node) node.clone(); 1251 copy.removeChildren(); 1252 1253 if (!copyStack.isEmpty()) 1254 { 1255 ((Node) copyStack.peek()).addChild(copy); 1256 } 1257 1258 copyStack.push(copy); 1259 } 1260 1261 1267 public Node getClone() 1268 { 1269 return result; 1270 } 1271 } 1272 1273 1288 protected abstract static class BuilderVisitor extends NodeVisitor 1289 { 1290 1293 public void visitBeforeChildren(Node node, ConfigurationKey key) 1294 { 1295 Iterator children = node.getChildren().iterator(); 1296 Node sibling1 = null; 1297 Node nd = null; 1298 1299 while (children.hasNext()) 1300 { 1301 do 1303 { 1304 sibling1 = nd; 1305 nd = (Node) children.next(); 1306 } while (nd.getReference() != null && children.hasNext()); 1307 1308 if (nd.getReference() == null) 1309 { 1310 List newNodes = new LinkedList (); 1312 newNodes.add(nd); 1313 while (children.hasNext()) 1314 { 1315 nd = (Node) children.next(); 1316 if (nd.getReference() == null) 1317 { 1318 newNodes.add(nd); 1319 } 1320 else 1321 { 1322 break; 1323 } 1324 } 1325 1326 Node sibling2 = (nd.getReference() == null) ? null : nd; 1328 for (Iterator it = newNodes.iterator(); it.hasNext();) 1329 { 1330 Node insertNode = (Node) it.next(); 1331 if (insertNode.getReference() == null) 1332 { 1333 Object ref = insert(insertNode, node, sibling1, sibling2); 1334 if (ref != null) 1335 { 1336 insertNode.setReference(ref); 1337 } 1338 } 1339 } 1340 } 1341 } 1342 } 1343 1344 1365 protected abstract Object insert(Node newNode, Node parent, Node sibling1, Node sibling2); 1366 } 1367} | Popular Tags |