rubytree 0.6.2 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,42 @@
1
+ = API Changes in RubyTree
2
+
3
+ This file documents various API level changes that have been made to the RubyTree package.
4
+
5
+ Note: API level changes are expected to reduce dramatically after the 1.x release. In most cases, an alternative will
6
+ be provided to ensure relatively smooth transition to the new APIs.
7
+
8
+ == Release 0.7.0 Changes
9
+
10
+ - Converted all exceptions thrown on invalid method arguments to from 'RuntimeError' to 'ArgumentError'. This impacts the
11
+ following methods:
12
+
13
+ - {Tree::TreeNode#initialize}
14
+ - {Tree::TreeNode#add}
15
+ - {Tree::TreeNode#[]}
16
+ - {Tree::BinaryTreeNode#add}
17
+
18
+ - Added {Tree::TreeNode#level} as an alias for {Tree::TreeNode#nodeDepth}
19
+
20
+ - Added new methods {Tree::TreeNode#in_degree} and {Tree::TreeNode#out_degree} to report the node's degree stats
21
+
22
+ - {Tree::TreeNode#isOnlyChild?} now returns +true+ for a root node.
23
+
24
+ - {Tree::TreeNode#nextSibling} and {Tree::TreeNode#previousSibling} now return +nil+ for a root node.
25
+
26
+ - {Tree::TreeNode#add} and {Tree::TreeNode#<<} now throw an ArgumentError exception if a +nil+ node is passed as an argument.
27
+
28
+ - Added new methods {Tree::TreeNode#to_json} and {Tree::TreeNode::json_create} to convert to/from the JSON format.
29
+ Thanks to Dirk[http://github.com/railsbros-dirk] for this change.
30
+
31
+ == Release 0.6.1 Changes
32
+
33
+ - Deprecated the {Tree::TreeNode#depth} method as it was returning an incorrect depth value. Have introduced a new replacement
34
+ method {Tree::TreeNode#nodeDepth} which returns the correct result.
35
+
36
+
37
+
38
+
39
+ # Local Variables:
40
+ # mode: text
41
+ # coding: utf-8-unix
42
+ # End:
data/COPYING CHANGED
@@ -27,3 +27,17 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWIS
27
27
  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
28
 
29
29
  $Id$
30
+
31
+
32
+
33
+
34
+
35
+
36
+
37
+
38
+
39
+
40
+ # Local Variables:
41
+ # mode: text
42
+ # coding: utf-8-unix
43
+ # End:
@@ -1,3 +1,24 @@
1
+ === 0.7.0 / 2010-05-03
2
+
3
+ * Added new methods to report the degree statistics of a node.
4
+
5
+ * Added a convenience method alias 'level' to 'nodeDepth'.
6
+
7
+ * Converted the exceptions thrown on invalid arguments to 'ArgumentError' instead of 'RuntimeError'.
8
+
9
+ * Converted the documentation to Yard format.
10
+
11
+ * Added new methods for converting from/to JSON formats. Thanks to Dirk Breuer[http://github.com/railsbros-dirk] for
12
+ this fork[http://github.com/galaxycats/].
13
+
14
+ * Added a separate API-CHANGES documentation file.
15
+
16
+ * Added fixes for root related edge conditions to 'isOnlyChild?', 'nextSibling', 'previousSibling' and 'remove' methods.
17
+
18
+ * Removed the 'ChangeLog' file as this can now be generated from the git logs.
19
+
20
+ * Other minor code cleanup.
21
+
1
22
  === 0.6.2 / 2010-01-30
2
23
 
3
24
  * Updated the documentation.
@@ -1,8 +1,8 @@
1
1
  COPYING
2
- ChangeLog
3
2
  History.txt
4
3
  Manifest.txt
5
4
  README
5
+ API-CHANGES
6
6
  Rakefile
7
7
  TODO
8
8
  lib/tree.rb
data/README CHANGED
@@ -1,4 +1,4 @@
1
- = rubytree
1
+ = RubyTree
2
2
  __ _ _
3
3
  /__\_ _| |__ _ _| |_ _ __ ___ ___
4
4
  / \// | | | '_ \| | | | __| '__/ _ \/ _ \
@@ -6,8 +6,9 @@
6
6
  \/ \_/\__,_|_.__/ \__, |\__|_| \___|\___|
7
7
  |___/
8
8
 
9
- Copyright (c) 2006, 2007, 2008, 2009, 2010 Anupam Sengupta (anupamsg at gmail dot com)
10
- http://rubytree.rubyforge.org
9
+ Copyright (c) 2006, 2007, 2008, 2009, 2010 Anupam Sengupta (anupamsg at gmail dot com)
10
+
11
+ http://rubytree.rubyforge.org
11
12
 
12
13
  == DESCRIPTION:
13
14
 
@@ -52,7 +53,7 @@ As an example, the following code-snippet implements this tree structure:
52
53
  child1 = root_node["CHILD1"]
53
54
  grand_child1 = root_node["CHILD1"]["GRANDCHILD1"]
54
55
 
55
- # ..... Now lets retrieve siblings of the current node as an array.
56
+ # ..... Lets retrieve siblings of the current node as an array.
56
57
  siblings_of_child1 = child1.siblings
57
58
 
58
59
  # ..... Lets retrieve immediate children of the root node as an array.
@@ -68,10 +69,16 @@ As an example, the following code-snippet implements this tree structure:
68
69
  == REQUIREMENTS:
69
70
 
70
71
  * Ruby 1.8+ (http://www.ruby-lang.org)
71
- * Hoe (http://seattlerb.rubyforge.org/hoe/Hoe.html) Rubygem
72
72
 
73
73
  * Optional but recommended:
74
74
  * structured_warnings (http://github.com/schmidt/structured_warnings) Rubygem
75
+ * Yard (http://yardoc.org) Rubygem for the documentation
76
+ * JSON (http://flori.github.com/json) Rubygem for converting to/from the JSON format
77
+
78
+ * Development dependencies (not required for installing the gem):
79
+ * Hoe (http://seattlerb.rubyforge.org/hoe/Hoe.html) Rubygem
80
+ * gemcutter (http://gemcutter.org/gems/gemcutter) Rubygem
81
+ * Rubyforge (http://codeforpeople.rubyforge.org/rubyforge) Rubygem
75
82
 
76
83
  == INSTALL:
77
84
 
@@ -119,20 +126,63 @@ From a command line/terminal prompt, you can issue the following command to view
119
126
 
120
127
  ri Tree::TreeNode
121
128
 
122
- Documentation on the web is available at:
129
+ Documentation for the latest released version is available at:
123
130
 
124
131
  http://rubytree.rubyforge.org/rdoc
125
132
 
133
+ Documentation for the latest git HEAD is available at:
134
+
135
+ http://rdoc.info/projects/evolve75/RubyTree
136
+
137
+ Note that the documentation is formatted for Yard (http://yardoc.org).
138
+
126
139
  == DEVELOPERS:
127
140
 
141
+ You can download the latest released source code using the tar or zip version as mentioned above in the installation
142
+ section.
143
+
144
+ Alternatively, you can checkout the latest commit/revision from the version control system. Note that RubyTree's
145
+ primary SCM[http://en.wikipedia.org/wiki/Source_Code_Management] is on git[http://git-scm.com] and is
146
+ also mirrored on github[http://www.github.com].
147
+
148
+ === Using the Git repository
149
+
150
+ For checking out from the primary Git repository, use the following command:
151
+
152
+ $ git clone git://rubyforge.org/rubytree.git
153
+
154
+ The Git repository is available for browsing on the web at: http://fisheye2.atlassian.com/browse/rubytree
155
+
156
+ === Using the Git repository on http://github.com
157
+
158
+ For cloning the git repository, use one of the following commands:
159
+
160
+ $ git clone git://github.com/evolve75/RubyTree.git
161
+
162
+ or
163
+ $ git clone http://github.com/evolve75/RubyTree.git
164
+
165
+ The git repository is available on the web at: http://github.com/evolve75/RubyTree
166
+
167
+ === Setting up the development environment
168
+
128
169
  After checking out the source, run:
129
170
 
130
171
  $ rake newb
131
172
 
132
173
  This task will install any missing dependencies, run the tests/specs, and generate the RDoc.
133
174
 
134
- Note that you need to have the Rubygem 'Hoe' (http://seattlerb.rubyforge.org/hoe/Hoe.html) to successfully run the rake
135
- tasks.
175
+ Note that you need to have the Rubygem Hoe[http://seattlerb.rubyforge.org/hoe/Hoe.html] to successfully run the rake
176
+ tasks. Installing Hoe may also install additional pre-requisite gems. See the REQUIREMENTS section in this document for
177
+ details.
178
+
179
+ For generating the documentation, it is strongly suggested that the Yard[http://yardoc.org] gem be installed.
180
+
181
+ == ACKNOWLEDGMENTS:
182
+
183
+ I would like to acknowledge the following contributors for helping improve RubyTree:
184
+
185
+ 1. Dirk Breuer (http://github.com/railsbros-dirk) for contributing the JSON conversion code.
136
186
 
137
187
  == LICENSE:
138
188
 
@@ -163,3 +213,8 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
163
213
 
164
214
 
165
215
  (Document Revision: $Revision$ by $Author$)
216
+
217
+ # Local Variables:
218
+ # mode: text
219
+ # coding: utf-8-unix
220
+ # End:
data/Rakefile CHANGED
@@ -43,16 +43,20 @@ task :default => :gem
43
43
  # Use Hoe to define the rake tasks.
44
44
  begin
45
45
  require 'hoe'
46
+ Hoe.plugin :yard
47
+
46
48
  Hoe.spec PKG_NAME do
47
49
  # The GemSpec settings
48
50
  self.rubyforge_name = PKG_NAME
49
51
  developer "Anupam Sengupta", "anupamsg@gmail.com"
50
- self.extra_rdoc_files = ['README', 'COPYING', 'ChangeLog']
52
+
51
53
  self.url = "http://rubytree.rubyforge.org"
52
54
  self.readme_file = 'README'
53
- # Set the RDoc Options.
54
- self.spec_extras[:rdoc_options] = ['--main', 'README', '--line-numbers']
55
- self.spec_extras[:has_rdoc] = true
55
+
56
+ # Set the Yard Options
57
+ extra_docs = ["COPYING", "API-CHANGES"]
58
+ extra_docs.each { |file| self.yard_files << file }
59
+ self.yard_options = ["--files", extra_docs.join(",") ]
56
60
 
57
61
  # Now the publishing settings
58
62
  self.remote_rdoc_dir = 'rdoc'
@@ -65,13 +69,15 @@ begin
65
69
  self.post_install_message = <<MSGEND
66
70
  ========================================================================
67
71
 
68
- Thank you for installing #{PKG_NAME.capitalize}.
72
+ Thank you for installing #{PKG_NAME}.
69
73
 
70
- Please note that a few APIs have been deprecated since Version 0.6.1
74
+ Please note that a few APIs have been deprecated since Version 0.6.1.
71
75
 
72
76
  Specifically, the 'Tree::TreeNode#depth' method is now deprecated, and
73
77
  a new nodeDepth() method has been introduced.
74
78
 
79
+ Details of the API changes are documented in the API-CHANGES file.
80
+
75
81
  ========================================================================
76
82
  MSGEND
77
83
 
data/TODO CHANGED
@@ -1,24 +1,52 @@
1
1
  # -*- mode: org; coding: utf-8-unix; -*-
2
2
 
3
- * TODO Convert all method names to the canonical /^[_a-z<>=\[|+-\/\*`]+[_a-z0-9_<>=~@\[\]]*[=!\?]?$/ pattern
4
- See Roodi report at http://getcaliper.com/caliper/tool?tool=roodi&repo=git://github.com/evolve75/RubyTree.git
5
- * TODO Fix the TreeNode#root method to return nil for root's root.
6
- * TODO Fix the marshal_load method. This probably needs to be a class method.
7
- * TODO Fix the semantic inconsistency between the TreeNode#first|lastSibling method and the siblings method w.r.t. the root
8
- * TODO Create the basic UML diagrams and upload to the Site
9
- DEADLINE: <2010-01-04 Mon>
10
3
 
11
- * DONE Fix bug # [[http://rubyforge.org/tracker/index.php%3Ffunc%3Ddetail&aid%3D22535&group_id%3D1215&atid%3D4793][22535]]: The method Tree::TreeNode#depth is a misnomer. The current definition actually provides the height function.
12
- DEADLINE: <2010-01-09 Sat> CLOSED: [2010-01-03 Sun 22:15]
13
-
14
- * TODO Add a YAML export method to the TreeNode class.
15
-
16
- * DONE Get the version control moved from CVS to Subversion (request submitted to RubyForge)
17
- CLOSED: [2010-01-02 Sat 17:58]
18
-
19
- * DONE Add logic in Rakefile to read the file list from Manifest.txt file.
4
+ * R0.7.0
5
+ *** TODO Start using signed tags from R0.7.0
6
+ *** DONE Add a check in the Tree::TreeNode.add method to prevent addition of nil child nodes
7
+ CLOSED: [2010-02-23 Tue 23:07]
8
+ *** DONE Fix the edge condition for Tree::TreeNode.isOnlyChild? when the root node is the receiver.
9
+ CLOSED: [2010-02-23 Tue 22:03]
10
+ There really is no good default to this situation. We will return 'true' simply because there is no other sibling
11
+ to a root. However, a good case can be made that a root node does not have any parent either.
12
+ *** DONE Add a convenience 'level' method to the TreeNode class (will be an alias to nodeDepth)
13
+ CLOSED: [2010-02-21 Sun 01:02]
14
+ *** DONE Add a API-CHANGES file to document the various API changes made till date
15
+ CLOSED: [2010-01-31 Sun 00:52]
16
+ *** DONE Add new methods to return the degree counts of the receiver node (in-degree and out-degree)
17
+ CLOSED: [2010-01-30 Sat 23:56]
18
+
19
+ * R0.8.0
20
+ *** TODO Convert all method names to the canonical /^[_a-z<>=\[|+-\/\*`]+[_a-z0-9_<>=~@\[\]]*[=!\?]?$/ pattern
21
+ See Roodi report at http://getcaliper.com/caliper/tool?tool=roodi&repo=git://github.com/evolve75/RubyTree.git
22
+ *** TODO Fix the inconsistency of returning root as its first sibling, and returning a nil instead. Ditto for last sibling.
23
+ *** TODO fix the inconsistency of returning nil for the root, and an empty array for nodes which have no siblings.
24
+ *** TODO We should perhaps return nil as root's root.
25
+ *** TODO The semantic of length is probably unclear. Should return the node_depth instead (or remove the method)
26
+ The current equivalence of length to size should also be removed.
27
+
28
+
29
+ * Unplanned / Not assigned to any release
30
+ *** TODO Fix the TreeNode#root method to return nil for root's root.
31
+ *** TODO Fix the marshal_load method. This probably needs to be a class method.
32
+ *** TODO Fix the semantic inconsistency between the TreeNode#first|lastSibling method and the siblings method w.r.t. the root
33
+ *** TODO Create the basic UML diagrams and upload to the Site
34
+ DEADLINE: <2010-01-04 Mon>
35
+
36
+ *** DONE Fix bug # [[http://rubyforge.org/tracker/index.php%3Ffunc%3Ddetail&aid%3D22535&group_id%3D1215&atid%3D4793][22535]]: The method Tree::TreeNode#depth is a misnomer. The current definition actually provides the height function.
37
+ DEADLINE: <2010-01-09 Sat> CLOSED: [2010-01-03 Sun 22:15]
38
+
39
+ *** TODO Add a YAML export method to the TreeNode class.
40
+
41
+ *** DONE Get the version control moved from CVS to Subversion (request submitted to RubyForge)
42
+ CLOSED: [2010-01-02 Sat 17:58]
43
+
44
+ *** DONE Add logic in Rakefile to read the file list from Manifest.txt file.
20
45
  CLOSED: [2009-12-31 Thu 23:37]
46
+ *** TODO Fix the inconsistency of returning root as its last sibling, and returning a nil array for siblings of the node
47
+ *** TODO marshal_load method probably should be a class method. It currently clobbers self.
48
+ *** TODO Fix the inconsistency of returning root as its first/last sibling, and returning a nil array for siblings of the node
21
49
 
50
+ $Id$
22
51
 
23
52
 
24
- $Id$
@@ -44,39 +44,39 @@
44
44
  # This module provides a TreeNode class which is the primary class for representing
45
45
  # nodes in the tree.
46
46
  #
47
- # This module mixes in the Enumerable module, and also acts as the namespace for all
48
- # classes in RubyTree.
47
+ # This module also acts as the namespace for all classes in the RubyTree package.
49
48
  module Tree
50
49
 
51
50
  # Rubytree Package Version
52
- VERSION = '0.6.2'
51
+ VERSION = '0.7.0'
53
52
 
54
53
  # == TreeNode Class Description
55
54
  #
56
- # This class models the nodes for an N-ary tree data structue. The nodes are +named+
57
- # and have a place-holder for the node data (i.e., `content' of the node). The node
55
+ # This class models the nodes for an *N-ary* tree data structue. The nodes are *named*
56
+ # and have a place-holder for the node data (i.e., _content_ of the node). The node
58
57
  # names are required to be *unique* within the tree.
59
58
  #
60
- # The node content is not required to be unique across different nodes in the tree, and
59
+ # The node's _content_ is *not* required to be unique across different nodes in the tree, and
61
60
  # can be +nil+ as well.
62
61
  #
63
- # The class provides various traversal methods to navigate the tree,
64
- # methods to modify contents of the node or to change position of the node in the tree
65
- # and methods to change structure of the tree.
62
+ # The class provides various methods to navigate the tree, traverse the structure,
63
+ # modify contents of the node, change position of the node in the tree,
64
+ # and to make structural changes to the tree.
66
65
  #
67
- # A node can have any number of child nodes attached to it and hence can be used to create N-ary trees.
66
+ # A node can have any number of *child* nodes attached to it and hence can be used to create N-ary trees.
68
67
  # Access to the child nodes can be made in order (with the conventional left to right access), or
69
68
  # randomly.
70
69
  #
71
- # The node also provides direct access to its parent and other superior parents in the path to
72
- # root of the tree. In addition, a node can also access its sibling nodes, if present.
73
- # Note that while this implementation does not explicitly support directed graphs, the class itself makes
74
- # no restrictions on associating a node's +CONTENT+ with multiple nodes in the tree.
70
+ # The node also provides direct access to its *parent* node as well as other superior parents in the path to
71
+ # root of the tree. In addition, a node can also access its *sibling* nodes, if present.
72
+ #
73
+ # Note that while this implementation does not _explicitly_ support directed graphs, the class itself makes
74
+ # no restrictions on associating a node's *content* with multiple nodes in the tree.
75
75
  #
76
76
  #
77
77
  # == Example
78
78
  #
79
- # The following example implements this tree structure:
79
+ # The following example implements this tree structure:
80
80
  #
81
81
  # +------------+
82
82
  # | ROOT |
@@ -92,30 +92,36 @@ module Tree
92
92
  # | GRANDCHILD 1 |
93
93
  # +---------------+
94
94
  #
95
- # require 'tree'
96
- #
97
- # root_node = Tree::TreeNode.new("ROOT", "Root Content")
98
- #
99
- # root_node << Tree::TreeNode.new("CHILD1", "Child1 Content") << Tree::TreeNode.new("GRANDCHILD1", "GrandChild1 Content")
100
- #
101
- # root_node << Tree::TreeNode.new("CHILD2", "Child2 Content")
95
+ # # ..... Example starts.
96
+ # require 'tree' # Load the library
102
97
  #
103
- # root_node.printTree
98
+ # # ..... Create the root node first. Note that every node has a name and an optional content payload.
99
+ # root_node = Tree::TreeNode.new("ROOT", "Root Content")
104
100
  #
105
- # child1 = root_node["CHILD1"]
101
+ # # ..... Now insert the child nodes. Note that you can "chain" the child insertions for a given path to any depth.
102
+ # root_node << Tree::TreeNode.new("CHILD1", "Child1 Content") << Tree::TreeNode.new("GRANDCHILD1", "GrandChild1 Content")
103
+ # root_node << Tree::TreeNode.new("CHILD2", "Child2 Content")
106
104
  #
107
- # grand_child1 = root_node["CHILD1"]["GRANDCHILD1"]
105
+ # # ..... Lets print the representation to stdout. This is primarily used for debugging purposes.
106
+ # root_node.printTree
108
107
  #
109
- # siblings_of_child1 = child1.siblings
108
+ # # ..... Lets directly access children and grandchildren of the root. The can be "chained" for a given path to any depth.
109
+ # child1 = root_node["CHILD1"]
110
+ # grand_child1 = root_node["CHILD1"]["GRANDCHILD1"]
110
111
  #
111
- # children_of_root = root_node.children
112
+ # # ..... Now lets retrieve siblings of the current node as an array.
113
+ # siblings_of_child1 = child1.siblings
112
114
  #
113
- # # Process all nodes
115
+ # # ..... Lets retrieve immediate children of the root node as an array.
116
+ # children_of_root = root_node.children
114
117
  #
115
- # root_node.each { |node| node.content.reverse }
118
+ # # ..... This is a depth-first and L-to-R pre-ordered traversal.
119
+ # root_node.each { |node| node.content.reverse }
116
120
  #
117
- # root_node.remove!(child1) # Remove the child
121
+ # # ..... Lets remove a child node from the root node.
122
+ # root_node.remove!(child1)
118
123
  #
124
+ # @author Anupam Sengupta
119
125
  class TreeNode
120
126
  include Enumerable
121
127
 
@@ -125,31 +131,40 @@ module Tree
125
131
  # Content of this node. Can be +nil+.
126
132
  attr_accessor :content
127
133
 
128
- # Parent of this node. Will be +nil+ for root nodes.
134
+ # Parent of this node. Will be +nil+ for a root node.
129
135
  attr_reader :parent
130
136
 
131
137
 
132
- # Constructor which expects the name of the node.
133
- # Name of the node is expected to be unique across the tree.
138
+ # Creates a new node with a name and optional content.
139
+ # The node name is expected to be unique within the tree.
134
140
  #
135
- # The content can be of any type, defaults to +nil+.
141
+ # The content can be of any type, and defaults to +nil+.
142
+ #
143
+ # @param [Object] name Name of the node. Usual usage is to pass a String.
144
+ # @param [Object] content Content of the node.
145
+ #
146
+ # @raise [ArgumentError] Raised if the node name is empty.
136
147
  def initialize(name, content = nil)
137
- raise "Node name HAS to be provided" if name == nil
138
- @name = name
139
- @content = content
140
- self.setAsRoot!
148
+ raise ArgumentError, "Node name HAS to be provided!" if name == nil
149
+ @name, @content = name, content
141
150
 
151
+ self.setAsRoot!
142
152
  @childrenHash = Hash.new
143
153
  @children = []
144
154
  end
145
155
 
146
156
  # Returns a copy of the receiver node, with its parent and children links removed.
147
157
  # The original node remains attached to its tree.
158
+ #
159
+ # @return [Tree::TreeNode] A copy of the receiver node.
148
160
  def detached_copy
149
161
  Tree::TreeNode.new(@name, @content ? @content.clone : nil)
150
162
  end
151
163
 
152
- # Print the string representation of this node. This is primary for debugging purposes.
164
+ # Returns string representation of the receiver node.
165
+ # This method is primarily meant for debugging purposes.
166
+ #
167
+ # @return [String] A string representation of the node.
153
168
  def to_s
154
169
  "Node Name: #{@name}" +
155
170
  " Content: " + (@content || "<Empty>") +
@@ -162,6 +177,8 @@ module Tree
162
177
  # (the first element is the immediate parent of the receiver).
163
178
  #
164
179
  # Returns +nil+ if the receiver is a root node.
180
+ #
181
+ # @return [Array, nil] An array of ancestors of the receiver node, or +nil+ if this is a root node.
165
182
  def parentage
166
183
  return nil if isRoot?
167
184
 
@@ -178,19 +195,26 @@ module Tree
178
195
  # Protected method to set the parent node for the receiver node.
179
196
  # This method should *NOT* be invoked by client code.
180
197
  #
181
- # Returns the parent.
198
+ # @param [Tree::TreeNode] parent The parent node.
199
+ #
200
+ # @return [Tree::TreeNode] The parent node.
182
201
  def parent=(parent) # :nodoc:
183
202
  @parent = parent
184
203
  end
185
204
 
186
- # Convenience synonym for TreeNode#add method.
205
+ # Convenience synonym for {Tree::TreeNode#add} method.
187
206
  #
188
- # This method allows an easy method to add node hierarchies to the tree
207
+ # This method allows an easy mechanism to add node hierarchies to the tree
189
208
  # on a given path via chaining the method calls to successive child nodes.
190
209
  #
191
- # Example: <tt>root << child << grand_child</tt>
210
+ # @example Add a child and grand-child to the root
211
+ # root << child << grand_child
192
212
  #
193
- # Returns the added child node.
213
+ # @param [Tree::TreeNode] child the child node to add.
214
+ #
215
+ # @return [Tree::TreeNode] The added child node.
216
+ #
217
+ # @see Tree::TreeNode#add
194
218
  def <<(child)
195
219
  add(child)
196
220
  end
@@ -204,11 +228,18 @@ module Tree
204
228
  # the child is added as the last child ("right most") in the current set of
205
229
  # children of the receiver node.
206
230
  #
207
- # Returns the added child node.
231
+ # @param [Tree::TreeNode] child The child node to add.
232
+ #
233
+ # @return [Tree::TreeNode] The added child node.
208
234
  #
209
- # An exception is raised if another child node with the same name exists.
235
+ # @raise [RuntimeError] This exception is raised if another child node with the same
236
+ # name exists.
237
+ # @raise [ArgumentError] This exception is raised if a +nil+ node is passed as the argument.
238
+ #
239
+ # @see #<<
210
240
  def add(child)
211
- raise "Child already added" if @childrenHash.has_key?(child.name)
241
+ raise ArgumentError, "Attempting to add a nil node" unless child
242
+ raise "Child #{child.name} already added!" if @childrenHash.has_key?(child.name)
212
243
 
213
244
  @childrenHash[child.name] = child
214
245
  @children << child
@@ -218,32 +249,45 @@ module Tree
218
249
 
219
250
  # Removes the specified child node from the receiver node.
220
251
  #
221
- # This method can also be used for *pruning* a subtree, in cases where the removed child node is
222
- # the root of the subtree to be pruned.
252
+ # This method can also be used for *pruning* a sub-tree, in cases where the removed child node is
253
+ # the root of the sub-tree to be pruned.
254
+ #
255
+ # The removed child node is orphaned but accessible if an alternate reference exists. If accessible via
256
+ # an alternate reference, the removed child will report itself as a root node for its sub-tree.
223
257
  #
224
- # The removed child node is orphaned but accessible if an alternate reference exists. If accesible via
225
- # an alternate reference, the removed child will report itself as a root node for its subtree.
258
+ # @param [Tree::TreeNode] child The child node to remove.
226
259
  #
227
- # Returns the child node.
260
+ # @return [Tree::TreeNode] The removed child node, or +nil+ if a +nil+ was passed in as argument.
261
+ #
262
+ # @see #removeFromParent!
263
+ # @see #removeAll!
228
264
  def remove!(child)
265
+ return nil unless child
266
+
229
267
  @childrenHash.delete(child.name)
230
268
  @children.delete(child)
231
- child.setAsRoot! unless child == nil
232
- return child
269
+ child.setAsRoot!
270
+ child
233
271
  end
234
272
 
235
273
  # Removes the receiver node from its parent. The reciever node becomes the new root for its subtree.
236
274
  #
237
275
  # If this is the root node, then does nothing.
238
276
  #
239
- # Returns self (the removed receiver node) if the operation is successful, and +nil+ otherwise.
277
+ # @return [Tree:TreeNode] +self+ (the removed receiver node) if the operation is successful, +nil+ otherwise.
278
+ #
279
+ # @see #removeAll!
240
280
  def removeFromParent!
241
281
  @parent.remove!(self) unless isRoot?
242
282
  end
243
283
 
244
- # Removes all children from the receiver node.
284
+ # Removes all children from the receiver node. If an indepedent reference exists to the child
285
+ # nodes, then these child nodes report themselves as roots after this operation.
245
286
  #
246
- # Returns the receiver node.
287
+ # @return [Tree::TreeNode] The receiver node (+self+)
288
+ #
289
+ # @see #remove!
290
+ # @see #removeFromParent!
247
291
  def removeAll!
248
292
  for child in @children
249
293
  child.setAsRoot!
@@ -253,38 +297,56 @@ module Tree
253
297
  self
254
298
  end
255
299
 
256
- # Returns +true+ if the receiver node has any associated content.
300
+ # Returns +true+ if the receiver node has content.
301
+ #
302
+ # @return [Boolean] +true+ if the node has content.
257
303
  def hasContent?
258
304
  @content != nil
259
305
  end
260
306
 
261
307
  # Protected method which sets the receiver node as a root node.
262
308
  #
263
- # Returns +nil+.
309
+ # @return +nil+.
264
310
  def setAsRoot! # :nodoc:
265
311
  @parent = nil
266
312
  end
267
313
 
268
314
  # Returns +true+ if the receiver is a root node. Note that
269
315
  # orphaned children will also be reported as root nodes.
316
+ #
317
+ # @return [Boolean] +true+ if this is a root node.
270
318
  def isRoot?
271
319
  @parent == nil
272
320
  end
273
321
 
274
- # Returns +true+ if the receiver node has any immediate child nodes.
322
+ # Returns +true+ if the receiver node has any child node.
323
+ #
324
+ # @return [Boolean] +true+ if child nodes exist.
325
+ #
326
+ # @see #isLeaf?
275
327
  def hasChildren?
276
328
  @children.length != 0
277
329
  end
278
330
 
279
331
  # Returns +true+ if the receiver node is a 'leaf' - i.e., one without
280
332
  # any children.
333
+ #
334
+ # @return [Boolean] +true+ if this is a leaf node.
335
+ #
336
+ # @see #hasChildren?
281
337
  def isLeaf?
282
338
  !hasChildren?
283
339
  end
284
340
 
285
- # Returns an array of all the immediate children of the receiver node.
341
+ # Returns an array of all the immediate children of the receiver node. The child nodes are ordered
342
+ # "left-to-right" in the returned array.
286
343
  #
287
344
  # If a block is given, yields each child node to the block traversing from left to right.
345
+ #
346
+ # @yield [child] Each child is passed to the block, if given
347
+ # @yieldparam [Tree::TreeNode] child Each child node.
348
+ #
349
+ # @return [Array<Tree::TreeNode>] An array of the child nodes, if no block is given.
288
350
  def children
289
351
  if block_given?
290
352
  @children.each {|child| yield child}
@@ -296,6 +358,8 @@ module Tree
296
358
  # Returns the first child of the receiver node.
297
359
  #
298
360
  # Will return +nil+ if no children are present.
361
+ #
362
+ # @return [Tree::TreeNode] The first child, or +nil+ if none is present.
299
363
  def firstChild
300
364
  children.first
301
365
  end
@@ -303,28 +367,49 @@ module Tree
303
367
  # Returns the last child of the receiver node.
304
368
  #
305
369
  # Will return +nil+ if no children are present.
370
+ #
371
+ # @return [Tree::TreeNode] The last child, or +nil+ if none is present.
306
372
  def lastChild
307
373
  children.last
308
374
  end
309
375
 
310
- # Traverses every node (including the receiver node) from the (sub)tree
311
- # by yielding the node to the specified block.
376
+ # Traverses each node (including the receiver node) of the (sub)tree rooted at this node
377
+ # by yielding the nodes to the specified block.
378
+ #
379
+ # The traversal is *depth-first* and from *left-to-right* in pre-ordered sequence.
380
+ #
381
+ # @yield [child] Each node is passed to the block.
382
+ # @yieldparam [Tree::TreeNode] child Each node.
312
383
  #
313
- # The traversal is depth-first and from left to right in pre-ordered sequence.
314
- def each &block # :yields: node
384
+ # @see #preordered_each
385
+ # @see #breadth_each
386
+ def each(&block) # :yields: node
315
387
  yield self
316
388
  children { |child| child.each(&block) }
317
389
  end
318
390
 
319
- # Traverses the tree in a pre-ordered sequence. This is equivalent to
320
- # TreeNode#each
321
- def preordered_each &block # :yields: node
391
+ # Traverses the (sub)tree rooted at the receiver node in pre-ordered sequence.
392
+ # This is a synonym of {Tree::TreeNode#each}.
393
+ #
394
+ # @yield [child] Each child is passed to the block.
395
+ # @yieldparam [Tree::TreeNode] node Each node.
396
+ #
397
+ # @see #each
398
+ # @see #breadth_each
399
+ def preordered_each(&block) # :yields: node
322
400
  each(&block)
323
401
  end
324
402
 
325
- # Performs breadth first traversal of the tree starting at the receiver node. The
326
- # traversal at a given level is from left to right.
327
- def breadth_each &block
403
+ # Performs breadth-first traversal of the (sub)tree rooted at the receiver node. The
404
+ # traversal at a given level is from *left-to-right*. The receiver node itself is the first
405
+ # node to be traversed.
406
+ #
407
+ # @yield [child] Each node is passed to the block.
408
+ # @yieldparam [Tree::TreeNode] node Each node.
409
+ #
410
+ # @see #preordered_each
411
+ # @see #breadth_each
412
+ def breadth_each(&block)
328
413
  node_queue = [self] # Create a queue with self as the initial entry
329
414
 
330
415
  # Use a queue to do breadth traversal
@@ -336,23 +421,39 @@ module Tree
336
421
  end
337
422
  end
338
423
 
339
- # Yields all leaf nodes from the receiver node to the specified block.
424
+ # Yields every leaf node of the (sub)tree rooted at the receiver node to the specified block.
340
425
  #
341
426
  # May yield this node as well if this is a leaf node.
342
- # Leaf traversal is depth-first and left to right.
427
+ # Leaf traversal is *depth-first* and *left-to-right*.
428
+ #
429
+ # @yield [node] Each leaf node is passed to the block.
430
+ # @yieldparam [Tree::TreeNode] node Each leaf node.
431
+ #
432
+ # @see #each
433
+ # @see #breadth_each
343
434
  def each_leaf &block
344
435
  self.each { |node| yield(node) if node.isLeaf? }
345
436
  end
346
437
 
347
438
  # Returns the requested node from the set of immediate children.
348
439
  #
349
- # If the argument is _numeric_, then the in-sequence array of children is
350
- # accessed (see Tree#children). If the argument is *NOT* _numeric_, then it
351
- # is assumed to be *name* of the child node to be returned.
440
+ # If the argument is _numeric_, then the in-sequence array of children is accessed using
441
+ # the argument as the *index* (zero-based).
442
+ #
443
+ # If the argument is *NOT* _numeric_, then it is taken to be the *name* of the child node to be returned.
444
+ #
445
+ # An ArgumentError exception is raised if neither name nor an index is provided.
446
+ #
447
+ # @param [String|Number] name_or_index Name of the child, or its positional index in the array of child nodes.
448
+ #
449
+ # @return [Tree::TreeNode] the requested child node. If the index in not in range, or the name is not
450
+ # present, then a +nil+ is returned.
451
+ #
452
+ # @raise [ArgumentError] Raised if neither name nor index is provided.
352
453
  #
353
- # Raises an exception is the requested child node is not found.
454
+ # @see #add
354
455
  def [](name_or_index)
355
- raise "Name_or_index needs to be provided" if name_or_index == nil
456
+ raise ArgumentError, "Name_or_index needs to be provided!" if name_or_index == nil
356
457
 
357
458
  if name_or_index.kind_of?(Integer)
358
459
  @children[name_or_index]
@@ -366,16 +467,28 @@ module Tree
366
467
  # Size of the tree is defined as:
367
468
  #
368
469
  # Size:: Total number nodes in the subtree including the receiver node.
470
+ #
471
+ # @return [Number] Total number of nodes in this (sub)tree.
369
472
  def size
370
473
  @children.inject(1) {|sum, node| sum + node.size}
371
474
  end
372
475
 
373
- # Convenience synonym for Tree#size
476
+ # Convenience synonym for {Tree::TreeNode#size}.
477
+ #
478
+ # @todo The semantic of length is probably unclear. Should return the node depth instead
479
+ # to reflect the path length.
480
+ #
481
+ # @deprecated This method name is ambiguous and may be removed. Use TreeNode#size instead.
482
+ #
483
+ # @return [Number] The total number of nodes in this (sub)tree.
484
+ # @see #size
374
485
  def length
375
486
  size()
376
487
  end
377
488
 
378
- # Pretty prints the tree starting with the receiver node.
489
+ # Pretty prints the (sub)tree rooted at the receiver node.
490
+ #
491
+ # @param [Number] level The indentation level (4 spaces) to start with.
379
492
  def printTree(level = 0)
380
493
 
381
494
  if isRoot?
@@ -396,47 +509,66 @@ module Tree
396
509
  # Returns root node for the (sub)tree to which the receiver node belongs.
397
510
  #
398
511
  # Note that a root node's root is itself (*beware* of any loop construct that may become infinite!)
399
- #--
400
- # TODO: We should perhaps return nil as root's root.
401
- #++
512
+ #
513
+ # @todo We should perhaps return nil as root's root.
514
+ #
515
+ # @return [Tree::TreeNode] Root of the (sub)tree.
402
516
  def root
403
517
  root = self
404
518
  root = root.parent while !root.isRoot?
405
519
  root
406
520
  end
407
521
 
408
- # Returns the first sibling for the receiver node. If this is the root node, returns
522
+ # Returns the first sibling of the receiver node. If this is the root node, then returns
409
523
  # itself.
410
524
  #
411
525
  # 'First' sibling is defined as follows:
412
526
  # First sibling:: The left-most child of the receiver's parent, which may be the receiver itself
413
- #--
414
- # TODO: Fix the inconsistency of returning root as its first sibling, and returning a
415
- # a nil array for siblings for the node.
416
- #++
527
+ #
528
+ # @todo Fix the inconsistency of returning root as its first sibling, and returning
529
+ # a +nil+ array for siblings of the node.
530
+ #
531
+ # @return [Tree::TreeNode] The first sibling node.
532
+ #
533
+ # @see #isFirstSibling?
534
+ # @see #lastSibling
417
535
  def firstSibling
418
536
  isRoot? ? self : parent.children.first
419
537
  end
420
538
 
421
- # Returns true if the receiver node is the first sibling.
539
+ # Returns +true+ if the receiver node is the first sibling at its level.
540
+ #
541
+ # @return [Boolean] +true+ if this is the first sibling.
542
+ #
543
+ # @see #isLastSibling?
544
+ # @see #firstSibling
422
545
  def isFirstSibling?
423
546
  firstSibling == self
424
547
  end
425
548
 
426
- # Returns the last sibling for the receiver node. If this is the root node, returns
549
+ # Returns the last sibling of the receiver node. If this is the root node, then returns
427
550
  # itself.
428
551
  #
429
552
  # 'Last' sibling is defined as follows:
430
553
  # Last sibling:: The right-most child of the receiver's parent, which may be the receiver itself
431
- #--
432
- # TODO: Fix the inconsistency of returning root as its last sibling, and returning a
433
- # a nil array for siblings for the node.
434
- #++
554
+ #
555
+ # @todo Fix the inconsistency of returning root as its last sibling, and returning
556
+ # a +nil+ array for siblings of the node.
557
+ #
558
+ # @return [Tree::TreeNode] The last sibling node.
559
+ #
560
+ # @see #isLastSibling?
561
+ # @see #firstSibling
435
562
  def lastSibling
436
563
  isRoot? ? self : parent.children.last
437
564
  end
438
565
 
439
- # Returns true if the receivere node is the last sibling.
566
+ # Returns +true+ if the receiver node is the last sibling at its level.
567
+ #
568
+ # @return [Boolean] +true+ if this is the last sibling.
569
+ #
570
+ # @see #isFirstSibling?
571
+ # @see #lastSibling
440
572
  def isLastSibling?
441
573
  lastSibling == self
442
574
  end
@@ -445,10 +577,19 @@ module Tree
445
577
  #
446
578
  # If a block is provided, yields each of the sibling nodes to the block.
447
579
  # The root always has +nil+ siblings.
448
- #--
449
- # TODO: Fix the inconsistency of returning root as its first/last sibling, and returning a
450
- # a nil array for siblings for the node.
451
- #++
580
+ #
581
+ # @todo Fix the inconsistency of returning root as its own first/last sibling, and returning
582
+ # a +nil+ array for siblings of the same root node.
583
+ # @todo Also fix the inconsistency of returning +nil+ for a root node, and an empty array for nodes
584
+ # which have no siblings.
585
+ #
586
+ # @yield [sibling] Each sibling is passed to the block.
587
+ # @yieldparam [Tree::TreeNode] sibling Each sibling node.
588
+ #
589
+ # @return [Array<Tree::TreeNode>] Array of siblings of this node.
590
+ #
591
+ # @see #firstSibling
592
+ # @see #lastSibling
452
593
  def siblings
453
594
  return nil if isRoot?
454
595
 
@@ -463,26 +604,44 @@ module Tree
463
604
  end
464
605
  end
465
606
 
466
- # Returns true if the receiver node is the only child of its parent.
607
+ # Returns +true+ if the receiver node is the only child of its parent.
608
+ #
609
+ # As a special case, a root node will always return +true+.
610
+ #
611
+ # @return [Boolean] +true+ if this is the only child of its parent.
612
+ #
613
+ # @see #siblings
467
614
  def isOnlyChild?
468
- parent.children.size == 1
615
+ isRoot? ? true : parent.children.size == 1
469
616
  end
470
617
 
471
618
  # Returns the next sibling for the receiver node.
472
619
  # The 'next' node is defined as the node to right of the receiver node.
473
620
  #
474
- # Will return +nil+ if no subsequent node is present.
621
+ # Will return +nil+ if no subsequent node is present, or if the receiver is a root node.
622
+ #
623
+ # @return [Tree::treeNode] the next sibling node, if present.
624
+ #
625
+ # @see #previousSibling
626
+ # @see #siblings
475
627
  def nextSibling
628
+ return nil if isRoot?
476
629
  if myidx = parent.children.index(self)
477
630
  parent.children.at(myidx + 1)
478
631
  end
479
632
  end
480
633
 
481
- # Returns the previous sibling for the receiver node.
482
- # The 'previous' node is defined as the node to left of the receiver node.
634
+ # Returns the previous sibling of the receiver node.
635
+ # 'Previous' node is defined to be the node to left of the receiver node.
636
+ #
637
+ # Will return +nil+ if no predecessor node is present, or if the receiver is a root node.
638
+ #
639
+ # @return [Tree::treeNode] the previous sibling node, if present.
483
640
  #
484
- # Will return nil if no predecessor node is present.
641
+ # @see #nextSibling
642
+ # @see #siblings
485
643
  def previousSibling
644
+ return nil if isRoot?
486
645
  if myidx = parent.children.index(self)
487
646
  parent.children.at(myidx - 1) if myidx > 0
488
647
  end
@@ -490,13 +649,20 @@ module Tree
490
649
 
491
650
  # Provides a comparision operation for the nodes.
492
651
  #
493
- # Comparision is based on the natural character-set ordering of the *node name*.
652
+ # Comparision is based on the natural character-set ordering of the node name.
653
+ #
654
+ # @param [Tree::TreeNode] other The other node to compare against.
655
+ #
656
+ # @return [Number] +1 if this node is a 'successor', 0 if equal and -1 if this node is a 'predecessor'.
494
657
  def <=>(other)
495
658
  return +1 if other == nil
496
659
  self.name <=> other.name
497
660
  end
498
661
 
499
662
  # Freezes all nodes in the (sub)tree rooted at the receiver node.
663
+ #
664
+ # The nodes become immutable after this operation. In effect, the entire tree's
665
+ # structure and contents become _read-only_ and cannot be changed.
500
666
  def freezeTree!
501
667
  each {|node| node.freeze}
502
668
  end
@@ -514,10 +680,10 @@ module Tree
514
680
  # Loads a marshalled dump of a tree and returns the root node of the
515
681
  # reconstructed tree. See the Marshal class for additional details.
516
682
  #
517
- #--
518
- # TODO: This method probably should be a class method. It currently clobbers self
683
+ #
684
+ # @todo This method probably should be a class method. It currently clobbers self
519
685
  # and makes itself the root.
520
- #++
686
+ #
521
687
  def marshal_load(dumped_tree_array)
522
688
  nodes = { }
523
689
  for node_hash in dumped_tree_array do
@@ -537,12 +703,73 @@ module Tree
537
703
  end
538
704
  end
539
705
 
706
+ # Creates a JSON representation of this node including all it's children. This requires the JSON gem to be
707
+ # available, or else the operation fails with a warning message.
708
+ #
709
+ # @author Dirk Breuer (http://github.com/railsbros-dirk)
710
+ # @since 0.7.0
711
+ #
712
+ # @return The JSON representation of this subtree.
713
+ #
714
+ # @see Tree::TreeNode.json_create
715
+ # @see http://flori.github.com/json
716
+ def to_json(*a)
717
+ begin
718
+ require 'json'
719
+
720
+ json_hash = {
721
+ "name" => name,
722
+ "content" => content,
723
+ JSON.create_id => self.class.name
724
+ }
725
+
726
+ if hasChildren?
727
+ json_hash["children"] = children
728
+ end
729
+
730
+ return json_hash.to_json
731
+
732
+ rescue LoadError => e
733
+ warn "The JSON gem couldn't be loaded. Due to this we cannot serialize the tree to a JSON representation"
734
+ end
735
+ end
736
+
737
+ # Creates a Tree::TreeNode object instance from a given JSON Hash representation. This requires the JSON gem to be
738
+ # available, or else the operation fails with a warning message.
739
+ #
740
+ # @author Dirk Breuer (http://github.com/railsbros-dirk)
741
+ # @since 0.7.0
742
+ #
743
+ # @param [Hash] json_hash The JSON hash to convert from.
744
+ #
745
+ # @return [Tree::TreeNode] The created tree.
746
+ #
747
+ # @see #to_json
748
+ # @see http://flori.github.com/json
749
+ def self.json_create(json_hash)
750
+ begin
751
+ require 'json'
752
+
753
+ node = new(json_hash["name"], json_hash["content"])
754
+
755
+ json_hash["children"].each do |child|
756
+ node << child
757
+ end if json_hash["children"]
758
+
759
+ return node
760
+ rescue LoadError => e
761
+ warn "The JSON gem couldn't be loaded. Due to this we cannot serialize the tree to a JSON representation."
762
+ end
763
+ end
764
+
540
765
  # Returns height of the (sub)tree from the receiver node. Height of a node is defined as:
541
766
  #
542
767
  # Height:: Length of the longest downward path to a leaf from the node.
543
768
  #
544
769
  # - Height from a root node is height of the entire tree.
545
770
  # - The height of a leaf node is zero.
771
+ #
772
+ # @return [Number] Height of the node.
546
773
  def nodeHeight
547
774
  return 0 if isLeaf?
548
775
  1 + @children.collect { |child| child.nodeHeight }.max
@@ -552,13 +779,16 @@ module Tree
552
779
  #
553
780
  # Depth:: Length of the node's path to its root. Depth of a root node is zero.
554
781
  #
555
- # *Note* that the deprecated method Tree::TreeNode#depth was incorrectly computing this value.
556
- # Please replace all calls to the old method with Tree::TreeNode#nodeDepth instead.
782
+ # 'level' is an alias for this method.
783
+ #
784
+ # @return [Number] Depth of this node.
557
785
  def nodeDepth
558
786
  return 0 if isRoot?
559
787
  1 + parent.nodeDepth
560
788
  end
561
789
 
790
+ alias level nodeDepth # Aliased level() method to the nodeDepth().
791
+
562
792
  # Returns depth of the tree from the receiver node. A single leaf node has a depth of 1.
563
793
  #
564
794
  # This method is *DEPRECATED* and may be removed in the subsequent releases.
@@ -566,8 +796,13 @@ module Tree
566
796
  #
567
797
  # _height_ + 1 of the node, *NOT* the _depth_.
568
798
  #
569
- # For correct and conventional behavior, please use Tree::TreeNode#nodeDepth and
570
- # Tree::TreeNode#nodeHeight methods instead.
799
+ # For correct and conventional behavior, please use {Tree::TreeNode#nodeDepth} and
800
+ # {Tree::TreeNode#nodeHeight} methods instead.
801
+ #
802
+ # @return [Number] depth of the node.
803
+ # @deprecated This method returns an incorrect value. Use the 'nodeDepth' method instead.
804
+ #
805
+ # @see #nodeDepth
571
806
  def depth
572
807
  begin
573
808
  require 'structured_warnings' # To enable a nice way of deprecating of the depth method.
@@ -581,15 +816,41 @@ module Tree
581
816
  1 + @children.collect { |child| child.depth }.max
582
817
  end
583
818
 
584
- # Returns breadth of the tree at the receiver node's level.
819
+ # Returns breadth of the tree at the receiver node's level.
585
820
  # A single node without siblings has a breadth of 1.
586
821
  #
587
822
  # Breadth is defined to be:
588
- # Breadth:: Number of sibling nodes to this node + 1 (this node itself), i.e., the number of children the parent of this node has.
823
+ # Breadth:: Number of sibling nodes to this node + 1 (this node itself),
824
+ # i.e., the number of children the parent of this node has.
825
+ #
826
+ # @return [Number] breadth of the node's level.
589
827
  def breadth
590
828
  isRoot? ? 1 : parent.children.size
591
829
  end
592
830
 
831
+ # Returns the incoming edge-count of the receiver node.
832
+ #
833
+ # In-degree is defined as:
834
+ # In-degree:: The number of edges arriving at the node (0 for root, 1 for all other nodes)
835
+ #
836
+ # - In-degree = 0 for a root or orphaned node
837
+ # - In-degree = 1 for a node which has a parent
838
+ #
839
+ # @return [Number] The in-degree of this node.
840
+ def in_degree
841
+ isRoot? ? 0 : 1
842
+ end
843
+
844
+ # Returns the outgoing edge-count of the receiver node.
845
+ #
846
+ # Out-degree is defined as:
847
+ # Out-degree:: The number of edges leaving the node (zero for leafs)
848
+ #
849
+ # @return [Number] The out-degree of this node.
850
+ def out_degree
851
+ isLeaf? ? 0 : children.size
852
+ end
853
+
593
854
  protected :parent=, :setAsRoot!, :createDumpRep
594
855
 
595
856
  end