rubytree 0.7.0 → 0.8.1

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.
data.tar.gz.sig ADDED
@@ -0,0 +1 @@
1
+ ܥ**�]ڏ�)�5"����qƵtܣ�g��Fl]t�߉���8?��)��������Bl"3mj(˳~�"U<_�M="�J�>�ݚ�K�1�h�Hgaw(�,���)T9�N��ⶎ�ڙ���P-q���U������)��u��T�e��>-��l�H�{�`,���Cn6� ow�x��q�(k'g`��{pɆ^u�4��&xGQ��E�DP*�.`���F?�m��m>+��W�� C���U�f%u��2z\0�
data/API-CHANGES CHANGED
@@ -5,6 +5,15 @@ This file documents various API level changes that have been made to the RubyTre
5
5
  Note: API level changes are expected to reduce dramatically after the 1.x release. In most cases, an alternative will
6
6
  be provided to ensure relatively smooth transition to the new APIs.
7
7
 
8
+ == Release 0.8.0 Changes
9
+
10
+ - Added the ability to specify an optional insertion position in the {Tree::TreeNode#add} method. Idea and original
11
+ code contributed by Dirk.
12
+ - Added a new method {Tree::TreeNode#detached_subtree_copy} to allow cloning the entire tree. This method is also
13
+ aliased to {Tree::TreeNode#dup}. Idea and original code contributed by Vincenzo Farruggia.
14
+ - Converted all CamelCase method names to the canonical ruby_method_names (underscore separated). The CamelCase methods
15
+ can still be invoked, but will throw a Deprecated warning.
16
+
8
17
  == Release 0.7.0 Changes
9
18
 
10
19
  - Converted all exceptions thrown on invalid method arguments to from 'RuntimeError' to 'ArgumentError'. This impacts the
data/History.txt CHANGED
@@ -1,3 +1,40 @@
1
+ === 0.8.1 / 2010-10-02
2
+
3
+ * This is the public release of R0.8.0, with additional bug-fixes.
4
+ Note that R0.8.0 will not be released separately as a publicly
5
+ available Rubygem. All changes as listed for R0.8.0 are available in
6
+ this release.
7
+
8
+ * The main change in R0.8.0/R0.8.1 is conversion of all CamelCase
9
+ method names to snake_case. The old CamelCase method names will
10
+ still work (to ensure backwards compatibility), but will also
11
+ display a warning.
12
+
13
+ * The TreeNode#add method now accepts an optional child insertion
14
+ point.
15
+
16
+ * The subtree from the current node can now be cloned in its entirety
17
+ using the `TreeNode#detached_subtree_copy' method.
18
+
19
+ * A major bug-fix for bug #28613 which impacted the Binarytree
20
+ implementation. See
21
+ http://rubyforge.org/tracker/index.php?func=detail&aid=28613&group_id=1215&atid=4793
22
+ for details.
23
+
24
+ * Minor code re-factoring driven by the code-smell checks using reek.
25
+
26
+ * Inclusion of the `reek' code-smell detection tool in the Rakefile.
27
+
28
+ === 0.8.0 / 2010-05-04
29
+
30
+ * Updated the 'add' method to allow the optional specification of an insertion position in the child array.
31
+
32
+ * Added a new method 'detached_subtree_copy' to allow cloning the entire tree (this method is also aliased as 'dup').
33
+
34
+ * Converted all CamelCase method names to the canonical ruby_method_names (underscore separated). The CamelCase methods
35
+ can still be invoked, but will throw a Deprecated warning. The support for old CamelCase methods will go away some
36
+ time in the future, so the user is advised to convert all current method invocations to the new names.
37
+
1
38
  === 0.7.0 / 2010-05-03
2
39
 
3
40
  * Added new methods to report the degree statistics of a node.
data/README CHANGED
@@ -47,7 +47,7 @@ As an example, the following code-snippet implements this tree structure:
47
47
  root_node << Tree::TreeNode.new("CHILD2", "Child2 Content")
48
48
 
49
49
  # ..... Lets print the representation to stdout. This is primarily used for debugging purposes.
50
- root_node.printTree
50
+ root_node.print_tree
51
51
 
52
52
  # ..... Lets directly access children and grandchildren of the root. The can be "chained" for a given path to any depth.
53
53
  child1 = root_node["CHILD1"]
@@ -183,6 +183,7 @@ For generating the documentation, it is strongly suggested that the Yard[http://
183
183
  I would like to acknowledge the following contributors for helping improve RubyTree:
184
184
 
185
185
  1. Dirk Breuer (http://github.com/railsbros-dirk) for contributing the JSON conversion code.
186
+ 2. Vincenzo Farruggia for contributing the (sub)tree cloning code.
186
187
 
187
188
  == LICENSE:
188
189
 
data/Rakefile CHANGED
@@ -71,10 +71,15 @@ begin
71
71
 
72
72
  Thank you for installing #{PKG_NAME}.
73
73
 
74
- Please note that a few APIs have been deprecated since Version 0.6.1.
74
+ WARNING: SIGNIFICANT API CHANGE in 0.8.0 !
75
+ ------------------------------------------
75
76
 
76
- Specifically, the 'Tree::TreeNode#depth' method is now deprecated, and
77
- a new nodeDepth() method has been introduced.
77
+ Please note that as of 0.8.0 the CamelCase method names are DEPRECATED.
78
+
79
+ The new method names follow the ruby_convention (separated by '_').
80
+
81
+ The old CamelCase methods still work (a warning will be displayed),
82
+ but may go away in the future.
78
83
 
79
84
  Details of the API changes are documented in the API-CHANGES file.
80
85
 
@@ -122,3 +127,21 @@ rescue LoadError
122
127
 
123
128
  END
124
129
  end
130
+
131
+ begin
132
+ require 'reek/rake/task'
133
+ Reek::Rake::Task.new do |t|
134
+ t.verbose = false
135
+ t.source_files = 'lib/**/*.rb'
136
+ end
137
+ rescue LoadError
138
+ $stderr.puts <<-END
139
+ ERROR!!! You need to have reek (http://github.com/kevinrutherford/reek) for detecing the code smell.
140
+
141
+ You can install the reek gem by running the following command as root (or sudo):
142
+
143
+ $ gem install reek
144
+
145
+ END
146
+
147
+ end
data/TODO CHANGED
@@ -1,8 +1,7 @@
1
1
  # -*- mode: org; coding: utf-8-unix; -*-
2
2
 
3
-
4
3
  * R0.7.0
5
- *** TODO Start using signed tags from R0.7.0
4
+ *** DONE Start using signed tags from R0.7.0
6
5
  *** DONE Add a check in the Tree::TreeNode.add method to prevent addition of nil child nodes
7
6
  CLOSED: [2010-02-23 Tue 23:07]
8
7
  *** DONE Fix the edge condition for Tree::TreeNode.isOnlyChild? when the root node is the receiver.
@@ -16,9 +15,19 @@
16
15
  *** DONE Add new methods to return the degree counts of the receiver node (in-degree and out-degree)
17
16
  CLOSED: [2010-01-30 Sat 23:56]
18
17
 
18
+
19
+
19
20
  * R0.8.0
20
- *** TODO Convert all method names to the canonical /^[_a-z<>=\[|+-\/\*`]+[_a-z0-9_<>=~@\[\]]*[=!\?]?$/ pattern
21
+ *** DONE Convert all method names to the canonical /^[_a-z<>=\[|+-\/\*`]+[_a-z0-9_<>=~@\[\]]*[=!\?]?$/ pattern
21
22
  See Roodi report at http://getcaliper.com/caliper/tool?tool=roodi&repo=git://github.com/evolve75/RubyTree.git
23
+ *** DONE Integrate the subtree cloning patch submitted by Vincenzo Farrugia.
24
+
25
+
26
+ * R0.8.1
27
+ *** DONE Fix [[http://rubyforge.org/tracker/index.php?func%3Ddetail&aid%3D28613&group_id%3D1215&atid%3D4793][bug #28613]] which was affecting the `leftChild=' and `rightChild=' methods for binary trees.
28
+
29
+
30
+ * R0.9.0
22
31
  *** TODO Fix the inconsistency of returning root as its first sibling, and returning a nil instead. Ditto for last sibling.
23
32
  *** TODO fix the inconsistency of returning nil for the root, and an empty array for nodes which have no siblings.
24
33
  *** TODO We should perhaps return nil as root's root.
@@ -46,7 +55,3 @@
46
55
  *** TODO Fix the inconsistency of returning root as its last sibling, and returning a nil array for siblings of the node
47
56
  *** TODO marshal_load method probably should be a class method. It currently clobbers self.
48
57
  *** TODO Fix the inconsistency of returning root as its first/last sibling, and returning a nil array for siblings of the node
49
-
50
- $Id$
51
-
52
-
data/lib/tree.rb CHANGED
@@ -48,7 +48,7 @@
48
48
  module Tree
49
49
 
50
50
  # Rubytree Package Version
51
- VERSION = '0.7.0'
51
+ VERSION = '0.8.1'
52
52
 
53
53
  # == TreeNode Class Description
54
54
  #
@@ -97,13 +97,14 @@ module Tree
97
97
  #
98
98
  # # ..... Create the root node first. Note that every node has a name and an optional content payload.
99
99
  # root_node = Tree::TreeNode.new("ROOT", "Root Content")
100
+ # root_node.print_tree
100
101
  #
101
102
  # # ..... Now insert the child nodes. Note that you can "chain" the child insertions for a given path to any depth.
102
103
  # root_node << Tree::TreeNode.new("CHILD1", "Child1 Content") << Tree::TreeNode.new("GRANDCHILD1", "GrandChild1 Content")
103
104
  # root_node << Tree::TreeNode.new("CHILD2", "Child2 Content")
104
105
  #
105
106
  # # ..... Lets print the representation to stdout. This is primarily used for debugging purposes.
106
- # root_node.printTree
107
+ # root_node.print_tree
107
108
  #
108
109
  # # ..... Lets directly access children and grandchildren of the root. The can be "chained" for a given path to any depth.
109
110
  # child1 = root_node["CHILD1"]
@@ -134,7 +135,6 @@ module Tree
134
135
  # Parent of this node. Will be +nil+ for a root node.
135
136
  attr_reader :parent
136
137
 
137
-
138
138
  # Creates a new node with a name and optional content.
139
139
  # The node name is expected to be unique within the tree.
140
140
  #
@@ -148,8 +148,8 @@ module Tree
148
148
  raise ArgumentError, "Node name HAS to be provided!" if name == nil
149
149
  @name, @content = name, content
150
150
 
151
- self.setAsRoot!
152
- @childrenHash = Hash.new
151
+ self.set_as_root!
152
+ @children_hash = Hash.new
153
153
  @children = []
154
154
  end
155
155
 
@@ -161,6 +161,23 @@ module Tree
161
161
  Tree::TreeNode.new(@name, @content ? @content.clone : nil)
162
162
  end
163
163
 
164
+ # Returns a copy of entire (sub-)tree from receiver node.
165
+ #
166
+ # @author Vincenzo Farruggia
167
+ # @since 0.8.0
168
+ #
169
+ # @return [Tree::TreeNode] A copy of (sub-)tree from receiver node.
170
+ def detached_subtree_copy
171
+ new_node = detached_copy
172
+ children { |child| new_node << child.detached_subtree_copy }
173
+ new_node
174
+ end
175
+
176
+ # Alias for {Tree::TreeNode#detached_subtree_copy}
177
+ #
178
+ # @see Tree::TreeNode#detached_subtree_copy
179
+ alias :dup :detached_subtree_copy
180
+
164
181
  # Returns string representation of the receiver node.
165
182
  # This method is primarily meant for debugging purposes.
166
183
  #
@@ -168,7 +185,7 @@ module Tree
168
185
  def to_s
169
186
  "Node Name: #{@name}" +
170
187
  " Content: " + (@content || "<Empty>") +
171
- " Parent: " + (isRoot?() ? "<None>" : @parent.name) +
188
+ " Parent: " + (is_root?() ? "<None>" : @parent.name) +
172
189
  " Children: #{@children.length}" +
173
190
  " Total Nodes: #{size()}"
174
191
  end
@@ -180,16 +197,16 @@ module Tree
180
197
  #
181
198
  # @return [Array, nil] An array of ancestors of the receiver node, or +nil+ if this is a root node.
182
199
  def parentage
183
- return nil if isRoot?
200
+ return nil if is_root?
184
201
 
185
- parentageArray = []
186
- prevParent = self.parent
187
- while (prevParent)
188
- parentageArray << prevParent
189
- prevParent = prevParent.parent
202
+ parentage_array = []
203
+ prev_parent = self.parent
204
+ while (prev_parent)
205
+ parentage_array << prev_parent
206
+ prev_parent = prev_parent.parent
190
207
  end
191
208
 
192
- parentageArray
209
+ parentage_array
193
210
  end
194
211
 
195
212
  # Protected method to set the parent node for the receiver node.
@@ -228,25 +245,44 @@ module Tree
228
245
  # the child is added as the last child ("right most") in the current set of
229
246
  # children of the receiver node.
230
247
  #
248
+ # Additionally you can specify a insert position. The new node will be inserted
249
+ # BEFORE that position. If you don't specify any position the node will be
250
+ # just appended. This feature is provided to make implementation of node
251
+ # movement within the tree very simple.
252
+ #
253
+ # If an insertion position is provided, it needs to be within the valid range of:
254
+ #
255
+ # -children.size..children.size
256
+ #
257
+ # This is to prevent +nil+ nodes being created as children if a non-existant position is used.
258
+ #
231
259
  # @param [Tree::TreeNode] child The child node to add.
260
+ # @param [optional, Number] at_index The optional position where the node is to be inserted.
232
261
  #
233
262
  # @return [Tree::TreeNode] The added child node.
234
263
  #
235
264
  # @raise [RuntimeError] This exception is raised if another child node with the same
236
- # name exists.
265
+ # name exists, or if an invalid insertion position is specified.
237
266
  # @raise [ArgumentError] This exception is raised if a +nil+ node is passed as the argument.
238
267
  #
239
268
  # @see #<<
240
- def add(child)
269
+ def add(child, at_index = -1)
241
270
  raise ArgumentError, "Attempting to add a nil node" unless child
242
- raise "Child #{child.name} already added!" if @childrenHash.has_key?(child.name)
271
+ raise "Child #{child.name} already added!" if @children_hash.has_key?(child.name)
243
272
 
244
- @childrenHash[child.name] = child
245
- @children << child
273
+ if insertion_range.include?(at_index)
274
+ @children.insert(at_index, child)
275
+ else
276
+ raise "Attempting to insert a child at a non-existent location (#{at_index}) when only positions from #{insertion_range.min} to #{insertion_range.max} exist."
277
+ end
278
+
279
+ @children_hash[child.name] = child
246
280
  child.parent = self
247
281
  return child
248
282
  end
249
283
 
284
+
285
+
250
286
  # Removes the specified child node from the receiver node.
251
287
  #
252
288
  # This method can also be used for *pruning* a sub-tree, in cases where the removed child node is
@@ -259,14 +295,14 @@ module Tree
259
295
  #
260
296
  # @return [Tree::TreeNode] The removed child node, or +nil+ if a +nil+ was passed in as argument.
261
297
  #
262
- # @see #removeFromParent!
263
- # @see #removeAll!
298
+ # @see #remove_from_parent!
299
+ # @see #remove_all!
264
300
  def remove!(child)
265
301
  return nil unless child
266
302
 
267
- @childrenHash.delete(child.name)
303
+ @children_hash.delete(child.name)
268
304
  @children.delete(child)
269
- child.setAsRoot!
305
+ child.set_as_root!
270
306
  child
271
307
  end
272
308
 
@@ -276,9 +312,9 @@ module Tree
276
312
  #
277
313
  # @return [Tree:TreeNode] +self+ (the removed receiver node) if the operation is successful, +nil+ otherwise.
278
314
  #
279
- # @see #removeAll!
280
- def removeFromParent!
281
- @parent.remove!(self) unless isRoot?
315
+ # @see #remove_all!
316
+ def remove_from_parent!
317
+ @parent.remove!(self) unless is_root?
282
318
  end
283
319
 
284
320
  # Removes all children from the receiver node. If an indepedent reference exists to the child
@@ -287,12 +323,11 @@ module Tree
287
323
  # @return [Tree::TreeNode] The receiver node (+self+)
288
324
  #
289
325
  # @see #remove!
290
- # @see #removeFromParent!
291
- def removeAll!
292
- for child in @children
293
- child.setAsRoot!
294
- end
295
- @childrenHash.clear
326
+ # @see #remove_from_parent!
327
+ def remove_all!
328
+ @children.each { |child| child.set_as_root! }
329
+
330
+ @children_hash.clear
296
331
  @children.clear
297
332
  self
298
333
  end
@@ -300,14 +335,14 @@ module Tree
300
335
  # Returns +true+ if the receiver node has content.
301
336
  #
302
337
  # @return [Boolean] +true+ if the node has content.
303
- def hasContent?
338
+ def has_content?
304
339
  @content != nil
305
340
  end
306
341
 
307
342
  # Protected method which sets the receiver node as a root node.
308
343
  #
309
344
  # @return +nil+.
310
- def setAsRoot! # :nodoc:
345
+ def set_as_root! # :nodoc:
311
346
  @parent = nil
312
347
  end
313
348
 
@@ -315,7 +350,7 @@ module Tree
315
350
  # orphaned children will also be reported as root nodes.
316
351
  #
317
352
  # @return [Boolean] +true+ if this is a root node.
318
- def isRoot?
353
+ def is_root?
319
354
  @parent == nil
320
355
  end
321
356
 
@@ -323,8 +358,8 @@ module Tree
323
358
  #
324
359
  # @return [Boolean] +true+ if child nodes exist.
325
360
  #
326
- # @see #isLeaf?
327
- def hasChildren?
361
+ # @see #is_leaf?
362
+ def has_children?
328
363
  @children.length != 0
329
364
  end
330
365
 
@@ -333,9 +368,9 @@ module Tree
333
368
  #
334
369
  # @return [Boolean] +true+ if this is a leaf node.
335
370
  #
336
- # @see #hasChildren?
337
- def isLeaf?
338
- !hasChildren?
371
+ # @see #has_children?
372
+ def is_leaf?
373
+ !has_children?
339
374
  end
340
375
 
341
376
  # Returns an array of all the immediate children of the receiver node. The child nodes are ordered
@@ -360,7 +395,7 @@ module Tree
360
395
  # Will return +nil+ if no children are present.
361
396
  #
362
397
  # @return [Tree::TreeNode] The first child, or +nil+ if none is present.
363
- def firstChild
398
+ def first_child
364
399
  children.first
365
400
  end
366
401
 
@@ -369,7 +404,7 @@ module Tree
369
404
  # Will return +nil+ if no children are present.
370
405
  #
371
406
  # @return [Tree::TreeNode] The last child, or +nil+ if none is present.
372
- def lastChild
407
+ def last_child
373
408
  children.last
374
409
  end
375
410
 
@@ -432,7 +467,7 @@ module Tree
432
467
  # @see #each
433
468
  # @see #breadth_each
434
469
  def each_leaf &block
435
- self.each { |node| yield(node) if node.isLeaf? }
470
+ self.each { |node| yield(node) if node.is_leaf? }
436
471
  end
437
472
 
438
473
  # Returns the requested node from the set of immediate children.
@@ -458,7 +493,7 @@ module Tree
458
493
  if name_or_index.kind_of?(Integer)
459
494
  @children[name_or_index]
460
495
  else
461
- @childrenHash[name_or_index]
496
+ @children_hash[name_or_index]
462
497
  end
463
498
  end
464
499
 
@@ -489,21 +524,20 @@ module Tree
489
524
  # Pretty prints the (sub)tree rooted at the receiver node.
490
525
  #
491
526
  # @param [Number] level The indentation level (4 spaces) to start with.
492
- def printTree(level = 0)
493
-
494
- if isRoot?
527
+ def print_tree(level = 0)
528
+ if is_root?
495
529
  print "*"
496
530
  else
497
- print "|" unless parent.isLastSibling?
531
+ print "|" unless parent.is_last_sibling?
498
532
  print(' ' * (level - 1) * 4)
499
- print(isLastSibling? ? "+" : "|")
533
+ print(is_last_sibling? ? "+" : "|")
500
534
  print "---"
501
- print(hasChildren? ? "+" : ">")
535
+ print(has_children? ? "+" : ">")
502
536
  end
503
537
 
504
538
  puts " #{name}"
505
539
 
506
- children { |child| child.printTree(level + 1)}
540
+ children { |child| child.print_tree(level + 1)}
507
541
  end
508
542
 
509
543
  # Returns root node for the (sub)tree to which the receiver node belongs.
@@ -515,7 +549,7 @@ module Tree
515
549
  # @return [Tree::TreeNode] Root of the (sub)tree.
516
550
  def root
517
551
  root = self
518
- root = root.parent while !root.isRoot?
552
+ root = root.parent while !root.is_root?
519
553
  root
520
554
  end
521
555
 
@@ -530,20 +564,20 @@ module Tree
530
564
  #
531
565
  # @return [Tree::TreeNode] The first sibling node.
532
566
  #
533
- # @see #isFirstSibling?
534
- # @see #lastSibling
535
- def firstSibling
536
- isRoot? ? self : parent.children.first
567
+ # @see #is_first_sibling?
568
+ # @see #last_sibling
569
+ def first_sibling
570
+ is_root? ? self : parent.children.first
537
571
  end
538
572
 
539
573
  # Returns +true+ if the receiver node is the first sibling at its level.
540
574
  #
541
575
  # @return [Boolean] +true+ if this is the first sibling.
542
576
  #
543
- # @see #isLastSibling?
544
- # @see #firstSibling
545
- def isFirstSibling?
546
- firstSibling == self
577
+ # @see #is_last_sibling?
578
+ # @see #first_sibling
579
+ def is_first_sibling?
580
+ first_sibling == self
547
581
  end
548
582
 
549
583
  # Returns the last sibling of the receiver node. If this is the root node, then returns
@@ -557,20 +591,20 @@ module Tree
557
591
  #
558
592
  # @return [Tree::TreeNode] The last sibling node.
559
593
  #
560
- # @see #isLastSibling?
561
- # @see #firstSibling
562
- def lastSibling
563
- isRoot? ? self : parent.children.last
594
+ # @see #is_last_sibling?
595
+ # @see #first_sibling
596
+ def last_sibling
597
+ is_root? ? self : parent.children.last
564
598
  end
565
599
 
566
600
  # Returns +true+ if the receiver node is the last sibling at its level.
567
601
  #
568
602
  # @return [Boolean] +true+ if this is the last sibling.
569
603
  #
570
- # @see #isFirstSibling?
571
- # @see #lastSibling
572
- def isLastSibling?
573
- lastSibling == self
604
+ # @see #is_first_sibling?
605
+ # @see #last_sibling
606
+ def is_last_sibling?
607
+ last_sibling == self
574
608
  end
575
609
 
576
610
  # Returns an array of siblings for the receiver node. The receiver node is excluded.
@@ -588,15 +622,13 @@ module Tree
588
622
  #
589
623
  # @return [Array<Tree::TreeNode>] Array of siblings of this node.
590
624
  #
591
- # @see #firstSibling
592
- # @see #lastSibling
625
+ # @see #first_sibling
626
+ # @see #last_sibling
593
627
  def siblings
594
- return nil if isRoot?
628
+ return nil if is_root?
595
629
 
596
630
  if block_given?
597
- for sibling in parent.children
598
- yield sibling if sibling != self
599
- end
631
+ parent.children.each { |sibling| yield sibling if sibling != self }
600
632
  else
601
633
  siblings = []
602
634
  parent.children {|my_sibling| siblings << my_sibling if my_sibling != self}
@@ -611,8 +643,8 @@ module Tree
611
643
  # @return [Boolean] +true+ if this is the only child of its parent.
612
644
  #
613
645
  # @see #siblings
614
- def isOnlyChild?
615
- isRoot? ? true : parent.children.size == 1
646
+ def is_only_child?
647
+ is_root? ? true : parent.children.size == 1
616
648
  end
617
649
 
618
650
  # Returns the next sibling for the receiver node.
@@ -622,13 +654,13 @@ module Tree
622
654
  #
623
655
  # @return [Tree::treeNode] the next sibling node, if present.
624
656
  #
625
- # @see #previousSibling
657
+ # @see #previous_sibling
626
658
  # @see #siblings
627
- def nextSibling
628
- return nil if isRoot?
629
- if myidx = parent.children.index(self)
630
- parent.children.at(myidx + 1)
631
- end
659
+ def next_sibling
660
+ return nil if is_root?
661
+
662
+ myidx = parent.children.index(self)
663
+ parent.children.at(myidx + 1) if myidx
632
664
  end
633
665
 
634
666
  # Returns the previous sibling of the receiver node.
@@ -638,13 +670,13 @@ module Tree
638
670
  #
639
671
  # @return [Tree::treeNode] the previous sibling node, if present.
640
672
  #
641
- # @see #nextSibling
673
+ # @see #next_sibling
642
674
  # @see #siblings
643
- def previousSibling
644
- return nil if isRoot?
645
- if myidx = parent.children.index(self)
646
- parent.children.at(myidx - 1) if myidx > 0
647
- end
675
+ def previous_sibling
676
+ return nil if is_root?
677
+
678
+ myidx = parent.children.index(self)
679
+ parent.children.at(myidx - 1) if myidx && myidx > 0
648
680
  end
649
681
 
650
682
  # Provides a comparision operation for the nodes.
@@ -663,18 +695,18 @@ module Tree
663
695
  #
664
696
  # The nodes become immutable after this operation. In effect, the entire tree's
665
697
  # structure and contents become _read-only_ and cannot be changed.
666
- def freezeTree!
698
+ def freeze_tree!
667
699
  each {|node| node.freeze}
668
700
  end
669
701
 
670
702
  # Returns a marshal-dump represention of the (sub)tree rooted at the receiver node.
671
703
  def marshal_dump
672
- self.collect { |node| node.createDumpRep }
704
+ self.collect { |node| node.create_dump_rep }
673
705
  end
674
706
 
675
707
  # Creates a dump representation of the reciever node and returns the same as a hash.
676
- def createDumpRep # :nodoc:
677
- { :name => @name, :parent => (isRoot? ? nil : @parent.name), :content => Marshal.dump(@content)}
708
+ def create_dump_rep # :nodoc:
709
+ { :name => @name, :parent => (is_root? ? nil : @parent.name), :content => Marshal.dump(@content)}
678
710
  end
679
711
 
680
712
  # Loads a marshalled dump of a tree and returns the root node of the
@@ -686,7 +718,7 @@ module Tree
686
718
  #
687
719
  def marshal_load(dumped_tree_array)
688
720
  nodes = { }
689
- for node_hash in dumped_tree_array do
721
+ dumped_tree_array.each do |node_hash|
690
722
  name = node_hash[:name]
691
723
  parent_name = node_hash[:parent]
692
724
  content = Marshal.load(node_hash[:content])
@@ -723,19 +755,23 @@ module Tree
723
755
  JSON.create_id => self.class.name
724
756
  }
725
757
 
726
- if hasChildren?
758
+ if has_children?
727
759
  json_hash["children"] = children
728
760
  end
729
761
 
730
762
  return json_hash.to_json
731
763
 
732
- rescue LoadError => e
764
+ rescue LoadError
733
765
  warn "The JSON gem couldn't be loaded. Due to this we cannot serialize the tree to a JSON representation"
734
766
  end
735
767
  end
736
768
 
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.
769
+ # Helper method to create a Tree::TreeNode instance from the JSON hash representation. Note that this method should
770
+ # *NOT* be called directly. Instead, to convert the JSON hash back to a tree, do:
771
+ #
772
+ # tree = JSON.parse (the_json_hash)
773
+ #
774
+ # This operation requires the JSON gem to be available, or else the operation fails with a warning message.
739
775
  #
740
776
  # @author Dirk Breuer (http://github.com/railsbros-dirk)
741
777
  # @since 0.7.0
@@ -770,24 +806,27 @@ module Tree
770
806
  # - The height of a leaf node is zero.
771
807
  #
772
808
  # @return [Number] Height of the node.
773
- def nodeHeight
774
- return 0 if isLeaf?
775
- 1 + @children.collect { |child| child.nodeHeight }.max
809
+ def node_height
810
+ return 0 if is_leaf?
811
+ 1 + @children.collect { |child| child.node_height }.max
776
812
  end
777
813
 
778
814
  # Returns depth of the receiver node in its tree. Depth of a node is defined as:
779
815
  #
780
816
  # Depth:: Length of the node's path to its root. Depth of a root node is zero.
781
817
  #
818
+ # *Note* that the deprecated method Tree::TreeNode#depth was incorrectly computing this value.
819
+ # Please replace all calls to the old method with Tree::TreeNode#node_depth instead.
820
+ #
782
821
  # 'level' is an alias for this method.
783
822
  #
784
823
  # @return [Number] Depth of this node.
785
- def nodeDepth
786
- return 0 if isRoot?
787
- 1 + parent.nodeDepth
824
+ def node_depth
825
+ return 0 if is_root?
826
+ 1 + parent.node_depth
788
827
  end
789
828
 
790
- alias level nodeDepth # Aliased level() method to the nodeDepth().
829
+ alias level node_depth # Aliased level() method to the node_depth().
791
830
 
792
831
  # Returns depth of the tree from the receiver node. A single leaf node has a depth of 1.
793
832
  #
@@ -796,26 +835,46 @@ module Tree
796
835
  #
797
836
  # _height_ + 1 of the node, *NOT* the _depth_.
798
837
  #
799
- # For correct and conventional behavior, please use {Tree::TreeNode#nodeDepth} and
800
- # {Tree::TreeNode#nodeHeight} methods instead.
838
+ # For correct and conventional behavior, please use {Tree::TreeNode#node_depth} and
839
+ # {Tree::TreeNode#node_height} methods instead.
801
840
  #
802
841
  # @return [Number] depth of the node.
803
- # @deprecated This method returns an incorrect value. Use the 'nodeDepth' method instead.
842
+ # @deprecated This method returns an incorrect value. Use the 'node_depth' method instead.
804
843
  #
805
- # @see #nodeDepth
844
+ # @see #node_depth
806
845
  def depth
807
846
  begin
808
847
  require 'structured_warnings' # To enable a nice way of deprecating of the depth method.
809
- warn DeprecatedMethodWarning, 'This method is deprecated. Please use nodeDepth() or nodeHeight() instead (bug # 22535)'
848
+ warn DeprecatedMethodWarning, 'This method is deprecated. Please use node_depth() or node_height() instead (bug # 22535)'
810
849
  rescue LoadError
811
850
  # Oh well. Will use the standard Kernel#warn. Behavior will be identical.
812
- warn 'Tree::TreeNode#depth() method is deprecated. Please use nodeDepth() or nodeHeight() instead (bug # 22535)'
851
+ warn 'Tree::TreeNode#depth() method is deprecated. Please use node_depth() or node_height() instead (bug # 22535)'
813
852
  end
814
853
 
815
- return 1 if isLeaf?
854
+ return 1 if is_leaf?
816
855
  1 + @children.collect { |child| child.depth }.max
817
856
  end
818
857
 
858
+ # Allow the deprecated CamelCase method names. Display a warning.
859
+ def method_missing(meth, *args, &blk)
860
+ if self.respond_to?(new_method_name = underscore(meth))
861
+ begin
862
+ require 'structured_warnings' # To enable a nice way of deprecating of the invoked CamelCase method.
863
+ warn DeprecatedMethodWarning, "The camelCased methods are deprecated. Please use #{new_method_name} instead of #{meth}"
864
+
865
+ rescue LoadError
866
+ # Oh well. Will use the standard Kernel#warn. Behavior will be identical.
867
+ warn "Tree::TreeNode##{meth}() method is deprecated. Please use #{new_method_name} instead."
868
+
869
+ ensure # Invoke the method now.
870
+ return send(new_method_name, *args, &blk)
871
+ end
872
+
873
+ else
874
+ super
875
+ end
876
+ end
877
+
819
878
  # Returns breadth of the tree at the receiver node's level.
820
879
  # A single node without siblings has a breadth of 1.
821
880
  #
@@ -825,7 +884,7 @@ module Tree
825
884
  #
826
885
  # @return [Number] breadth of the node's level.
827
886
  def breadth
828
- isRoot? ? 1 : parent.children.size
887
+ is_root? ? 1 : parent.children.size
829
888
  end
830
889
 
831
890
  # Returns the incoming edge-count of the receiver node.
@@ -838,7 +897,7 @@ module Tree
838
897
  #
839
898
  # @return [Number] The in-degree of this node.
840
899
  def in_degree
841
- isRoot? ? 0 : 1
900
+ is_root? ? 0 : 1
842
901
  end
843
902
 
844
903
  # Returns the outgoing edge-count of the receiver node.
@@ -848,10 +907,33 @@ module Tree
848
907
  #
849
908
  # @return [Number] The out-degree of this node.
850
909
  def out_degree
851
- isLeaf? ? 0 : children.size
910
+ is_leaf? ? 0 : children.size
852
911
  end
853
912
 
854
- protected :parent=, :setAsRoot!, :createDumpRep
913
+ protected :parent=, :set_as_root!, :create_dump_rep
914
+
915
+ private
916
+
917
+ # Convert a CamelCasedWord to a underscore separated camel_cased_word.
918
+ #
919
+ # Just copied from ActiveSupport::Inflector because it is only needed
920
+ # aliasing deprecated methods
921
+ def underscore(camel_cased_word)
922
+ word = camel_cased_word.to_s.dup
923
+ word.gsub!(/::/, '/')
924
+ word.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
925
+ word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
926
+ word.tr!("-", "_")
927
+ word.downcase!
928
+ word
929
+ end
930
+
931
+ # Return a range of valid insertion positions. Used in the #add method.
932
+ def insertion_range
933
+ max = @children.size
934
+ min = -(max+1)
935
+ min..max
936
+ end
855
937
 
856
938
  end
857
939
  end