Source for file TreeNode.class.php

Documentation is available at TreeNode.class.php

  1. <?php
  2.  
  3. require_once(HARMONI."oki2/hierarchy/tree/TreeNode.interface.php");
  4.  
  5. /**
  6. * This is the building piece of the Tree data structure used for the backbone of the
  7. * hierarchy.
  8. *
  9. * @package harmoni.osid_v2.hierarchy.tree
  10. *
  11. * @copyright Copyright &copy; 2005, Middlebury College
  12. * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License (GPL)
  13. *
  14. * @version $Id: TreeNode.class.php,v 1.8 2007/09/04 20:25:42 adamfranco Exp $
  15. */
  16.  
  17. class TreeNode extends TreeNodeInterface
  18. { // begin Node
  19.  
  20.  
  21. /**
  22. * The id (string representation) for this node.
  23. * @var string _id
  24. * @access protected
  25. */
  26. var $_id;
  27. /**
  28. * The parents of this node. The index of
  29. * each element of the array is the string representation of the Id of the
  30. * corresponding Node.
  31. * @var array _parent
  32. * @access protected
  33. */
  34. var $_parents;
  35. /**
  36. * The children of this node. The index of
  37. * each element of the array is the string representation of the Id of the
  38. * corresponding Node.
  39. * @var array _children
  40. * @access protected
  41. */
  42. var $_children;
  43. /**
  44. * Constructor.
  45. *
  46. * @param string $id The id of this Node.
  47. */
  48. function TreeNode($id) {
  49. // ** parameter validation
  50. $stringRule = StringValidatorRule::getRule();
  51. ArgumentValidator::validate($id, $stringRule, true);
  52. // ** end of parameter validation
  53. $this->_id = $id;
  54. $this->_parents = array();
  55. $this->_children = array();
  56. }
  57.  
  58.  
  59. /**
  60. * Returns true if this TreeNode is among the children of the given node.
  61. * @access public
  62. * @param object node The node to start recursing from.
  63. * @return boolean True, if this TreeNode is among the children of <code>$node</code>.
  64. ***/
  65. function isDescendantOf($node) {
  66. // base case
  67. if ($this->_id == $node->_id)
  68. return true;
  69. // check children
  70. else
  71. foreach (array_keys($node->_children) as $i => $key)
  72. // recurse down
  73. if ($this->isDescendantOf($node->_children[$key]))
  74. return true;
  75. return false;
  76. }
  77.  
  78. /**
  79. * Adds a new child for this node.
  80. * @access public
  81. * @param ref object child The child node to add.
  82. * @return void
  83. */
  84. function addChild($child) {
  85. // echo "Adding {$child->_id} to {$this->_id} <br />";
  86. $extendsRule = ExtendsValidatorRule::getRule("TreeNodeInterface");
  87. ArgumentValidator::validate($child, $extendsRule, true);
  88.  
  89. // check whether we are duplicating $child
  90. if (isset($this->_children[$child->_id])) {
  91. $str = "A child with the given id already exists!";
  92. throwError(new Error($str, "Hierarchy", true));
  93. }
  94.  
  95. // check if we are duplicating $this
  96. $childsParents = $child->getParents();
  97. if (isset($childsParents[$this->_id])) {
  98. $str = "Child node already has a parent with the given id!";
  99. throwError(new Error($str, "Hierarchy", true));
  100. }
  101.  
  102. // now perform cycle check
  103. // **********************************************************
  104. // NB: hmmm, it this check going to slow down things a lot???
  105. // **********************************************************
  106. if ($this->isDescendantOf($child)) {
  107. $str = "Adding this node would result in a cycle!";
  108. throwError(new Error($str, "Hierarchy", true));
  109. return;
  110. }
  111.  
  112. // see if $this is among any of $child's children.
  113. // if yes, that signifies a cycle
  114.  
  115. // set parent-child relationship
  116. $child->_parents[$this->_id] =$this;
  117. $this->_children[$child->_id] =$child;
  118. }
  119. /**
  120. * Detaches the child from this node. The child remains in the hierarchy.
  121. * @access public
  122. * @param ref object child The child node to detach.
  123. * @return void
  124. ***/
  125. function detachChild($child) {
  126. // echo "Detaching {$child->_id} from {$this->_id} <br />";
  127. $extendsRule = ExtendsValidatorRule::getRule("TreeNodeInterface");
  128. ArgumentValidator::validate($child, $extendsRule, true);
  129. // echo "Removing child ".$child->_id." from parent ".$this->_id."<br />";
  130. // check if $child is really a child of $this
  131. if (!$this->isChild($child)) {
  132. $str = "The given node is not a child of this node.";
  133. throwError(new Error($str, "Hierarchy", true));
  134. }
  135. // remove $child from $this's list of children
  136. unset($this->_children[$child->_id]);
  137. unset($child->_parents[ $this->_id]);
  138. // !! NOTE: if child has no parents left, then it is now a root
  139. }
  140.  
  141.  
  142. /**
  143. * Returns the parent node of this node.
  144. * @access public
  145. * @return ref array The parent nodes of this node.
  146. */
  147. function getParents() {
  148. return $this->_parents;
  149. }
  150.  
  151. /**
  152. * Returns the number of parents for this node.
  153. * @access public
  154. * @return integer The number of parents for this node.
  155. */
  156. function getParentsCount() {
  157. return count($this->_parents);
  158. }
  159. /**
  160. * Determines if this node has any parents.
  161. * @access public
  162. * @return boolean <code>true</code> if this node has at least one parent;
  163. * <code>false</code>, otherwise.
  164. */
  165. function hasParents() {
  166. return $this->getParentsCount() > 0;
  167. }
  168.  
  169.  
  170. /**
  171. * Returns the children of this node in the order they were added.
  172. * @access public
  173. * @return ref array An array of the children nodes of this node.
  174. */
  175. function getChildren() {
  176. return $this->_children;
  177. }
  178. /**
  179. * Returns the number of children for this node.
  180. * @access public
  181. * @return integer The number of children for this node.
  182. */
  183. function getChildrenCount() {
  184. return count($this->_children);
  185. }
  186. /**
  187. * Determines if this node has any children.
  188. * @access public
  189. * @return boolean <code>true</code> if this node has at least one child;
  190. * <code>false</code>, otherwise.
  191. */
  192. function hasChildren() {
  193. return $this->getChildrenCount() > 0;
  194. }
  195.  
  196. /**
  197. * Checks if the given node is a child of this node.
  198. * @access public
  199. * @param ref object node The child node to check.
  200. * @return boolean <code>true</code> if <code>$node</code> is a child of this node.
  201. ***/
  202. function isChild($node) {
  203. $extendsRule = ExtendsValidatorRule::getRule("TreeNodeInterface");
  204. ArgumentValidator::validate($node, $extendsRule, true);
  205.  
  206. if (!isset($this->_children[$node->_id]))
  207. return false;
  208.  
  209. return ($this->_children[$node->_id]->_id === $node->_id);
  210. }
  211.  
  212.  
  213. /**
  214. * Checks if the given node is a parent of this node.
  215. * @access public
  216. * @param ref object node The child node to check.
  217. * @return boolean <code>true</code> if <code>$node</code> is a parent of this node.
  218. ***/
  219. function isParent($node) {
  220. $extendsRule = ExtendsValidatorRule::getRule("TreeNodeInterface");
  221. ArgumentValidator::validate($node, $extendsRule, true);
  222.  
  223. if (!isset($this->_parents[$node->_id]))
  224. return false;
  225.  
  226. return ($this->_parents[$node->_id]->_id === $node->_id);
  227. }
  228.  
  229. /**
  230. * Returns the id of this node.
  231. * @access public
  232. * @return string The id of this node.
  233. */
  234. function getId() {
  235. return $this->_id;
  236. }
  237. }
  238.  
  239. ?>

Documentation generated on Wed, 19 Sep 2007 10:27:34 -0400 by phpDocumentor 1.3.0RC3