1 18 19 package org.apache.jorphan.collections; 20 21 import java.io.IOException ; 22 import java.io.ObjectInputStream ; 23 import java.io.ObjectOutputStream ; 24 import java.io.Serializable ; 25 import java.util.Arrays ; 26 import java.util.Collection ; 27 import java.util.HashMap ; 28 import java.util.Iterator ; 29 import java.util.Map ; 30 import java.util.Set ; 31 32 import junit.framework.TestCase; 33 34 import org.apache.jorphan.logging.LoggingManager; 35 import org.apache.log.Logger; 36 37 57 public class HashTree implements Serializable , Map 58 { 59 66 69 public HashTree() 70 { 71 data = new HashMap (); 72 } 73 74 78 public HashTree(Object key) 79 { 80 data = new HashMap (); 81 data.put(key, new HashTree()); 82 } 83 84 91 public void putAll(Map map) 92 { 93 if (map instanceof HashTree) 94 { 95 this.add((HashTree) map); 96 } 97 else 98 { 99 throw new UnsupportedOperationException ( 100 "can only putAll other HashTree objects"); 101 } 102 } 103 104 108 public Set entrySet() 109 { 110 return data.entrySet(); 111 } 112 113 121 public boolean containsValue(Object value) 122 { 123 return data.containsValue(value); 124 } 125 126 132 public Object put(Object key, Object value) 133 { 134 Object previous = data.get(key); 135 add(key, value); 136 return previous; 137 } 138 139 143 public void clear() 144 { 145 data.clear(); 146 } 147 148 152 public Collection values() 153 { 154 return data.values(); 155 } 156 157 165 public void add(Object key, HashTree subTree) 166 { 167 add(key); 168 getTree(key).add(subTree); 169 } 170 171 176 public void add(HashTree newTree) 177 { 178 Iterator iter = newTree.list().iterator(); 179 while (iter.hasNext()) 180 { 181 Object item = iter.next(); 182 add(item); 183 getTree(item).add(newTree.getTree(item)); 184 } 185 } 186 187 193 public HashTree(Collection keys) 194 { 195 data = new HashMap (); 196 Iterator it = keys.iterator(); 197 while (it.hasNext()) 198 { 199 data.put(it.next(), new HashTree()); 200 } 201 } 202 203 207 public HashTree(Object [] keys) 208 { 209 data = new HashMap (); 210 for (int x = 0; x < keys.length; x++) 211 { 212 data.put(keys[x], new HashTree()); 213 } 214 } 215 216 224 public boolean containsKey(Object o) 225 { 226 return data.containsKey(o); 227 } 228 229 233 public boolean isEmpty() 234 { 235 return data.isEmpty(); 236 } 237 238 246 public void set(Object key, Object value) 247 { 248 data.put(key, createNewTree(value)); 249 } 250 251 258 public void set(Object key, HashTree t) 259 { 260 data.put(key, t); 261 } 262 263 272 public void set(Object key, Object [] values) 273 { 274 data.put(key, createNewTree(Arrays.asList(values))); 275 } 276 277 287 public void set(Object key, Collection values) 288 { 289 data.put(key, createNewTree(values)); 290 } 291 292 304 public void set(Object [] treePath, Object [] values) 305 { 306 if (treePath != null && values != null) 307 { 308 set(Arrays.asList(treePath), Arrays.asList(values)); 309 } 310 } 311 312 325 public void set(Object [] treePath, Collection values) 326 { 327 if (treePath != null) 328 { 329 set(Arrays.asList(treePath), values); 330 } 331 } 332 333 345 public void set(Collection treePath, Object [] values) 346 { 347 HashTree tree = addTreePath(treePath); 348 tree.set(Arrays.asList(values)); 349 } 350 351 357 public void set(Collection values) 358 { 359 clear(); 360 this.add(values); 361 } 362 363 376 public void set(Collection treePath, Collection values) 377 { 378 HashTree tree = addTreePath(treePath); 379 tree.set(values); 380 } 381 382 387 public HashTree add(Object key) 388 { 389 if (!data.containsKey(key)) 390 { 391 HashTree newTree = createNewTree(); 392 data.put(key, newTree); 393 return newTree; 394 } 395 else 396 { 397 return getTree(key); 398 } 399 } 400 401 406 public void add(Object [] keys) 407 { 408 for (int x = 0; x < keys.length; x++) 409 { 410 add(keys[x]); 411 } 412 } 413 414 419 public void add(Collection keys) 420 { 421 Iterator it = keys.iterator(); 422 while (it.hasNext()) 423 { 424 add(it.next()); 425 } 426 } 427 428 435 public HashTree add(Object key, Object value) 436 { 437 add(key); 438 return getTree(key).add(value); 439 } 440 441 449 public void add(Object key, Object [] values) 450 { 451 add(key); 452 getTree(key).add(values); 453 } 454 455 463 public void add(Object key, Collection values) 464 { 465 add(key); 466 getTree(key).add(values); 467 } 468 469 479 public void add(Object [] treePath, Object [] values) 480 { 481 if (treePath != null) 482 { 483 add(Arrays.asList(treePath), Arrays.asList(values)); 484 } 485 } 486 487 498 public void add(Object [] treePath, Collection values) 499 { 500 if (treePath != null) 501 { 502 add(Arrays.asList(treePath), values); 503 } 504 } 505 506 public HashTree add(Object [] treePath,Object value) 507 { 508 return add(Arrays.asList(treePath),value); 509 } 510 511 521 public void add(Collection treePath, Object [] values) 522 { 523 HashTree tree = addTreePath(treePath); 524 tree.add(Arrays.asList(values)); 525 } 526 527 537 public HashTree add(Collection treePath, Object value) 538 { 539 HashTree tree = addTreePath(treePath); 540 return tree.add(value); 541 } 542 543 554 public void add(Collection treePath, Collection values) 555 { 556 HashTree tree = addTreePath(treePath); 557 tree.add(values); 558 } 559 560 protected HashTree addTreePath(Collection treePath) 561 { 562 HashTree tree = this; 563 Iterator iter = treePath.iterator(); 564 while (iter.hasNext()) 565 { 566 Object temp = iter.next(); 567 tree.add(temp); 568 tree = tree.getTree(temp); 569 } 570 return tree; 571 } 572 573 577 public HashTree getTree(Object key) 578 { 579 return (HashTree) data.get(key); 580 } 581 582 588 public Object get(Object key) 589 { 590 return getTree(key); 591 } 592 593 600 public HashTree getTree(Object [] treePath) 601 { 602 if (treePath != null) 603 { 604 return getTree(Arrays.asList(treePath)); 605 } 606 else 607 { 608 return this; 609 } 610 } 611 612 617 public Object clone() 618 { 619 HashTree newTree = new HashTree(); 620 cloneTree(newTree); 621 return newTree; 622 } 623 624 protected void cloneTree(HashTree newTree) 625 { 626 Iterator iter = list().iterator(); 627 while (iter.hasNext()) 628 { 629 Object key = iter.next(); 630 newTree.set(key, (HashTree) getTree(key).clone()); 631 } 632 } 633 634 644 protected HashTree createNewTree() 645 { 646 return new HashTree(); 647 } 648 649 659 protected HashTree createNewTree(Object key) 660 { 661 return new HashTree(key); 662 } 663 664 674 protected HashTree createNewTree(Collection values) 675 { 676 return new HashTree(values); 677 } 678 679 686 public HashTree getTree(Collection treePath) 687 { 688 return getTreePath(treePath); 689 } 690 691 698 public Collection list() 699 { 700 return data.keySet(); 701 } 702 703 712 public Collection list(Object key) 713 { 714 HashTree temp = (HashTree) data.get(key); 715 if (temp != null) 716 { 717 return temp.list(); 718 } 719 else 720 { 721 return null; 722 } 723 } 724 725 729 public Object remove(Object key) 730 { 731 return data.remove(key); 732 } 733 734 735 745 public Collection list(Object [] treePath) 746 { 747 if (treePath != null) 748 { 749 return list(Arrays.asList(treePath)); 750 } 751 else 752 { 753 return list(); 754 } 755 } 756 757 767 public Collection list(Collection treePath) 768 { 769 return getTreePath(treePath).list(); 770 } 771 772 776 public void replace(Object currentKey, Object newKey) 777 { 778 HashTree tree = getTree(currentKey); 779 data.remove(currentKey); 780 data.put(newKey, tree); 781 } 782 783 790 public Object [] getArray() 791 { 792 return data.keySet().toArray(); 793 } 794 795 805 public Object [] getArray(Object key) 806 { 807 return getTree(key).getArray(); 808 } 809 810 820 public Object [] getArray(Object [] treePath) 821 { 822 if (treePath != null) 823 { 824 return getArray(Arrays.asList(treePath)); 825 } 826 else 827 { 828 return getArray(); 829 } 830 } 831 832 843 public Object [] getArray(Collection treePath) 844 { 845 HashTree tree = getTreePath(treePath); 846 return tree.getArray(); 847 } 848 849 protected HashTree getTreePath(Collection treePath) 850 { 851 HashTree tree = this; 852 Iterator iter = treePath.iterator(); 853 while (iter.hasNext()) 854 { 855 Object temp = iter.next(); 856 tree = tree.getTree(temp); 857 } 858 return tree; 859 } 860 861 865 public int hashCode() 866 { 867 return data.hashCode() * 7; 868 } 869 870 878 public boolean equals(Object o) 879 { 880 if (!(o instanceof HashTree)) return false; 881 HashTree oo = (HashTree) o; 882 if (oo.size() != this.size()) return false; 883 return data.equals(oo.data); 884 885 } 918 919 923 public Set keySet() 924 { 925 return data.keySet(); 926 } 927 928 936 public HashTree search(Object key) 937 { 938 HashTree result = getTree(key); 939 if(result != null) 940 { 941 return result; 942 } 943 TreeSearcher searcher = new TreeSearcher(key); 944 try 945 { 946 traverse(searcher); 947 } 948 catch(Exception e){ 949 } 951 return searcher.getResult(); 952 } 953 956 void readObject(ObjectInputStream ois) 957 throws ClassNotFoundException , IOException 958 { 959 ois.defaultReadObject(); 960 } 961 962 void writeObject(ObjectOutputStream oos) throws IOException 963 { 964 oos.defaultWriteObject(); 965 } 966 967 971 public int size() 972 { 973 return data.size(); 974 } 975 976 983 public void traverse(HashTreeTraverser visitor) 984 { 985 Iterator iter = list().iterator(); 986 while (iter.hasNext()) 987 { 988 Object item = iter.next(); 989 visitor.addNode(item, getTree(item)); 990 getTree(item).traverseInto(visitor); 991 } 992 } 993 994 998 private void traverseInto(HashTreeTraverser visitor) 999 { 1000 1001 if (list().size() == 0) 1002 { 1003 visitor.processPath(); 1004 } 1005 else 1006 { 1007 Iterator iter = list().iterator(); 1008 while (iter.hasNext()) 1009 { 1010 Object item = iter.next(); 1011 visitor.addNode(item, getTree(item)); 1012 getTree(item).traverseInto(visitor); 1013 } 1014 } 1015 visitor.subtractNode(); 1016 } 1017 1018 public String toString() 1019 { 1020 ConvertToString converter = new ConvertToString(); 1021 traverse(converter); 1022 return converter.toString(); 1023 } 1024 1025 protected Map data; 1026 1027 private class TreeSearcher implements HashTreeTraverser 1028 { 1029 Object target; 1030 HashTree result; 1031 1032 public TreeSearcher(Object t) 1033 { 1034 target = t; 1035 } 1036 1037 public HashTree getResult() 1038 { 1039 return result; 1040 } 1041 1044 public void addNode(Object node, HashTree subTree) { 1045 result = subTree.getTree(target); 1046 if(result != null) 1047 { 1048 throw new RuntimeException ("found"); } 1050 } 1051 1054 public void processPath() { 1055 1057 } 1058 1061 public void subtractNode() { 1062 1064 } 1065} 1066 1067 private class ConvertToString implements HashTreeTraverser 1068 { 1069 StringBuffer string = new StringBuffer (getClass().getName() + "{"); 1070 StringBuffer spaces = new StringBuffer (); 1071 int depth = 0; 1072 public void addNode(Object key, HashTree subTree) 1073 { 1074 depth++; 1075 string.append("\n" + getSpaces() + key + " {"); 1076 } 1077 1078 public void subtractNode() 1079 { 1080 string.append("\n" + getSpaces() + "}"); 1081 depth--; 1082 } 1083 1084 public void processPath() 1085 { 1086 } 1087 1088 public String toString() 1089 { 1090 string.append("\n}"); 1091 return string.toString(); 1092 } 1093 1094 private String getSpaces() 1095 { 1096 if (spaces.length() < depth * 2) 1097 { 1098 while (spaces.length() < depth * 2) 1099 { 1100 spaces.append(" "); 1101 } 1102 } 1103 else if (spaces.length() > depth * 2) 1104 { 1105 spaces.setLength(depth * 2); 1106 } 1107 return spaces.toString(); 1108 } 1109 } 1110 1111 public static class Test extends TestCase 1112 { 1113 public Test(String name) 1114 { 1115 super(name); 1116 } 1117 1118 public void testAdd1() throws Exception 1119 { 1120 Logger log = 1121 LoggingManager.getLoggerForClass(); 1122 Collection treePath = 1123 Arrays.asList(new String [] { "1", "2", "3", "4" }); 1124 HashTree tree = new HashTree(); 1125 log.debug("treePath = " + treePath); 1126 tree.add(treePath, "value"); 1127 log.debug("Now treePath = " + treePath); 1128 log.debug(tree.toString()); 1129 assertEquals(1, tree.list(treePath).size()); 1130 assertEquals("value", tree.getArray(treePath)[0]); 1131 } 1132 1133 public void testEqualsAndHashCode() throws Exception 1134 { 1135 HashTree tree1 = new HashTree("abcd"); 1136 HashTree tree2 = new HashTree("abcd"); 1137 HashTree tree3 = new HashTree("abcde"); 1138 HashTree tree4 = new HashTree("abcde"); 1139 1140 assertTrue(tree1.equals(tree1)); 1141 assertTrue(tree1.equals(tree2)); 1142 assertTrue(tree2.equals(tree1)); 1143 assertTrue(tree2.equals(tree2)); 1144 assertTrue(tree1.hashCode()==tree2.hashCode()); 1145 1146 assertTrue(tree3.equals(tree3)); 1147 assertTrue(tree3.equals(tree4)); 1148 assertTrue(tree4.equals(tree3)); 1149 assertTrue(tree4.equals(tree4)); 1150 assertTrue(tree3.hashCode()==tree4.hashCode()); 1151 1152 assertNotSame(tree1,tree2); 1153 assertNotSame(tree1,tree3); 1154 assertNotSame(tree1,tree4); 1155 assertNotSame(tree2,tree3); 1156 assertNotSame(tree2,tree4); 1157 1158 assertFalse(tree1.equals(tree3)); 1159 assertFalse(tree1.equals(tree4)); 1160 assertFalse(tree2.equals(tree3)); 1161 assertFalse(tree2.equals(tree4)); 1162 1163 assertNotNull(tree1); 1164 assertNotNull(tree1); 1165 assertNotNull(tree2); 1166 assertNotNull(tree2); 1167 1168 tree1.add("abcd",tree3); 1169 assertFalse(tree1.equals(tree2)); 1170 assertFalse(tree2.equals(tree1)); if (tree1.hashCode()==tree2.hashCode()) 1172 { 1173 System.out.println("WARN: unequal HashTrees should not have equal hashCodes"); 1175 } 1176 tree2.add("abcd",tree4); 1177 assertTrue(tree1.equals(tree2)); 1178 assertTrue(tree2.equals(tree1)); 1179 assertTrue(tree1.hashCode()==tree2.hashCode()); 1180 } 1181 } 1182} 1183 | Popular Tags |