rubytree 0.7.0 → 0.8.1

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