Overview Package Class Use Source Tree Index Deprecated About
GNU Classpath (0.95)
Frames | No Frames

Source for javax.swing.tree.DefaultMutableTreeNode

 1:  /* DefaultMutableTreeNode.java --
 2:  Copyright (C) 2002, 2004, 2005, 2006, Free Software Foundation, Inc.
 3: 
 4: This file is part of GNU Classpath.
 5: 
 6: GNU Classpath is free software; you can redistribute it and/or modify
 7: it under the terms of the GNU General Public License as published by
 8: the Free Software Foundation; either version 2, or (at your option)
 9: any later version.
 10: 
 11: GNU Classpath is distributed in the hope that it will be useful, but
 12: WITHOUT ANY WARRANTY; without even the implied warranty of
 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 14: General Public License for more details.
 15: 
 16: You should have received a copy of the GNU General Public License
 17: along with GNU Classpath; see the file COPYING. If not, write to the
 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 19: 02110-1301 USA.
 20: 
 21: Linking this library statically or dynamically with other modules is
 22: making a combined work based on this library. Thus, the terms and
 23: conditions of the GNU General Public License cover the whole
 24: combination.
 25: 
 26: As a special exception, the copyright holders of this library give you
 27: permission to link this library with independent modules to produce an
 28: executable, regardless of the license terms of these independent
 29: modules, and to copy and distribute the resulting executable under
 30: terms of your choice, provided that you also meet, for each linked
 31: independent module, the terms and conditions of the license of that
 32: module. An independent module is a module which is not derived from
 33: or based on this library. If you modify this library, you may extend
 34: this exception to your version of the library, but you are not
 35: obligated to do so. If you do not wish to do so, delete this
 36: exception statement from your version. */
 37: 
 38: 
 39:  package javax.swing.tree;
 40: 
 41:  import gnu.java.util.EmptyEnumeration;
 42: 
 43:  import java.io.IOException;
 44:  import java.io.ObjectInputStream;
 45:  import java.io.ObjectOutputStream;
 46:  import java.io.Serializable;
 47:  import java.util.ArrayList;
 48:  import java.util.Enumeration;
 49:  import java.util.LinkedList;
 50:  import java.util.NoSuchElementException;
 51:  import java.util.Stack;
 52:  import java.util.Vector;
 53: 
 54: 
 55:  /**
 56:  * A default implementation of the {@link MutableTreeNode} interface.
 57:  *
 58:  * @author Andrew Selkirk
 59:  * @author Robert Schuster (robertschuster@fsfe.org)
 60:  */
 61:  public class DefaultMutableTreeNode
 62:  implements Cloneable, MutableTreeNode, Serializable
 63: {
 64:  private static final long serialVersionUID = -4298474751201349152L;
 65: 
 66:  /**
 67:  * An empty enumeration, returned by {@link #children()} if a node has no
 68:  * children.
 69:  */
 70:  public static final Enumeration<TreeNode> EMPTY_ENUMERATION =
 71:  EmptyEnumeration.getInstance();
 72: 
 73:  /**
 74:  * The parent of this node (possibly <code>null</code>).
 75:  */
 76:  protected MutableTreeNode parent;
 77: 
 78:  /**
 79:  * The child nodes for this node (may be empty).
 80:  */
 81:  protected Vector<MutableTreeNode> children = new Vector<MutableTreeNode>();
 82: 
 83:  /**
 84:  * userObject
 85:  */
 86:  protected transient Object userObject;
 87: 
 88:  /**
 89:  * allowsChildren
 90:  */
 91:  protected boolean allowsChildren;
 92: 
 93:  /**
 94:  * Creates a <code>DefaultMutableTreeNode</code> object.
 95:  * This is equivalent to <code>DefaultMutableTreeNode(null, true)</code>.
 96:  */
 97:  public DefaultMutableTreeNode()
 98:  {
 99:  this(null, true);
 100:  }
 101: 
 102:  /**
 103:  * Creates a <code>DefaultMutableTreeNode</code> object with the given
 104:  * user object attached to it. This is equivalent to 
 105:  * <code>DefaultMutableTreeNode(userObject, true)</code>.
 106:  *
 107:  * @param userObject the user object (<code>null</code> permitted).
 108:  */
 109:  public DefaultMutableTreeNode(Object userObject)
 110:  {
 111:  this(userObject, true);
 112:  }
 113: 
 114:  /**
 115:  * Creates a <code>DefaultMutableTreeNode</code> object with the given
 116:  * user object attached to it.
 117:  *
 118:  * @param userObject the user object (<code>null</code> permitted).
 119:  * @param allowsChildren <code>true</code> if the code allows to add child
 120:  * nodes, <code>false</code> otherwise
 121:  */
 122:  public DefaultMutableTreeNode(Object userObject, boolean allowsChildren)
 123:  {
 124:  this.userObject = userObject;
 125:  this.allowsChildren = allowsChildren;
 126:  }
 127: 
 128:  /**
 129:  * Returns a clone of the node. The clone contains a shallow copy of the 
 130:  * user object, and does not copy the parent node or the child nodes.
 131:  *
 132:  * @return A clone of the node.
 133:  */
 134:  public Object clone()
 135:  {
 136:  return new DefaultMutableTreeNode(this.userObject, this.allowsChildren);
 137:  }
 138: 
 139:  /**
 140:  * Returns a string representation of the node. This implementation returns
 141:  * <code>getUserObject().toString()</code>, or <code>null</code> if there
 142:  * is no user object.
 143:  *
 144:  * @return A string representation of the node (possibly <code>null</code>).
 145:  */
 146:  public String toString()
 147:  {
 148:  if (userObject == null)
 149:  return null;
 150: 
 151:  return userObject.toString();
 152:  }
 153: 
 154:  /**
 155:  * Adds a new child node to this node and sets this node as the parent of
 156:  * the child node. The child node must not be an ancestor of this node.
 157:  * If the tree uses the {@link DefaultTreeModel}, you must subsequently
 158:  * call {@link DefaultTreeModel#reload(TreeNode)}.
 159:  *
 160:  * @param child the child node (<code>null</code> not permitted).
 161:  *
 162:  * @throws IllegalStateException if {@link #getAllowsChildren()} returns 
 163:  * <code>false</code>.
 164:  * @throws IllegalArgumentException if {@link #isNodeAncestor} returns
 165:  * <code>true</code>. 
 166:  * @throws IllegalArgumentException if <code>child</code> is 
 167:  * <code>null</code>.
 168:  */
 169:  public void add(MutableTreeNode child)
 170:  {
 171:  if (! allowsChildren)
 172:  throw new IllegalStateException();
 173:  
 174:  if (child == null)
 175:  throw new IllegalArgumentException();
 176: 
 177:  if (isNodeAncestor(child))
 178:  throw new IllegalArgumentException("Cannot add ancestor node.");
 179:  
 180:  children.add(child);
 181:  child.setParent(this);
 182:  }
 183: 
 184:  /**
 185:  * Returns the parent node of this node.
 186:  *
 187:  * @return The parent node (possibly <code>null</code>).
 188:  */
 189:  public TreeNode getParent()
 190:  {
 191:  return parent;
 192:  }
 193: 
 194:  /**
 195:  * Removes the child with the given index from this node.
 196:  *
 197:  * @param index the index (in the range <code>0</code> to 
 198:  * <code>getChildCount() - 1</code>).
 199:  * 
 200:  * @throws ArrayIndexOutOfBoundsException if <code>index</code> is outside 
 201:  * the valid range.
 202:  */
 203:  public void remove(int index)
 204:  {
 205:  MutableTreeNode child = (MutableTreeNode) children.remove(index);
 206:  child.setParent(null);
 207:  }
 208: 
 209:  /**
 210:  * Removes the given child from this node and sets its parent to 
 211:  * <code>null</code>.
 212:  *
 213:  * @param node the child node (<code>null</code> not permitted).
 214:  * 
 215:  * @throws IllegalArgumentException if <code>node</code> is not a child of 
 216:  * this node.
 217:  * @throws IllegalArgumentException if <code>node</code> is null.
 218:  */
 219:  public void remove(MutableTreeNode node)
 220:  {
 221:  if (node == null)
 222:  throw new IllegalArgumentException("Null 'node' argument.");
 223:  if (node.getParent() != this)
 224:  throw new IllegalArgumentException(
 225:  "The given 'node' is not a child of this node.");
 226:  children.remove(node);
 227:  node.setParent(null);
 228:  }
 229: 
 230:  /**
 231:  * writeObject
 232:  *
 233:  * @param stream the output stream
 234:  *
 235:  * @exception IOException If an error occurs
 236:  */
 237:  private void writeObject(ObjectOutputStream stream)
 238:  throws IOException
 239:  {
 240:  // TODO: Implement me.
 241:  }
 242: 
 243:  /**
 244:  * readObject
 245:  *
 246:  * @param stream the input stream
 247:  *
 248:  * @exception IOException If an error occurs
 249:  * @exception ClassNotFoundException TODO
 250:  */
 251:  private void readObject(ObjectInputStream stream)
 252:  throws IOException, ClassNotFoundException
 253:  {
 254:  // TODO: Implement me.
 255:  }
 256: 
 257:  /**
 258:  * Inserts given child node at the given index.
 259:  *
 260:  * @param node the child node (<code>null</code> not permitted).
 261:  * @param index the index.
 262:  * 
 263:  * @throws IllegalArgumentException if <code>node</code> is 
 264:  * </code>null</code>.
 265:  */
 266:  public void insert(MutableTreeNode node, int index)
 267:  {
 268:  if (! allowsChildren)
 269:  throw new IllegalStateException();
 270: 
 271:  if (node == null)
 272:  throw new IllegalArgumentException("Null 'node' argument.");
 273:  
 274:  if (isNodeAncestor(node))
 275:  throw new IllegalArgumentException("Cannot insert ancestor node.");
 276: 
 277:  children.insertElementAt(node, index);
 278:  }
 279: 
 280:  /**
 281:  * Returns a path to this node from the root.
 282:  *
 283:  * @return an array of tree nodes
 284:  */
 285:  public TreeNode[] getPath()
 286:  {
 287:  return getPathToRoot(this, 0);
 288:  }
 289: 
 290:  /**
 291:  * Returns an enumeration containing all children of this node.
 292:  * <code>EMPTY_ENUMERATION</code> is returned if this node has no children.
 293:  *
 294:  * @return an enumeration of tree nodes
 295:  */
 296:  public Enumeration children()
 297:  {
 298:  if (children.size() == 0)
 299:  return EMPTY_ENUMERATION;
 300:  
 301:  return children.elements();
 302:  }
 303: 
 304:  /**
 305:  * Set the parent node for this node.
 306:  *
 307:  * @param node the parent node
 308:  */
 309:  public void setParent(MutableTreeNode node)
 310:  {
 311:  parent = node;
 312:  }
 313: 
 314:  /**
 315:  * Returns the child node at a given index.
 316:  *
 317:  * @param index the index
 318:  *
 319:  * @return the child node
 320:  */
 321:  public TreeNode getChildAt(int index)
 322:  {
 323:  return (TreeNode) children.elementAt(index);
 324:  }
 325: 
 326:  /**
 327:  * Returns the number of children of this node.
 328:  *
 329:  * @return the number of children
 330:  */
 331:  public int getChildCount()
 332:  {
 333:  return children.size();
 334:  }
 335: 
 336:  /**
 337:  * Returns the index of the specified child node, or -1 if the node is not
 338:  * in fact a child of this node.
 339:  * 
 340:  * @param node the node (<code>null</code> not permitted).
 341:  * 
 342:  * @return The index of the specified child node, or -1.
 343:  * 
 344:  * @throws IllegalArgumentException if <code>node</code> is <code>null</code>.
 345:  */
 346:  public int getIndex(TreeNode node)
 347:  {
 348:  if (node == null)
 349:  throw new IllegalArgumentException("Null 'node' argument.");
 350:  return children.indexOf(node);
 351:  }
 352: 
 353:  /**
 354:  * Sets the flag that controls whether or not this node allows the addition / 
 355:  * insertion of child nodes. If the flag is set to <code>false</code>, any
 356:  * existing children are removed.
 357:  *
 358:  * @param allowsChildren the flag.
 359:  */
 360:  public void setAllowsChildren(boolean allowsChildren)
 361:  {
 362:  if (!allowsChildren)
 363:  removeAllChildren();
 364:  this.allowsChildren = allowsChildren;
 365:  }
 366: 
 367:  /**
 368:  * getAllowsChildren
 369:  *
 370:  * @return boolean
 371:  */
 372:  public boolean getAllowsChildren()
 373:  {
 374:  return allowsChildren;
 375:  }
 376: 
 377:  /**
 378:  * Sets the user object for this node
 379:  *
 380:  * @param userObject the user object
 381:  */
 382:  public void setUserObject(Object userObject)
 383:  {
 384:  this.userObject = userObject;
 385:  }
 386: 
 387:  /**
 388:  * Returns the user object attached to this node. <code>null</code> is
 389:  * returned when no user object is set.
 390:  *
 391:  * @return the user object
 392:  */
 393:  public Object getUserObject()
 394:  {
 395:  return userObject;
 396:  }
 397: 
 398:  /**
 399:  * Removes this node from its parent.
 400:  */
 401:  public void removeFromParent()
 402:  {
 403:  parent.remove(this);
 404:  parent = null;
 405:  }
 406: 
 407:  /**
 408:  * Removes all child nodes from this node.
 409:  */
 410:  public void removeAllChildren()
 411:  {
 412:  for (int i = getChildCount() - 1; i >= 0; i--)
 413:  remove(i);
 414:  }
 415: 
 416:  /**
 417:  * Returns <code>true</code> if <code>node</code> is an ancestor of this
 418:  * tree node, and <code>false</code> otherwise. An ancestor node is any of:
 419:  * <ul>
 420:  * <li>this tree node;</li>
 421:  * <li>the parent node (if there is one);</li>
 422:  * <li>any ancestor of the parent node;</li>
 423:  * </ul>
 424:  * If <code>node</code> is <code>null</code>, this method returns 
 425:  * <code>false</code>.
 426:  * 
 427:  * @param node the node (<code>null</code> permitted).
 428:  *
 429:  * @return A boolean.
 430:  */
 431:  public boolean isNodeAncestor(TreeNode node)
 432:  {
 433:  if (node == null)
 434:  return false;
 435: 
 436:  TreeNode current = this;
 437: 
 438:  while (current != null && current != node)
 439:  current = current.getParent();
 440: 
 441:  return current == node;
 442:  }
 443: 
 444:  /**
 445:  * Returns <code>true</code> if <code>node</code> is a descendant of this
 446:  * tree node, and <code>false</code> otherwise. A descendant node is any of:
 447:  * <ul>
 448:  * <li>this tree node;</li>
 449:  * <li>the child nodes belonging to this tree node, if there are any;</li>
 450:  * <li>any descendants of the child nodes;</li>
 451:  * </ul>
 452:  * If <code>node</code> is <code>null</code>, this method returns 
 453:  * <code>false</code>.
 454:  * 
 455:  * @param node the node (<code>null</code> permitted).
 456:  *
 457:  * @return A boolean.
 458:  */
 459:  public boolean isNodeDescendant(DefaultMutableTreeNode node)
 460:  {
 461:  if (node == null)
 462:  return false;
 463: 
 464:  TreeNode current = node;
 465:  
 466:  while (current != null
 467:  && current != this)
 468:  current = current.getParent();
 469: 
 470:  return current == this;
 471:  }
 472: 
 473:  /**
 474:  * getSharedAncestor
 475:  *
 476:  * @param node TODO
 477:  *
 478:  * @return TreeNode
 479:  */
 480:  public TreeNode getSharedAncestor(DefaultMutableTreeNode node)
 481:  {
 482:  TreeNode current = this;
 483:  ArrayList<TreeNode> list = new ArrayList<TreeNode>();
 484: 
 485:  while (current != null)
 486:  {
 487:  list.add(current);
 488:  current = current.getParent();
 489:  }
 490: 
 491:  current = node;
 492: 
 493:  while (current != null)
 494:  {
 495:  if (list.contains(current))
 496:  return current;
 497: 
 498:  current = current.getParent();
 499:  }
 500: 
 501:  return null;
 502:  }
 503: 
 504:  /**
 505:  * isNodeRelated
 506:  *
 507:  * @param node TODO
 508:  *
 509:  * @return boolean
 510:  */
 511:  public boolean isNodeRelated(DefaultMutableTreeNode node)
 512:  {
 513:  if (node == null)
 514:  return false;
 515: 
 516:  return node.getRoot() == getRoot();
 517:  }
 518: 
 519:  /**
 520:  * getDepth
 521:  *
 522:  * @return int
 523:  */
 524:  public int getDepth()
 525:  {
 526:  if ((! allowsChildren)
 527:  || children.size() == 0)
 528:  return 0;
 529: 
 530:  Stack<Integer> stack = new Stack<Integer>();
 531:  stack.push(new Integer(0));
 532:  TreeNode node = getChildAt(0);
 533:  int depth = 0;
 534:  int current = 1;
 535:  
 536:  while (! stack.empty())
 537:  {
 538:  if (node.getChildCount() != 0)
 539:  {
 540:  node = node.getChildAt(0);
 541:  stack.push(new Integer(0));
 542:  current++;
 543:  }
 544:  else
 545:  {
 546:  if (current > depth)
 547:  depth = current;
 548: 
 549:  int size;
 550:  int index;
 551:  
 552:  do
 553:  {
 554:  node = node.getParent();
 555:  size = node.getChildCount();
 556:  index = ((Integer) stack.pop()).intValue() + 1;
 557:  current--;
 558:  }
 559:  while (index >= size
 560:  && node != this);
 561: 
 562:  if (index < size)
 563:  {
 564:  node = node.getChildAt(index);
 565:  stack.push(new Integer(index));
 566:  current++;
 567:  }
 568:  }
 569:  }
 570: 
 571:  return depth;
 572:  }
 573: 
 574:  /**
 575:  * getLevel
 576:  *
 577:  * @return int
 578:  */
 579:  public int getLevel()
 580:  {
 581:  int count = -1;
 582:  TreeNode current = this;
 583: 
 584:  do
 585:  {
 586:  current = current.getParent();
 587:  count++;
 588:  }
 589:  while (current != null);
 590: 
 591:  return count;
 592:  }
 593: 
 594:  /**
 595:  * getPathToRoot
 596:  *
 597:  * @param node TODO
 598:  * @param depth TODO
 599:  *
 600:  * @return TreeNode[]
 601:  */
 602:  protected TreeNode[] getPathToRoot(TreeNode node, int depth)
 603:  {
 604:  if (node == null)
 605:  {
 606:  if (depth == 0)
 607:  return null;
 608:  
 609:  return new TreeNode[depth];
 610:  }
 611: 
 612:  TreeNode[] path = getPathToRoot(node.getParent(), depth + 1);
 613:  path[path.length - depth - 1] = node;
 614:  return path;
 615:  }
 616: 
 617:  /**
 618:  * getUserObjectPath
 619:  *
 620:  * @return Object[]
 621:  */
 622:  public Object[] getUserObjectPath()
 623:  {
 624:  TreeNode[] path = getPathToRoot(this, 0);
 625:  Object[] object = new Object[path.length];
 626:  
 627:  for (int index = 0; index < path.length; ++index)
 628:  object[index] = ((DefaultMutableTreeNode) path[index]).getUserObject();
 629: 
 630:  return object;
 631:  }
 632: 
 633:  /**
 634:  * Returns the root node by iterating the parents of this node.
 635:  *
 636:  * @return the root node
 637:  */
 638:  public TreeNode getRoot()
 639:  {
 640:  TreeNode current = this;
 641:  TreeNode check = current.getParent();
 642:  
 643:  while (check != null)
 644:  {
 645:  current = check;
 646:  check = current.getParent();
 647:  }
 648: 
 649:  return current;
 650:  }
 651: 
 652:  /**
 653:  * Tells whether this node is the root node or not.
 654:  *
 655:  * @return <code>true</code> if this is the root node,
 656:  * <code>false</code>otherwise
 657:  */
 658:  public boolean isRoot()
 659:  {
 660:  return parent == null;
 661:  }
 662: 
 663:  /**
 664:  * getNextNode
 665:  *
 666:  * @return DefaultMutableTreeNode
 667:  */
 668:  public DefaultMutableTreeNode getNextNode()
 669:  {
 670:  // Return first child.
 671:  if (getChildCount() != 0)
 672:  return (DefaultMutableTreeNode) getChildAt(0);
 673: 
 674:  // Return next sibling (if needed the sibling of some parent).
 675:  DefaultMutableTreeNode node = this;
 676:  DefaultMutableTreeNode sibling;
 677:  
 678:  do
 679:  {
 680:  sibling = node.getNextSibling();
 681:  node = (DefaultMutableTreeNode) node.getParent();
 682:  }
 683:  while (sibling == null &&
 684:  node != null);
 685:  
 686:  // Return sibling.
 687:  return sibling;
 688:  }
 689: 
 690:  /**
 691:  * getPreviousNode
 692:  *
 693:  * @return DefaultMutableTreeNode
 694:  */
 695:  public DefaultMutableTreeNode getPreviousNode()
 696:  {
 697:  // Return null if no parent.
 698:  if (parent == null)
 699:  return null;
 700:  
 701:  DefaultMutableTreeNode sibling = getPreviousSibling();
 702: 
 703:  // Return parent if no sibling.
 704:  if (sibling == null)
 705:  return (DefaultMutableTreeNode) parent;
 706: 
 707:  // Return last leaf of sibling.
 708:  if (sibling.getChildCount() != 0)
 709:  return sibling.getLastLeaf();
 710: 
 711:  // Return sibling.
 712:  return sibling;
 713:  }
 714: 
 715:  /**
 716:  * preorderEnumeration
 717:  *
 718:  * @return Enumeration
 719:  */
 720:  public Enumeration preorderEnumeration()
 721:  {
 722:  return new PreorderEnumeration(this);
 723:  }
 724: 
 725:  /**
 726:  * postorderEnumeration
 727:  *
 728:  * @return Enumeration
 729:  */
 730:  public Enumeration postorderEnumeration()
 731:  {
 732:  return new PostorderEnumeration(this);
 733:  }
 734: 
 735:  /**
 736:  * breadthFirstEnumeration
 737:  *
 738:  * @return Enumeration
 739:  */
 740:  public Enumeration breadthFirstEnumeration()
 741:  {
 742:  return new BreadthFirstEnumeration(this);
 743:  }
 744: 
 745:  /**
 746:  * depthFirstEnumeration
 747:  *
 748:  * @return Enumeration
 749:  */
 750:  public Enumeration depthFirstEnumeration()
 751:  {
 752:  return postorderEnumeration();
 753:  }
 754: 
 755:  /**
 756:  * pathFromAncestorEnumeration
 757:  *
 758:  * @param node TODO
 759:  *
 760:  * @return Enumeration
 761:  */
 762:  public Enumeration pathFromAncestorEnumeration(TreeNode node)
 763:  {
 764:  if (node == null)
 765:  throw new IllegalArgumentException();
 766:  
 767:  TreeNode parent = this;
 768:  Vector<TreeNode> nodes = new Vector<TreeNode>();
 769:  nodes.add(this);
 770: 
 771:  while (parent != node && parent != null)
 772:  {
 773:  parent = parent.getParent();
 774:  nodes.add(0, parent);
 775:  }
 776: 
 777:  if (parent != node)
 778:  throw new IllegalArgumentException();
 779:  
 780:  return nodes.elements();
 781:  }
 782: 
 783:  /**
 784:  * Returns <code>true</code> if <code>node</code> is a child of this tree 
 785:  * node, and <code>false</code> otherwise. If <code>node</code> is 
 786:  * <code>null</code>, this method returns <code>false</code>.
 787:  *
 788:  * @param node the node (<code>null</code> permitted).
 789:  *
 790:  * @return A boolean.
 791:  */
 792:  public boolean isNodeChild(TreeNode node)
 793:  {
 794:  if (node == null)
 795:  return false;
 796: 
 797:  return node.getParent() == this;
 798:  }
 799: 
 800:  /**
 801:  * Returns the first child node belonging to this tree node.
 802:  *
 803:  * @return The first child node.
 804:  * 
 805:  * @throws NoSuchElementException if this tree node has no children.
 806:  */
 807:  public TreeNode getFirstChild()
 808:  {
 809:  return (TreeNode) children.firstElement();
 810:  }
 811: 
 812:  /**
 813:  * Returns the last child node belonging to this tree node.
 814:  *
 815:  * @return The last child node.
 816:  * 
 817:  * @throws NoSuchElementException if this tree node has no children.
 818:  */
 819:  public TreeNode getLastChild()
 820:  {
 821:  return (TreeNode) children.lastElement();
 822:  }
 823: 
 824:  /**
 825:  * Returns the next child after the specified <code>node</code>, or 
 826:  * <code>null</code> if there is no child after the specified 
 827:  * <code>node</code>.
 828:  *
 829:  * @param node a child of this node (<code>null</code> not permitted).
 830:  *
 831:  * @return The next child, or <code>null</code>.
 832:  * 
 833:  * @throws IllegalArgumentException if <code>node</code> is not a child of 
 834:  * this node, or is <code>null</code>.
 835:  */
 836:  public TreeNode getChildAfter(TreeNode node)
 837:  {
 838:  if (node == null || node.getParent() != this)
 839:  throw new IllegalArgumentException();
 840: 
 841:  int index = getIndex(node) + 1;
 842: 
 843:  if (index == getChildCount())
 844:  return null;
 845: 
 846:  return getChildAt(index);
 847:  }
 848: 
 849:  /**
 850:  * Returns the previous child before the specified <code>node</code>, or 
 851:  * <code>null</code> if there is no child before the specified 
 852:  * <code>node</code>.
 853:  *
 854:  * @param node a child of this node (<code>null</code> not permitted).
 855:  *
 856:  * @return The previous child, or <code>null</code>.
 857:  * 
 858:  * @throws IllegalArgumentException if <code>node</code> is not a child of 
 859:  * this node, or is <code>null</code>.
 860:  */
 861:  public TreeNode getChildBefore(TreeNode node)
 862:  {
 863:  if (node == null || node.getParent() != this)
 864:  throw new IllegalArgumentException();
 865: 
 866:  int index = getIndex(node) - 1;
 867: 
 868:  if (index < 0)
 869:  return null;
 870: 
 871:  return getChildAt(index);
 872:  }
 873: 
 874:  /**
 875:  * Returns <code>true</code> if this tree node and <code>node</code> share
 876:  * the same parent. If <code>node</code> is this tree node, the method
 877:  * returns <code>true</code> and if <code>node</code> is <code>null</code>
 878:  * this method returns <code>false</code>.
 879:  *
 880:  * @param node the node (<code>null</code> permitted).
 881:  *
 882:  * @return A boolean.
 883:  */
 884:  public boolean isNodeSibling(TreeNode node)
 885:  {
 886:  if (node == null)
 887:  return false;
 888:  if (node == this)
 889:  return true;
 890:  return node.getParent() == getParent() && getParent() != null;
 891:  }
 892: 
 893:  /**
 894:  * Returns the number of siblings for this tree node. If the tree node has
 895:  * a parent, this method returns the child count for the parent, otherwise
 896:  * it returns <code>1</code>.
 897:  *
 898:  * @return The sibling count.
 899:  */
 900:  public int getSiblingCount()
 901:  {
 902:  if (parent == null)
 903:  return 1;
 904: 
 905:  return parent.getChildCount();
 906:  }
 907: 
 908:  /**
 909:  * Returns the next sibling for this tree node. If this node has no parent,
 910:  * or this node is the last child of its parent, this method returns 
 911:  * <code>null</code>. 
 912:  *
 913:  * @return The next sibling, or <code>null</code>.
 914:  */
 915:  public DefaultMutableTreeNode getNextSibling()
 916:  {
 917:  if (parent == null)
 918:  return null;
 919: 
 920:  int index = parent.getIndex(this) + 1;
 921:  
 922:  if (index == parent.getChildCount())
 923:  return null;
 924: 
 925:  return (DefaultMutableTreeNode) parent.getChildAt(index);
 926:  }
 927: 
 928:  /**
 929:  * Returns the previous sibling for this tree node. If this node has no 
 930:  * parent, or this node is the first child of its parent, this method returns 
 931:  * <code>null</code>. 
 932:  *
 933:  * @return The previous sibling, or <code>null</code>.
 934:  */
 935:  public DefaultMutableTreeNode getPreviousSibling()
 936:  {
 937:  if (parent == null)
 938:  return null;
 939: 
 940:  int index = parent.getIndex(this) - 1;
 941: 
 942:  if (index < 0)
 943:  return null;
 944: 
 945:  return (DefaultMutableTreeNode) parent.getChildAt(index);
 946:  }
 947: 
 948:  /**
 949:  * Returns <code>true</code> if this tree node is a lead node (that is, it 
 950:  * has no children), and <code>false</otherwise>.
 951:  *
 952:  * @return A boolean.
 953:  */
 954:  public boolean isLeaf()
 955:  {
 956:  return children.size() == 0;
 957:  }
 958: 
 959:  /**
 960:  * Returns the first leaf node that is a descendant of this node. Recall 
 961:  * that a node is its own descendant, so if this node has no children then 
 962:  * it is returned as the first leaf.
 963:  *
 964:  * @return The first leaf node.
 965:  */
 966:  public DefaultMutableTreeNode getFirstLeaf()
 967:  {
 968:  TreeNode current = this;
 969:  
 970:  while (current.getChildCount() > 0)
 971:  current = current.getChildAt(0);
 972: 
 973:  return (DefaultMutableTreeNode) current;
 974:  }
 975: 
 976:  /**
 977:  * Returns the last leaf node that is a descendant of this node. Recall 
 978:  * that a node is its own descendant, so if this node has no children then 
 979:  * it is returned as the last leaf.
 980:  *
 981:  * @return The first leaf node.
 982:  */
 983:  public DefaultMutableTreeNode getLastLeaf()
 984:  {
 985:  TreeNode current = this;
 986:  int size = current.getChildCount();
 987:  
 988:  while (size > 0)
 989:  {
 990:  current = current.getChildAt(size - 1);
 991:  size = current.getChildCount();
 992:  }
 993: 
 994:  return (DefaultMutableTreeNode) current;
 995:  }
 996: 
 997:  /**
 998:  * Returns the next leaf node after this tree node. 
 999:  *
1000:  * @return The next leaf node, or <code>null</code>.
1001:  */
1002:  public DefaultMutableTreeNode getNextLeaf()
1003:  {
1004:  // if there is a next sibling, return its first leaf
1005:  DefaultMutableTreeNode sibling = getNextSibling();
1006:  if (sibling != null)
1007:  return sibling.getFirstLeaf();
1008:  // otherwise move up one level and try again...
1009:  if (parent != null)
1010:  return ((DefaultMutableTreeNode) parent).getNextLeaf();
1011:  return null;
1012:  }
1013: 
1014:  /**
1015:  * Returns the previous leaf node before this tree node.
1016:  *
1017:  * @return The previous leaf node, or <code>null</code>.
1018:  */
1019:  public DefaultMutableTreeNode getPreviousLeaf()
1020:  {
1021:  // if there is a previous sibling, return its last leaf
1022:  DefaultMutableTreeNode sibling = getPreviousSibling();
1023:  if (sibling != null)
1024:  return sibling.getLastLeaf();
1025:  // otherwise move up one level and try again...
1026:  if (parent != null)
1027:  return ((DefaultMutableTreeNode) parent).getPreviousLeaf();
1028:  return null;
1029:  }
1030: 
1031:  /**
1032:  * getLeafCount
1033:  *
1034:  * @return int
1035:  */
1036:  public int getLeafCount()
1037:  {
1038:  int count = 0;
1039:  Enumeration e = depthFirstEnumeration();
1040: 
1041:  while (e.hasMoreElements())
1042:  {
1043:  TreeNode current = (TreeNode) e.nextElement();
1044:  
1045:  if (current.isLeaf())
1046:  count++;
1047:  }
1048: 
1049:  return count;
1050:  }
1051: 
1052:  /** Provides an enumeration of a tree in breadth-first traversal
1053:  * order.
1054:  */
1055:  static class BreadthFirstEnumeration implements Enumeration
1056:  {
1057: 
1058:  LinkedList queue = new LinkedList();
1059: 
1060:  BreadthFirstEnumeration(TreeNode node)
1061:  {
1062:  queue.add(node);
1063:  }
1064: 
1065:  public boolean hasMoreElements()
1066:  {
1067:  return !queue.isEmpty();
1068:  }
1069: 
1070:  public Object nextElement()
1071:  {
1072:  if (queue.isEmpty())
1073:  throw new NoSuchElementException("No more elements left.");
1074: 
1075:  TreeNode node = (TreeNode) queue.removeFirst();
1076: 
1077:  Enumeration children = node.children();
1078:  while (children.hasMoreElements())
1079:  queue.add(children.nextElement());
1080: 
1081:  return node;
1082:  }
1083:  }
1084: 
1085:  /** Provides an enumeration of a tree traversing it
1086:  * preordered.
1087:  */
1088:  static class PreorderEnumeration implements Enumeration
1089:  {
1090:  TreeNode next;
1091: 
1092:  Stack childrenEnums = new Stack();
1093: 
1094:  PreorderEnumeration(TreeNode node)
1095:  {
1096:  next = node;
1097:  childrenEnums.push(node.children());
1098:  }
1099: 
1100:  public boolean hasMoreElements()
1101:  {
1102:  return next != null;
1103:  }
1104: 
1105:  public Object nextElement()
1106:  {
1107:  if (next == null)
1108:  throw new NoSuchElementException("No more elements left.");
1109: 
1110:  Object current = next;
1111: 
1112:  Enumeration children = (Enumeration) childrenEnums.peek();
1113: 
1114:  // Retrieves the next element.
1115:  next = traverse(children);
1116: 
1117:  return current;
1118:  }
1119: 
1120:  private TreeNode traverse(Enumeration children)
1121:  {
1122:  // If more children are available step down.
1123:  if (children.hasMoreElements())
1124:  {
1125:  TreeNode child = (TreeNode) children.nextElement();
1126:  childrenEnums.push(child.children());
1127: 
1128:  return child;
1129:  }
1130:  
1131:  // If no children are left, we return to a higher level.
1132:  childrenEnums.pop();
1133: 
1134:  // If there are no more levels left, there is no next
1135:  // element to return.
1136:  if (childrenEnums.isEmpty())
1137:  return null;
1138:  else
1139:  {
1140:  return traverse((Enumeration) childrenEnums.peek());
1141:  }
1142:  }
1143:  }
1144: 
1145:  /** Provides an enumeration of a tree traversing it
1146:  * postordered (= depth-first).
1147:  */
1148:  static class PostorderEnumeration implements Enumeration
1149:  {
1150: 
1151:  Stack<TreeNode> nodes = new Stack<TreeNode>();
1152:  Stack childrenEnums = new Stack();
1153: 
1154:  PostorderEnumeration(TreeNode node)
1155:  {
1156:  nodes.push(node);
1157:  childrenEnums.push(node.children());
1158:  }
1159: 
1160:  public boolean hasMoreElements()
1161:  {
1162:  return !nodes.isEmpty();
1163:  }
1164: 
1165:  public Object nextElement()
1166:  {
1167:  if (nodes.isEmpty())
1168:  throw new NoSuchElementException("No more elements left!");
1169: 
1170:  Enumeration children = (Enumeration) childrenEnums.peek();
1171: 
1172:  return traverse(children);
1173:  }
1174: 
1175:  private Object traverse(Enumeration children)
1176:  {
1177:  if (children.hasMoreElements())
1178:  {
1179:  TreeNode node = (TreeNode) children.nextElement();
1180:  nodes.push(node);
1181: 
1182:  Enumeration newChildren = node.children();
1183:  childrenEnums.push(newChildren);
1184: 
1185:  return traverse(newChildren);
1186:  }
1187:  else
1188:  {
1189:  childrenEnums.pop();
1190: 
1191:  // Returns the node whose children
1192:  // have all been visited. (= postorder)
1193:  Object next = nodes.peek();
1194:  nodes.pop();
1195: 
1196:  return next;
1197:  }
1198:  }
1199: 
1200:  }
1201: 
1202: }
Overview Package Class Use Source Tree Index Deprecated About
GNU Classpath (0.95)

AltStyle によって変換されたページ (->オリジナル) /