1 package net.myvietnam.mvncore.configuration; 2 3 56 57 import java.io.Serializable ; 58 import java.util.ArrayList ; 59 import java.util.Collection ; 60 import java.util.HashSet ; 61 import java.util.Iterator ; 62 import java.util.LinkedList ; 63 import java.util.List ; 64 import java.util.Map ; 65 import java.util.Set ; 66 import java.util.Stack ; 67 68 import org.apache.commons.collections.SequencedHashMap; 69 import org.apache.commons.lang.StringUtils; 70 71 132 public class HierarchicalConfiguration extends AbstractConfiguration 133 { 134 135 private static final String NEW_KEY = "newKey"; 136 137 138 private Node root = new Node(); 139 140 143 public HierarchicalConfiguration() 144 { 145 super(); 146 } 147 148 153 public HierarchicalConfiguration(Configuration defaults) 154 { 155 super(defaults); 156 } 157 158 162 public Node getRoot() 163 { 164 return root; 165 } 166 167 171 public void setRoot(Node node) 172 { 173 if (node == null) 174 { 175 throw new IllegalArgumentException ("Root node must not be null!"); 176 } 177 root = node; 178 } 179 180 186 protected Object getPropertyDirect(String key) 187 { 188 List nodes = fetchNodeList(key); 189 190 if (nodes.size() == 0) 191 { 192 return null; 193 } 194 else 195 { 196 Container cont = new Container(); 197 for (Iterator it = nodes.iterator(); it.hasNext();) 198 { 199 Node nd = (Node) it.next(); 200 if (nd.getValue() != null) 201 { 202 cont.add(nd.getValue()); 203 } 204 } 205 206 if (cont.size() < 1) 207 { 208 return null; 209 } 210 else 211 { 212 return (cont.size() == 1) ? cont.get(0) : cont; 213 } 214 } 215 } 216 217 279 protected void addPropertyDirect(String key, Object obj) 280 { 281 ConfigurationKey.KeyIterator it = new ConfigurationKey(key).iterator(); 282 Node parent = fetchAddNode(it, getRoot()); 283 284 Node child = new Node(it.currentKey(true)); 285 child.setValue(obj); 286 parent.addChild(child); 287 } 288 289 301 public void addNodes(String key, Collection nodes) 302 { 303 if (nodes == null || nodes.isEmpty()) 304 { 305 return; 306 } 307 308 Node parent; 309 if (StringUtils.isEmpty(key)) 310 { 311 parent = getRoot(); 312 } 313 else 314 { 315 ConfigurationKey.KeyIterator kit = 316 new ConfigurationKey(key).iterator(); 317 parent = fetchAddNode(kit, getRoot()); 318 319 ConfigurationKey keyNew = 322 new ConfigurationKey(kit.currentKey(true)); 323 keyNew.append(NEW_KEY); 324 parent = fetchAddNode(keyNew.iterator(), parent); 325 } 326 327 for (Iterator it = nodes.iterator(); it.hasNext();) 328 { 329 parent.addChild((Node) it.next()); 330 } 331 } 332 333 338 public boolean isEmpty() 339 { 340 return !nodeDefined(getRoot()); 341 } 342 343 352 public boolean containsKey(String key) 353 { 354 return getPropertyDirect(key) != null; 355 } 356 357 361 public void clearProperty(String key) 362 { 363 List nodes = fetchNodeList(key); 364 365 for (Iterator it = nodes.iterator(); it.hasNext();) 366 { 367 removeNode((Node) it.next()); 368 } 369 } 370 371 377 public Iterator getKeys() 378 { 379 DefinedKeysVisitor visitor = new DefinedKeysVisitor(); 380 getRoot().visit(visitor, new ConfigurationKey()); 381 return visitor.getKeyList().iterator(); 382 } 383 384 392 public Configuration subset(String prefix) 393 { 394 Collection nodes = fetchNodeList(prefix); 395 if (nodes.isEmpty()) 396 { 397 return null; 398 } 399 400 HierarchicalConfiguration result = new HierarchicalConfiguration(); 401 CloneVisitor visitor = new CloneVisitor(); 402 403 for (Iterator it = nodes.iterator(); it.hasNext();) 404 { 405 Node nd = (Node) it.next(); 406 nd.visit(visitor, null); 407 408 Container children = visitor.getClone().getChildren(); 409 if (children.size() > 0) 410 { 411 for (int i = 0; i < children.size(); i++) 412 { 413 result.getRoot().addChild((Node) children.get(i)); 414 } 415 } 416 else 417 { 418 result.getRoot().addChild(visitor.getClone()); 421 } 422 } 423 424 return (result.isEmpty()) ? null : result; 425 } 426 427 435 public int getMaxIndex(String key) 436 { 437 return fetchNodeList(key).size() - 1; 438 } 439 440 446 protected List fetchNodeList(String key) 447 { 448 List nodes = new LinkedList (); 449 findPropertyNodes( 450 new ConfigurationKey(key).iterator(), 451 getRoot(), 452 nodes); 453 return nodes; 454 } 455 456 464 protected void findPropertyNodes( 465 ConfigurationKey.KeyIterator keyPart, 466 Node node, 467 Collection data) 468 { 469 if (!keyPart.hasNext()) 470 { 471 data.add(node); 472 } 473 474 else 475 { 476 String key = keyPart.nextKey(true); 477 Container children = node.getChildren(key); 478 if (keyPart.hasIndex()) 479 { 480 if (keyPart.getIndex() < children.size() 481 && keyPart.getIndex() >= 0) 482 { 483 findPropertyNodes( 484 (ConfigurationKey.KeyIterator) keyPart.clone(), 485 (Node) children.get(keyPart.getIndex()), 486 data); 487 } 488 } 489 490 else 491 { 492 for (Iterator it = children.iterator(); it.hasNext();) 493 { 494 findPropertyNodes( 495 (ConfigurationKey.KeyIterator) keyPart.clone(), 496 (Node) it.next(), 497 data); 498 } 499 } 500 } 501 } 502 503 508 protected boolean nodeDefined(Node node) 509 { 510 DefinedVisitor visitor = new DefinedVisitor(); 511 node.visit(visitor, null); 512 return visitor.isDefined(); 513 } 514 515 521 protected void removeNode(Node node) 522 { 523 Node parent = node.getParent(); 524 if (parent != null) 525 { 526 parent.remove(node); 527 if (!nodeDefined(parent)) 528 { 529 removeNode(parent); 530 } 531 } 532 } 533 534 543 protected Node fetchAddNode( 544 ConfigurationKey.KeyIterator keyIt, 545 Node startNode) 546 { 547 if (!keyIt.hasNext()) 548 { 549 throw new IllegalArgumentException ("Key must be defined!"); 550 } 551 552 return createAddPath(keyIt, findLastPathNode(keyIt, startNode)); 553 } 554 555 563 protected Node findLastPathNode( 564 ConfigurationKey.KeyIterator keyIt, 565 Node node) 566 { 567 String keyPart = keyIt.nextKey(true); 568 569 if (keyIt.hasNext()) 570 { 571 Container c = node.getChildren(keyPart); 572 int idx = (keyIt.hasIndex()) ? keyIt.getIndex() : c.size() - 1; 573 if (idx < 0 || idx >= c.size()) 574 { 575 return node; 576 } 577 else 578 { 579 return findLastPathNode(keyIt, (Node) c.get(idx)); 580 } 581 } 582 583 else 584 { 585 return node; 586 } 587 } 588 589 597 protected Node createAddPath(ConfigurationKey.KeyIterator keyIt, Node root) 598 { 599 if (keyIt.hasNext()) 600 { 601 Node child = new Node(keyIt.currentKey(true)); 602 root.addChild(child); 603 keyIt.next(); 604 return createAddPath(keyIt, child); 605 } 606 else 607 { 608 return root; 609 } 610 } 611 612 618 private static void addContainer(Container cont, Collection items) 619 { 620 for (Iterator it = items.iterator(); it.hasNext();) 621 { 622 cont.add(it.next()); 623 } 624 } 625 626 632 public static class Node implements Serializable , Cloneable 633 { 634 635 private Node parent; 636 637 638 private String name; 639 640 641 private Object value; 642 643 644 private Map children; 645 646 649 public Node() 650 { 651 this(null); 652 } 653 654 658 public Node(String name) 659 { 660 setName(name); 661 } 662 663 667 public String getName() 668 { 669 return name; 670 } 671 672 676 public Object getValue() 677 { 678 return value; 679 } 680 681 685 public Node getParent() 686 { 687 return parent; 688 } 689 690 694 public void setName(String string) 695 { 696 name = string; 697 } 698 699 703 public void setValue(Object object) 704 { 705 value = object; 706 } 707 708 712 public void setParent(Node node) 713 { 714 parent = node; 715 } 716 717 722 public void addChild(Node child) 723 { 724 if (children == null) 725 { 726 children = new SequencedHashMap(); 727 } 728 729 List c = (List ) children.get(child.getName()); 730 if (c == null) 731 { 732 c = new ArrayList (); 733 children.put(child.getName(), c); 734 } 735 736 c.add(child); 737 child.setParent(this); 738 } 739 740 745 public Container getChildren() 746 { 747 Container result = new Container(); 748 749 if (children != null) 750 { 751 for (Iterator it = children.values().iterator(); it.hasNext();) 752 { 753 addContainer(result, (Collection ) it.next()); 754 } 755 } 756 757 return result; 758 } 759 760 766 public Container getChildren(String name) 767 { 768 if (name == null || children == null) 769 { 770 return getChildren(); 771 } 772 773 Container cont = new Container(); 774 List c = (List ) children.get(name); 775 if (c != null) 776 { 777 addContainer(cont, c); 778 } 779 780 return cont; 781 } 782 783 788 public boolean remove(Node child) 789 { 790 if (children == null) 791 { 792 return false; 793 } 794 795 List c = (List ) children.get(child.getName()); 796 if (c == null) 797 { 798 return false; 799 } 800 801 else 802 { 803 if (c.remove(child)) 804 { 805 if (c.isEmpty()) 806 { 807 children.remove(child.getName()); 808 } 809 return true; 810 } 811 else 812 { 813 return false; 814 } 815 } 816 } 817 818 823 public boolean remove(String name) 824 { 825 if (children == null) 826 { 827 return false; 828 } 829 830 return children.remove(name) != null; 831 } 832 833 836 public void removeChildren() 837 { 838 children = null; 839 } 840 841 851 public void visit(NodeVisitor visitor, ConfigurationKey key) 852 { 853 int length = 0; 854 if (key != null) 855 { 856 length = key.length(); 857 if (getName() != null) 858 { 859 key.append(getName()); 860 } 861 } 862 863 visitor.visitBeforeChildren(this, key); 864 865 if (children != null) 866 { 867 for (Iterator it = children.values().iterator(); 868 it.hasNext() && !visitor.terminate(); 869 ) 870 { 871 Collection col = (Collection ) it.next(); 872 for (Iterator it2 = col.iterator(); 873 it2.hasNext() && !visitor.terminate(); 874 ) 875 { 876 ((Node) it2.next()).visit(visitor, key); 877 } 878 } 879 } 880 881 if (key != null) 882 { 883 key.setLength(length); 884 } 885 visitor.visitAfterChildren(this, key); 886 } 887 888 893 protected Object clone() 894 { 895 try 896 { 897 return super.clone(); 898 } 899 catch (CloneNotSupportedException cex) 900 { 901 return null; } 903 } 904 } 905 906 918 public static class NodeVisitor 919 { 920 926 public void visitBeforeChildren(Node node, ConfigurationKey key) 927 { 928 } 929 930 937 public void visitAfterChildren(Node node, ConfigurationKey key) 938 { 939 } 940 941 949 public boolean terminate() 950 { 951 return false; 952 } 953 } 954 955 962 static class DefinedVisitor extends NodeVisitor 963 { 964 965 private boolean defined; 966 967 972 public boolean terminate() 973 { 974 return isDefined(); 975 } 976 977 982 public void visitBeforeChildren(Node node, ConfigurationKey key) 983 { 984 defined = node.getValue() != null; 985 } 986 987 991 public boolean isDefined() 992 { 993 return defined; 994 } 995 } 996 997 1003 static class DefinedKeysVisitor extends NodeVisitor 1004 { 1005 1006 private Set keyList; 1007 1008 1011 public DefinedKeysVisitor() 1012 { 1013 keyList = new HashSet (); 1014 } 1015 1016 1020 public Set getKeyList() 1021 { 1022 return keyList; 1023 } 1024 1025 1031 public void visitBeforeChildren(Node node, ConfigurationKey key) 1032 { 1033 if (node.getValue() != null && key != null) 1034 { 1035 keyList.add(key.toString()); 1036 } 1037 } 1038 } 1039 1040 1046 static class CloneVisitor extends NodeVisitor 1047 { 1048 1049 private Stack copyStack; 1050 1051 1052 private Node result; 1053 1054 1057 public CloneVisitor() 1058 { 1059 copyStack = new Stack (); 1060 } 1061 1062 1067 public void visitAfterChildren(Node node, ConfigurationKey key) 1068 { 1069 copyStack.pop(); 1070 if (copyStack.isEmpty()) 1071 { 1072 result = node; 1073 } 1074 } 1075 1076 1081 public void visitBeforeChildren(Node node, ConfigurationKey key) 1082 { 1083 Node copy = (Node) node.clone(); 1084 copy.removeChildren(); 1085 1086 if (!copyStack.isEmpty()) 1087 { 1088 ((Node) copyStack.peek()).addChild(copy); 1089 } 1090 1091 copyStack.push(copy); 1092 } 1093 1094 1099 public Node getClone() 1100 { 1101 return result; 1102 } 1103 } 1104} 1105 | Popular Tags |