rubytree 0.6.2 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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