1 7 8 package javax.swing.tree; 9 11 import java.io.*; 12 import java.util.*; 13 14 15 70 public class DefaultMutableTreeNode extends Object implements Cloneable , 71 MutableTreeNode , Serializable 72 { 73 74 78 static public final Enumeration<TreeNode > EMPTY_ENUMERATION 79 = new Enumeration<TreeNode >() { 80 public boolean hasMoreElements() { return false; } 81 public TreeNode nextElement() { 82 throw new NoSuchElementException("No more elements"); 83 } 84 }; 85 86 87 protected MutableTreeNode parent; 88 89 90 protected Vector children; 91 92 93 transient protected Object userObject; 94 95 96 protected boolean allowsChildren; 97 98 99 103 public DefaultMutableTreeNode() { 104 this(null); 105 } 106 107 114 public DefaultMutableTreeNode(Object userObject) { 115 this(userObject, true); 116 } 117 118 128 public DefaultMutableTreeNode(Object userObject, boolean allowsChildren) { 129 super(); 130 parent = null; 131 this.allowsChildren = allowsChildren; 132 this.userObject = userObject; 133 } 134 135 136 140 159 public void insert(MutableTreeNode newChild, int childIndex) { 160 if (!allowsChildren) { 161 throw new IllegalStateException ("node does not allow children"); 162 } else if (newChild == null) { 163 throw new IllegalArgumentException ("new child is null"); 164 } else if (isNodeAncestor(newChild)) { 165 throw new IllegalArgumentException ("new child is an ancestor"); 166 } 167 168 MutableTreeNode oldParent = (MutableTreeNode )newChild.getParent(); 169 170 if (oldParent != null) { 171 oldParent.remove(newChild); 172 } 173 newChild.setParent(this); 174 if (children == null) { 175 children = new Vector(); 176 } 177 children.insertElementAt(newChild, childIndex); 178 } 179 180 190 public void remove(int childIndex) { 191 MutableTreeNode child = (MutableTreeNode )getChildAt(childIndex); 192 children.removeElementAt(childIndex); 193 child.setParent(null); 194 } 195 196 205 public void setParent(MutableTreeNode newParent) { 206 parent = newParent; 207 } 208 209 214 public TreeNode getParent() { 215 return parent; 216 } 217 218 226 public TreeNode getChildAt(int index) { 227 if (children == null) { 228 throw new ArrayIndexOutOfBoundsException ("node has no children"); 229 } 230 return (TreeNode )children.elementAt(index); 231 } 232 233 238 public int getChildCount() { 239 if (children == null) { 240 return 0; 241 } else { 242 return children.size(); 243 } 244 } 245 246 259 public int getIndex(TreeNode aChild) { 260 if (aChild == null) { 261 throw new IllegalArgumentException ("argument is null"); 262 } 263 264 if (!isNodeChild(aChild)) { 265 return -1; 266 } 267 return children.indexOf(aChild); } 269 270 277 public Enumeration children() { 278 if (children == null) { 279 return EMPTY_ENUMERATION; 280 } else { 281 return children.elements(); 282 } 283 } 284 285 294 public void setAllowsChildren(boolean allows) { 295 if (allows != allowsChildren) { 296 allowsChildren = allows; 297 if (!allowsChildren) { 298 removeAllChildren(); 299 } 300 } 301 } 302 303 308 public boolean getAllowsChildren() { 309 return allowsChildren; 310 } 311 312 320 public void setUserObject(Object userObject) { 321 this.userObject = userObject; 322 } 323 324 331 public Object getUserObject() { 332 return userObject; 333 } 334 335 336 340 345 public void removeFromParent() { 346 MutableTreeNode parent = (MutableTreeNode )getParent(); 347 if (parent != null) { 348 parent.remove(this); 349 } 350 } 351 352 360 public void remove(MutableTreeNode aChild) { 361 if (aChild == null) { 362 throw new IllegalArgumentException ("argument is null"); 363 } 364 365 if (!isNodeChild(aChild)) { 366 throw new IllegalArgumentException ("argument is not a child"); 367 } 368 remove(getIndex(aChild)); } 370 371 375 public void removeAllChildren() { 376 for (int i = getChildCount()-1; i >= 0; i--) { 377 remove(i); 378 } 379 } 380 381 392 public void add(MutableTreeNode newChild) { 393 if(newChild != null && newChild.getParent() == this) 394 insert(newChild, getChildCount() - 1); 395 else 396 insert(newChild, getChildCount()); 397 } 398 399 400 401 405 418 public boolean isNodeAncestor(TreeNode anotherNode) { 419 if (anotherNode == null) { 420 return false; 421 } 422 423 TreeNode ancestor = this; 424 425 do { 426 if (ancestor == anotherNode) { 427 return true; 428 } 429 } while((ancestor = ancestor.getParent()) != null); 430 431 return false; 432 } 433 434 447 public boolean isNodeDescendant(DefaultMutableTreeNode anotherNode) { 448 if (anotherNode == null) 449 return false; 450 451 return anotherNode.isNodeAncestor(this); 452 } 453 454 466 public TreeNode getSharedAncestor(DefaultMutableTreeNode aNode) { 467 if (aNode == this) { 468 return this; 469 } else if (aNode == null) { 470 return null; 471 } 472 473 int level1, level2, diff; 474 TreeNode node1, node2; 475 476 level1 = getLevel(); 477 level2 = aNode.getLevel(); 478 479 if (level2 > level1) { 480 diff = level2 - level1; 481 node1 = aNode; 482 node2 = this; 483 } else { 484 diff = level1 - level2; 485 node1 = this; 486 node2 = aNode; 487 } 488 489 while (diff > 0) { 491 node1 = node1.getParent(); 492 diff--; 493 } 494 495 500 do { 501 if (node1 == node2) { 502 return node1; 503 } 504 node1 = node1.getParent(); 505 node2 = node2.getParent(); 506 } while (node1 != null); 509 if (node1 != null || node2 != null) { 510 throw new Error ("nodes should be null"); 511 } 512 513 return null; 514 } 515 516 517 526 public boolean isNodeRelated(DefaultMutableTreeNode aNode) { 527 return (aNode != null) && (getRoot() == aNode.getRoot()); 528 } 529 530 531 541 public int getDepth() { 542 Object last = null; 543 Enumeration enum_ = breadthFirstEnumeration(); 544 545 while (enum_.hasMoreElements()) { 546 last = enum_.nextElement(); 547 } 548 549 if (last == null) { 550 throw new Error ("nodes should be null"); 551 } 552 553 return ((DefaultMutableTreeNode )last).getLevel() - getLevel(); 554 } 555 556 557 558 565 public int getLevel() { 566 TreeNode ancestor; 567 int levels = 0; 568 569 ancestor = this; 570 while((ancestor = ancestor.getParent()) != null){ 571 levels++; 572 } 573 574 return levels; 575 } 576 577 578 586 public TreeNode [] getPath() { 587 return getPathToRoot(this, 0); 588 } 589 590 602 protected TreeNode [] getPathToRoot(TreeNode aNode, int depth) { 603 TreeNode [] retNodes; 604 605 607 if(aNode == null) { 608 if(depth == 0) 609 return null; 610 else 611 retNodes = new TreeNode [depth]; 612 } 613 else { 614 depth++; 615 retNodes = getPathToRoot(aNode.getParent(), depth); 616 retNodes[retNodes.length - depth] = aNode; 617 } 618 return retNodes; 619 } 620 621 626 public Object [] getUserObjectPath() { 627 TreeNode [] realPath = getPath(); 628 Object [] retPath = new Object [realPath.length]; 629 630 for(int counter = 0; counter < realPath.length; counter++) 631 retPath[counter] = ((DefaultMutableTreeNode )realPath[counter]) 632 .getUserObject(); 633 return retPath; 634 } 635 636 643 public TreeNode getRoot() { 644 TreeNode ancestor = this; 645 TreeNode previous; 646 647 do { 648 previous = ancestor; 649 ancestor = ancestor.getParent(); 650 } while (ancestor != null); 651 652 return previous; 653 } 654 655 656 663 public boolean isRoot() { 664 return getParent() == null; 665 } 666 667 668 678 public DefaultMutableTreeNode getNextNode() { 679 if (getChildCount() == 0) { 680 DefaultMutableTreeNode nextSibling = getNextSibling(); 682 683 if (nextSibling == null) { 684 DefaultMutableTreeNode aNode = (DefaultMutableTreeNode )getParent(); 685 686 do { 687 if (aNode == null) { 688 return null; 689 } 690 691 nextSibling = aNode.getNextSibling(); 692 if (nextSibling != null) { 693 return nextSibling; 694 } 695 696 aNode = (DefaultMutableTreeNode )aNode.getParent(); 697 } while(true); 698 } else { 699 return nextSibling; 700 } 701 } else { 702 return (DefaultMutableTreeNode )getChildAt(0); 703 } 704 } 705 706 707 718 public DefaultMutableTreeNode getPreviousNode() { 719 DefaultMutableTreeNode previousSibling; 720 DefaultMutableTreeNode myParent = (DefaultMutableTreeNode )getParent(); 721 722 if (myParent == null) { 723 return null; 724 } 725 726 previousSibling = getPreviousSibling(); 727 728 if (previousSibling != null) { 729 if (previousSibling.getChildCount() == 0) 730 return previousSibling; 731 else 732 return previousSibling.getLastLeaf(); 733 } else { 734 return myParent; 735 } 736 } 737 738 749 public Enumeration preorderEnumeration() { 750 return new PreorderEnumeration(this); 751 } 752 753 766 public Enumeration postorderEnumeration() { 767 return new PostorderEnumeration(this); 768 } 769 770 781 public Enumeration breadthFirstEnumeration() { 782 return new BreadthFirstEnumeration(this); 783 } 784 785 798 public Enumeration depthFirstEnumeration() { 799 return postorderEnumeration(); 800 } 801 802 822 public Enumeration pathFromAncestorEnumeration(TreeNode ancestor) { 823 return new PathBetweenNodesEnumeration(ancestor, this); 824 } 825 826 827 831 838 public boolean isNodeChild(TreeNode aNode) { 839 boolean retval; 840 841 if (aNode == null) { 842 retval = false; 843 } else { 844 if (getChildCount() == 0) { 845 retval = false; 846 } else { 847 retval = (aNode.getParent() == this); 848 } 849 } 850 851 return retval; 852 } 853 854 855 862 public TreeNode getFirstChild() { 863 if (getChildCount() == 0) { 864 throw new NoSuchElementException("node has no children"); 865 } 866 return getChildAt(0); 867 } 868 869 870 877 public TreeNode getLastChild() { 878 if (getChildCount() == 0) { 879 throw new NoSuchElementException("node has no children"); 880 } 881 return getChildAt(getChildCount()-1); 882 } 883 884 885 899 public TreeNode getChildAfter(TreeNode aChild) { 900 if (aChild == null) { 901 throw new IllegalArgumentException ("argument is null"); 902 } 903 904 int index = getIndex(aChild); 906 if (index == -1) { 907 throw new IllegalArgumentException ("node is not a child"); 908 } 909 910 if (index < getChildCount() - 1) { 911 return getChildAt(index + 1); 912 } else { 913 return null; 914 } 915 } 916 917 918 930 public TreeNode getChildBefore(TreeNode aChild) { 931 if (aChild == null) { 932 throw new IllegalArgumentException ("argument is null"); 933 } 934 935 int index = getIndex(aChild); 937 if (index == -1) { 938 throw new IllegalArgumentException ("argument is not a child"); 939 } 940 941 if (index > 0) { 942 return getChildAt(index - 1); 943 } else { 944 return null; 945 } 946 } 947 948 949 953 954 962 public boolean isNodeSibling(TreeNode anotherNode) { 963 boolean retval; 964 965 if (anotherNode == null) { 966 retval = false; 967 } else if (anotherNode == this) { 968 retval = true; 969 } else { 970 TreeNode myParent = getParent(); 971 retval = (myParent != null && myParent == anotherNode.getParent()); 972 973 if (retval && !((DefaultMutableTreeNode )getParent()) 974 .isNodeChild(anotherNode)) { 975 throw new Error ("sibling has different parent"); 976 } 977 } 978 979 return retval; 980 } 981 982 983 990 public int getSiblingCount() { 991 TreeNode myParent = getParent(); 992 993 if (myParent == null) { 994 return 1; 995 } else { 996 return myParent.getChildCount(); 997 } 998 } 999 1000 1001 1011 public DefaultMutableTreeNode getNextSibling() { 1012 DefaultMutableTreeNode retval; 1013 1014 DefaultMutableTreeNode myParent = (DefaultMutableTreeNode )getParent(); 1015 1016 if (myParent == null) { 1017 retval = null; 1018 } else { 1019 retval = (DefaultMutableTreeNode )myParent.getChildAfter(this); } 1021 1022 if (retval != null && !isNodeSibling(retval)) { 1023 throw new Error ("child of parent is not a sibling"); 1024 } 1025 1026 return retval; 1027 } 1028 1029 1030 1038 public DefaultMutableTreeNode getPreviousSibling() { 1039 DefaultMutableTreeNode retval; 1040 1041 DefaultMutableTreeNode myParent = (DefaultMutableTreeNode )getParent(); 1042 1043 if (myParent == null) { 1044 retval = null; 1045 } else { 1046 retval = (DefaultMutableTreeNode )myParent.getChildBefore(this); } 1048 1049 if (retval != null && !isNodeSibling(retval)) { 1050 throw new Error ("child of parent is not a sibling"); 1051 } 1052 1053 return retval; 1054 } 1055 1056 1057 1058 1062 1071 public boolean isLeaf() { 1072 return (getChildCount() == 0); 1073 } 1074 1075 1076 1085 public DefaultMutableTreeNode getFirstLeaf() { 1086 DefaultMutableTreeNode node = this; 1087 1088 while (!node.isLeaf()) { 1089 node = (DefaultMutableTreeNode )node.getFirstChild(); 1090 } 1091 1092 return node; 1093 } 1094 1095 1096 1105 public DefaultMutableTreeNode getLastLeaf() { 1106 DefaultMutableTreeNode node = this; 1107 1108 while (!node.isLeaf()) { 1109 node = (DefaultMutableTreeNode )node.getLastChild(); 1110 } 1111 1112 return node; 1113 } 1114 1115 1116 1135 public DefaultMutableTreeNode getNextLeaf() { 1136 DefaultMutableTreeNode nextSibling; 1137 DefaultMutableTreeNode myParent = (DefaultMutableTreeNode )getParent(); 1138 1139 if (myParent == null) 1140 return null; 1141 1142 nextSibling = getNextSibling(); 1144 if (nextSibling != null) 1145 return nextSibling.getFirstLeaf(); 1146 1147 return myParent.getNextLeaf(); } 1149 1150 1151 1170 public DefaultMutableTreeNode getPreviousLeaf() { 1171 DefaultMutableTreeNode previousSibling; 1172 DefaultMutableTreeNode myParent = (DefaultMutableTreeNode )getParent(); 1173 1174 if (myParent == null) 1175 return null; 1176 1177 previousSibling = getPreviousSibling(); 1179 if (previousSibling != null) 1180 return previousSibling.getLastLeaf(); 1181 1182 return myParent.getPreviousLeaf(); } 1184 1185 1186 1194 public int getLeafCount() { 1195 int count = 0; 1196 1197 TreeNode node; 1198 Enumeration enum_ = breadthFirstEnumeration(); 1200 while (enum_.hasMoreElements()) { 1201 node = (TreeNode )enum_.nextElement(); 1202 if (node.isLeaf()) { 1203 count++; 1204 } 1205 } 1206 1207 if (count < 1) { 1208 throw new Error ("tree has zero leaves"); 1209 } 1210 1211 return count; 1212 } 1213 1214 1215 1219 1225 public String toString() { 1226 if (userObject == null) { 1227 return null; 1228 } else { 1229 return userObject.toString(); 1230 } 1231 } 1232 1233 1240 public Object clone() { 1241 DefaultMutableTreeNode newNode = null; 1242 1243 try { 1244 newNode = (DefaultMutableTreeNode )super.clone(); 1245 1246 newNode.children = null; 1248 newNode.parent = null; 1249 1250 } catch (CloneNotSupportedException e) { 1251 throw new Error (e.toString()); 1253 } 1254 1255 return newNode; 1256 } 1257 1258 1259 private void writeObject(ObjectOutputStream s) throws IOException { 1261 Object [] tValues; 1262 1263 s.defaultWriteObject(); 1264 if(userObject != null && userObject instanceof Serializable) { 1266 tValues = new Object [2]; 1267 tValues[0] = "userObject"; 1268 tValues[1] = userObject; 1269 } 1270 else 1271 tValues = new Object [0]; 1272 s.writeObject(tValues); 1273 } 1274 1275 private void readObject(ObjectInputStream s) 1276 throws IOException, ClassNotFoundException { 1277 Object [] tValues; 1278 1279 s.defaultReadObject(); 1280 1281 tValues = (Object [])s.readObject(); 1282 1283 if(tValues.length > 0 && tValues[0].equals("userObject")) 1284 userObject = tValues[1]; 1285 } 1286 1287 final class PreorderEnumeration implements Enumeration<TreeNode > { 1288 protected Stack stack; 1289 1290 public PreorderEnumeration(TreeNode rootNode) { 1291 super(); 1292 Vector v = new Vector(1); 1293 v.addElement(rootNode); stack = new Stack(); 1295 stack.push(v.elements()); 1296 } 1297 1298 public boolean hasMoreElements() { 1299 return (!stack.empty() && 1300 ((Enumeration)stack.peek()).hasMoreElements()); 1301 } 1302 1303 public TreeNode nextElement() { 1304 Enumeration enumer = (Enumeration)stack.peek(); 1305 TreeNode node = (TreeNode )enumer.nextElement(); 1306 Enumeration children = node.children(); 1307 1308 if (!enumer.hasMoreElements()) { 1309 stack.pop(); 1310 } 1311 if (children.hasMoreElements()) { 1312 stack.push(children); 1313 } 1314 return node; 1315 } 1316 1317 } 1319 1320 1321 final class PostorderEnumeration implements Enumeration<TreeNode > { 1322 protected TreeNode root; 1323 protected Enumeration<TreeNode > children; 1324 protected Enumeration<TreeNode > subtree; 1325 1326 public PostorderEnumeration(TreeNode rootNode) { 1327 super(); 1328 root = rootNode; 1329 children = root.children(); 1330 subtree = EMPTY_ENUMERATION; 1331 } 1332 1333 public boolean hasMoreElements() { 1334 return root != null; 1335 } 1336 1337 public TreeNode nextElement() { 1338 TreeNode retval; 1339 1340 if (subtree.hasMoreElements()) { 1341 retval = subtree.nextElement(); 1342 } else if (children.hasMoreElements()) { 1343 subtree = new PostorderEnumeration( 1344 (TreeNode )children.nextElement()); 1345 retval = subtree.nextElement(); 1346 } else { 1347 retval = root; 1348 root = null; 1349 } 1350 1351 return retval; 1352 } 1353 1354 } 1356 1357 1358 final class BreadthFirstEnumeration implements Enumeration<TreeNode > { 1359 protected Queue queue; 1360 1361 public BreadthFirstEnumeration(TreeNode rootNode) { 1362 super(); 1363 Vector v = new Vector(1); 1364 v.addElement(rootNode); queue = new Queue(); 1366 queue.enqueue(v.elements()); 1367 } 1368 1369 public boolean hasMoreElements() { 1370 return (!queue.isEmpty() && 1371 ((Enumeration)queue.firstObject()).hasMoreElements()); 1372 } 1373 1374 public TreeNode nextElement() { 1375 Enumeration enumer = (Enumeration)queue.firstObject(); 1376 TreeNode node = (TreeNode )enumer.nextElement(); 1377 Enumeration children = node.children(); 1378 1379 if (!enumer.hasMoreElements()) { 1380 queue.dequeue(); 1381 } 1382 if (children.hasMoreElements()) { 1383 queue.enqueue(children); 1384 } 1385 return node; 1386 } 1387 1388 1389 final class Queue { 1391 QNode head; QNode tail; 1393 1394 final class QNode { 1395 public Object object; 1396 public QNode next; public QNode(Object object, QNode next) { 1398 this.object = object; 1399 this.next = next; 1400 } 1401 } 1402 1403 public void enqueue(Object anObject) { 1404 if (head == null) { 1405 head = tail = new QNode(anObject, null); 1406 } else { 1407 tail.next = new QNode(anObject, null); 1408 tail = tail.next; 1409 } 1410 } 1411 1412 public Object dequeue() { 1413 if (head == null) { 1414 throw new NoSuchElementException("No more elements"); 1415 } 1416 1417 Object retval = head.object; 1418 QNode oldHead = head; 1419 head = head.next; 1420 if (head == null) { 1421 tail = null; 1422 } else { 1423 oldHead.next = null; 1424 } 1425 return retval; 1426 } 1427 1428 public Object firstObject() { 1429 if (head == null) { 1430 throw new NoSuchElementException("No more elements"); 1431 } 1432 1433 return head.object; 1434 } 1435 1436 public boolean isEmpty() { 1437 return head == null; 1438 } 1439 1440 } 1442 } 1444 1445 1446 final class PathBetweenNodesEnumeration implements Enumeration<TreeNode > { 1447 protected Stack<TreeNode > stack; 1448 1449 public PathBetweenNodesEnumeration(TreeNode ancestor, 1450 TreeNode descendant) 1451 { 1452 super(); 1453 1454 if (ancestor == null || descendant == null) { 1455 throw new IllegalArgumentException ("argument is null"); 1456 } 1457 1458 TreeNode current; 1459 1460 stack = new Stack<TreeNode >(); 1461 stack.push(descendant); 1462 1463 current = descendant; 1464 while (current != ancestor) { 1465 current = current.getParent(); 1466 if (current == null && descendant != ancestor) { 1467 throw new IllegalArgumentException ("node " + ancestor + 1468 " is not an ancestor of " + descendant); 1469 } 1470 stack.push(current); 1471 } 1472 } 1473 1474 public boolean hasMoreElements() { 1475 return stack.size() > 0; 1476 } 1477 1478 public TreeNode nextElement() { 1479 try { 1480 return stack.pop(); 1481 } catch (EmptyStackException e) { 1482 throw new NoSuchElementException("No more elements"); 1483 } 1484 } 1485 1486 } 1488 1489 1490} | Popular Tags |