Class: Tree::TreeNode

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/tree.rb

Overview

TreeNode Class Description

This class models the nodes for an N-ary tree data structue. The nodes are named and have a place-holder for the node data (i.e., content of the node). The node names are required to be unique within the tree.

The node's content is not required to be unique across different nodes in the tree, and can be nil as well.

The class provides various methods to navigate the tree, traverse the structure, modify contents of the node, change position of the node in the tree, and to make structural changes to the tree.

A node can have any number of child nodes attached to it and hence can be used to create N-ary trees. Access to the child nodes can be made in order (with the conventional left to right access), or randomly.

The node also provides direct access to its parent node as well as other superior parents in the path to root of the tree. In addition, a node can also access its sibling nodes, if present.

Note that while this implementation does not explicitly support directed graphs, the class itself makes no restrictions on associating a node's content with multiple nodes in the tree.

Example

The following example implements this tree structure:

                +------------+
                |    ROOT    |
                +-----+------+
        +-------------+------------+
        |                          |
+-------+-------+          +-------+-------+
|  CHILD 1      |          |  CHILD 2      |
+-------+-------+          +---------------+
        |
        |
+-------+-------+
| GRANDCHILD 1  |
+---------------+

# ..... Example starts.
require 'tree'                 # Load the library

# ..... Create the root node first.  Note that every node has a name and an optional content payload.
root_node = Tree::TreeNode.new("ROOT", "Root Content")
root_node.print_tree

# ..... Now insert the child nodes.  Note that you can "chain" the child insertions for a given path to any depth.
root_node << Tree::TreeNode.new("CHILD1", "Child1 Content") << Tree::TreeNode.new("GRANDCHILD1", "GrandChild1 Content")
root_node << Tree::TreeNode.new("CHILD2", "Child2 Content")

# ..... Lets print the representation to stdout.  This is primarily used for debugging purposes.
root_node.print_tree

# ..... Lets directly access children and grandchildren of the root.  The can be "chained" for a given path to any depth.
child1       = root_node["CHILD1"]
grand_child1 = root_node["CHILD1"]["GRANDCHILD1"]

# ..... Now lets retrieve siblings of the current node as an array.
siblings_of_child1 = child1.siblings

# ..... Lets retrieve immediate children of the root node as an array.
children_of_root = root_node.children

# ..... This is a depth-first and L-to-R pre-ordered traversal.
root_node.each { |node| node.content.reverse }

# ..... Lets remove a child node from the root node.
root_node.remove!(child1)

Author:

Direct Known Subclasses

BinaryTreeNode

Instance Attribute Summary (collapse)

Class Method Summary (collapse)

Instance Method Summary (collapse)

Constructor Details

- (TreeNode) initialize(name, content = nil)

Creates a new node with a name and optional content. The node name is expected to be unique within the tree.

The content can be of any type, and defaults to nil.

Parameters:

  • name (Object)

    Name of the node. Usual usage is to pass a String.

  • content (Object) (defaults to: nil)

    Content of the node.

Raises:

  • (ArgumentError)

    Raised if the node name is empty.



147
148
149
150
151
152
153
154
# File 'lib/tree.rb', line 147

def initialize(name, content = nil)
  raise ArgumentError, "Node name HAS to be provided!" if name == nil
  @name, @content = name, content

  self.set_as_root!
  @children_hash = Hash.new
  @children = []
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

- (Object) method_missing(meth, *args, &blk)

Allow the deprecated CamelCase method names. Display a warning.



859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
# File 'lib/tree.rb', line 859

def method_missing(meth, *args, &blk)
  if self.respond_to?(new_method_name = underscore(meth))
    begin
      require 'structured_warnings'   # To enable a nice way of deprecating of the invoked CamelCase method.
      warn DeprecatedMethodWarning, "The camelCased methods are deprecated. Please use #{new_method_name} instead of #{meth}"

    rescue LoadError
      # Oh well. Will use the standard Kernel#warn.  Behavior will be identical.
      warn "Tree::TreeNode##{meth}() method is deprecated. Please use #{new_method_name} instead."

    ensure                  # Invoke the method now.
      return send(new_method_name, *args, &blk)
    end

  else
    super
  end
end

Instance Attribute Details

- (Object) content

Content of this node. Can be nil.



133
134
135
# File 'lib/tree.rb', line 133

def content
  @content
end

- (Object) name (readonly)

Name of this node. Expected to be unique within the tree.



130
131
132
# File 'lib/tree.rb', line 130

def name
  @name
end

- (Object) parent

Parent of this node. Will be nil for a root node.



136
137
138
# File 'lib/tree.rb', line 136

def parent
  @parent
end

Class Method Details

+ (Tree::TreeNode) json_create(json_hash)

Helper method to create a Tree::TreeNode instance from the JSON hash representation. Note that this method should NOT be called directly. Instead, to convert the JSON hash back to a tree, do:

tree = JSON.parse (the_json_hash)

This operation requires the JSON gem to be available, or else the operation fails with a warning message.

Parameters:

  • json_hash (Hash)

    The JSON hash to convert from.

Returns:

See Also:

Author:

Since:

  • 0.7.0



785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
# File 'lib/tree.rb', line 785

def self.json_create(json_hash)
  begin
    require 'json'

    node = new(json_hash["name"], json_hash["content"])

    json_hash["children"].each do |child|
      node << child
    end if json_hash["children"]

    return node
  rescue LoadError => e
    warn "The JSON gem couldn't be loaded. Due to this we cannot serialize the tree to a JSON representation."
  end
end

Instance Method Details

- (Tree::TreeNode) <<(child)

Convenience synonym for #add method.

This method allows an easy mechanism to add node hierarchies to the tree on a given path via chaining the method calls to successive child nodes.

Examples:

Add a child and grand-child to the root

root << child << grand_child

Parameters:

Returns:

See Also:



235
236
237
# File 'lib/tree.rb', line 235

def <<(child)
  add(child)
end

- (Number) <=>(other)

Provides a comparision operation for the nodes.

Comparision is based on the natural character-set ordering of the node name.

Parameters:

Returns:

  • (Number)

    +1 if this node is a 'successor', 0 if equal and -1 if this node is a 'predecessor'.



689
690
691
692
# File 'lib/tree.rb', line 689

def <=>(other)
  return +1 if other == nil
  self.name <=> other.name
end

- (Tree::TreeNode) [](name_or_index)

Returns the requested node from the set of immediate children.

If the argument is numeric, then the in-sequence array of children is accessed using the argument as the index (zero-based).

If the argument is NOT numeric, then it is taken to be the name of the child node to be returned.

An ArgumentError exception is raised if neither name nor an index is provided.

Parameters:

  • name_or_index (String|Number)

    Name of the child, or its positional index in the array of child nodes.

Returns:

  • (Tree::TreeNode)

    the requested child node. If the index in not in range, or the name is not present, then a nil is returned.

Raises:

  • (ArgumentError)

    Raised if neither name nor index is provided.

See Also:



490
491
492
493
494
495
496
497
498
# File 'lib/tree.rb', line 490

def [](name_or_index)
  raise ArgumentError, "Name_or_index needs to be provided!" if name_or_index == nil

  if name_or_index.kind_of?(Integer)
    @children[name_or_index]
  else
    @children_hash[name_or_index]
  end
end

- (Tree::TreeNode) add(child, at_index = 1)

Adds the specified child node to the receiver node.

This method can also be used for grafting a subtree into the receiver node's tree, if the specified child node is the root of a subtree (i.e., has child nodes under it).

The receiver node becomes parent of the node passed in as the argument, and the child is added as the last child ("right most") in the current set of children of the receiver node.

Additionally you can specify a insert position. The new node will be inserted BEFORE that position. If you don't specify any position the node will be just appended. This feature is provided to make implementation of node movement within the tree very simple.

If an insertion position is provided, it needs to be within the valid range of:

-children.size..children.size

This is to prevent nil nodes being created as children if a non-existant position is used.

name exists, or if an invalid insertion position is specified.

Parameters:

  • child (Tree::TreeNode)

    The child node to add.

  • at_index (optional, Number) (defaults to: 1)

    The optional position where the node is to be inserted.

Returns:

Raises:

  • (RuntimeError)

    This exception is raised if another child node with the same

  • (ArgumentError)

    This exception is raised if a nil node is passed as the argument.

See Also:



269
270
271
272
273
274
275
276
277
278
279
280
281
282
# File 'lib/tree.rb', line 269

def add(child, at_index = -1)
  raise ArgumentError, "Attempting to add a nil node" unless child
  raise "Child #{child.name} already added!" if @children_hash.has_key?(child.name)

  if insertion_range.include?(at_index)
    @children.insert(at_index, child)
  else
    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."
  end

  @children_hash[child.name]  = child
  child.parent = self
  return child
end

- (Number) breadth

Returns breadth of the tree at the receiver node's level. A single node without siblings has a breadth of 1.

Breadth is defined to be:

Breadth

Number of sibling nodes to this node + 1 (this node itself),

i.e., the number of children the parent of this node has.

Returns:

  • (Number)

    breadth of the node's level.



886
887
888
# File 'lib/tree.rb', line 886

def breadth
  is_root? ? 1 : parent.children.size
end

- (Object) breadth_each {|child| ... }

Performs breadth-first traversal of the (sub)tree rooted at the receiver node. The traversal at a given level is from left-to-right. The receiver node itself is the first node to be traversed.

Yields:

  • (child)

    Each node is passed to the block.

Yield Parameters:

See Also:



447
448
449
450
451
452
453
454
455
456
457
# File 'lib/tree.rb', line 447

def breadth_each(&block)
  node_queue = [self]       # Create a queue with self as the initial entry

  # Use a queue to do breadth traversal
  until node_queue.empty?
    node_to_traverse = node_queue.shift
    yield node_to_traverse
    # Enqueue the children from left to right.
    node_to_traverse.children { |child| node_queue.push child }
  end
end

- (Array<Tree::TreeNode>) children {|child| ... }

Returns an array of all the immediate children of the receiver node. The child nodes are ordered "left-to-right" in the returned array.

If a block is given, yields each child node to the block traversing from left to right.

Yields:

  • (child)

    Each child is passed to the block, if given

Yield Parameters:

Returns:

  • (Array<Tree::TreeNode>)

    An array of the child nodes, if no block is given.



385
386
387
388
389
390
391
# File 'lib/tree.rb', line 385

def children
  if block_given?
    @children.each {|child| yield child}
  else
    @children
  end
end

- (Number) depth

Deprecated.

This method returns an incorrect value. Use the 'node_depth' method instead.

Returns depth of the tree from the receiver node. A single leaf node has a depth of 1.

This method is DEPRECATED and may be removed in the subsequent releases. Note that the value returned by this method is actually the:

height + 1 of the node, NOT the depth.

For correct and conventional behavior, please use #node_depth and #node_height methods instead.

Returns:

  • (Number)

    depth of the node.

See Also:



845
846
847
848
849
850
851
852
853
854
855
856
# File 'lib/tree.rb', line 845

def depth
  begin
    require 'structured_warnings'   # To enable a nice way of deprecating of the depth method.
    warn DeprecatedMethodWarning, 'This method is deprecated.  Please use node_depth() or node_height() instead (bug # 22535)'
  rescue LoadError
    # Oh well. Will use the standard Kernel#warn.  Behavior will be identical.
    warn 'Tree::TreeNode#depth() method is deprecated.  Please use node_depth() or node_height() instead (bug # 22535)'
  end

  return 1 if is_leaf?
  1 + @children.collect { |child| child.depth }.max
end

- (Tree::TreeNode) detached_copy

Returns a copy of the receiver node, with its parent and children links removed. The original node remains attached to its tree.

Returns:



160
161
162
# File 'lib/tree.rb', line 160

def detached_copy
  Tree::TreeNode.new(@name, @content ? @content.clone : nil)
end

- (Tree::TreeNode) detached_subtree_copy Also known as: dup

Returns a copy of entire (sub-)tree from receiver node.

Returns:

Author:

  • Vincenzo Farruggia

Since:

  • 0.8.0



170
171
172
173
174
# File 'lib/tree.rb', line 170

def detached_subtree_copy
  new_node = detached_copy
  children { |child| new_node << child.detached_subtree_copy }
  new_node
end

- (Object) each {|child| ... }

Traverses each node (including the receiver node) of the (sub)tree rooted at this node by yielding the nodes to the specified block.

The traversal is depth-first and from left-to-right in pre-ordered sequence.

Yields:

  • (child)

    Each node is passed to the block.

Yield Parameters:

See Also:



421
422
423
424
# File 'lib/tree.rb', line 421

def each(&block)             # :yields: node
  yield self
  children { |child| child.each(&block) }
end

- (Object) each_leaf {|node| ... }

Yields every leaf node of the (sub)tree rooted at the receiver node to the specified block.

May yield this node as well if this is a leaf node. Leaf traversal is depth-first and left-to-right.

Yields:

  • (node)

    Each leaf node is passed to the block.

Yield Parameters:

See Also:



469
470
471
# File 'lib/tree.rb', line 469

def each_leaf &block
  self.each { |node| yield(node) if node.is_leaf? }
end

- (Tree::TreeNode) first_child

Returns the first child of the receiver node.

Will return nil if no children are present.

Returns:



398
399
400
# File 'lib/tree.rb', line 398

def first_child
  children.first
end

- (Tree::TreeNode) first_sibling

TODO:

Fix the inconsistency of returning root as its first sibling, and returning a nil array for siblings of the node.

Returns the first sibling of the receiver node. If this is the root node, then returns itself.

'First' sibling is defined as follows:

First sibling

The left-most child of the receiver's parent, which may be the receiver itself

Returns:

See Also:



569
570
571
# File 'lib/tree.rb', line 569

def first_sibling
  is_root? ? self : parent.children.first
end

- (Object) freeze_tree!

Freezes all nodes in the (sub)tree rooted at the receiver node.

The nodes become immutable after this operation. In effect, the entire tree's structure and contents become read-only and cannot be changed.



698
699
700
# File 'lib/tree.rb', line 698

def freeze_tree!
  each {|node| node.freeze}
end

- (Boolean) has_children?

Returns true if the receiver node has any child node.

Returns:

  • (Boolean)

    true if child nodes exist.

See Also:



362
363
364
# File 'lib/tree.rb', line 362

def has_children?
  @children.length != 0
end

- (Boolean) has_content?

Returns true if the receiver node has content.

Returns:

  • (Boolean)

    true if the node has content.



338
339
340
# File 'lib/tree.rb', line 338

def has_content?
  @content != nil
end

- (Number) in_degree

Returns the incoming edge-count of the receiver node.

In-degree is defined as:

In-degree

The number of edges arriving at the node (0 for root, 1 for all other nodes)

  • In-degree = 0 for a root or orphaned node

  • In-degree = 1 for a node which has a parent

Returns:

  • (Number)

    The in-degree of this node.



899
900
901
# File 'lib/tree.rb', line 899

def in_degree
  is_root? ? 0 : 1
end

- (Boolean) is_first_sibling?

Returns true if the receiver node is the first sibling at its level.

Returns:

  • (Boolean)

    true if this is the first sibling.

See Also:



579
580
581
# File 'lib/tree.rb', line 579

def is_first_sibling?
  first_sibling == self
end

- (Boolean) is_last_sibling?

Returns true if the receiver node is the last sibling at its level.

Returns:

  • (Boolean)

    true if this is the last sibling.

See Also:



606
607
608
# File 'lib/tree.rb', line 606

def is_last_sibling?
  last_sibling == self
end

- (Boolean) is_leaf?

Returns true if the receiver node is a 'leaf' - i.e., one without any children.

Returns:

  • (Boolean)

    true if this is a leaf node.

See Also:



372
373
374
# File 'lib/tree.rb', line 372

def is_leaf?
  !has_children?
end

- (Boolean) is_only_child?

Returns true if the receiver node is the only child of its parent.

As a special case, a root node will always return true.

Returns:

  • (Boolean)

    true if this is the only child of its parent.

See Also:



646
647
648
# File 'lib/tree.rb', line 646

def is_only_child?
  is_root? ? true : parent.children.size == 1
end

- (Boolean) is_root?

Returns true if the receiver is a root node. Note that orphaned children will also be reported as root nodes.

Returns:

  • (Boolean)

    true if this is a root node.



353
354
355
# File 'lib/tree.rb', line 353

def is_root?
  @parent == nil
end

- (Tree::TreeNode) last_child

Returns the last child of the receiver node.

Will return nil if no children are present.

Returns:



407
408
409
# File 'lib/tree.rb', line 407

def last_child
  children.last
end

- (Tree::TreeNode) last_sibling

TODO:

Fix the inconsistency of returning root as its last sibling, and returning a nil array for siblings of the node.

Returns the last sibling of the receiver node. If this is the root node, then returns itself.

'Last' sibling is defined as follows:

Last sibling

The right-most child of the receiver's parent, which may be the receiver itself

Returns:

See Also:



596
597
598
# File 'lib/tree.rb', line 596

def last_sibling
  is_root? ? self : parent.children.last
end

- (Number) length

Deprecated.

This method name is ambiguous and may be removed. Use TreeNode#size instead.

TODO:

The semantic of length is probably unclear. Should return the node depth instead to reflect the path length.

Convenience synonym for #size.

Returns:

  • (Number)

    The total number of nodes in this (sub)tree.

See Also:



520
521
522
# File 'lib/tree.rb', line 520

def length
  size()
end

- (Object) marshal_dump

Returns a marshal-dump represention of the (sub)tree rooted at the receiver node.



703
704
705
# File 'lib/tree.rb', line 703

def marshal_dump
  self.collect { |node| node.create_dump_rep }
end

- (Object) marshal_load(dumped_tree_array)

TODO:

This method probably should be a class method. It currently clobbers self and makes itself the root.

Loads a marshalled dump of a tree and returns the root node of the reconstructed tree. See the Marshal class for additional details.



719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
# File 'lib/tree.rb', line 719

def marshal_load(dumped_tree_array)
  nodes = { }
  dumped_tree_array.each do |node_hash|
    name        = node_hash[:name]
    parent_name = node_hash[:parent]
    content     = Marshal.load(node_hash[:content])

    if parent_name then
      nodes[name] = current_node = Tree::TreeNode.new(name, content)
      nodes[parent_name].add current_node
    else
      # This is the root node, hence initialize self.
      initialize(name, content)

      nodes[name] = self    # Add self to the list of nodes
    end
  end
end

- (Tree::treeNode) next_sibling

Returns the next sibling for the receiver node. The 'next' node is defined as the node to right of the receiver node.

Will return nil if no subsequent node is present, or if the receiver is a root node.

Returns:

  • (Tree::treeNode)

    the next sibling node, if present.

See Also:



659
660
661
662
663
664
# File 'lib/tree.rb', line 659

def next_sibling
  return nil if is_root?

  myidx = parent.children.index(self)
  parent.children.at(myidx + 1) if myidx
end

- (Number) node_depth Also known as: level

Returns depth of the receiver node in its tree. Depth of a node is defined as:

Depth

Length of the node's path to its root. Depth of a root node is zero.

Note that the deprecated method Tree::TreeNode#depth was incorrectly computing this value. Please replace all calls to the old method with Tree::TreeNode#node_depth instead.

'level' is an alias for this method.

Returns:

  • (Number)

    Depth of this node.



824
825
826
827
# File 'lib/tree.rb', line 824

def node_depth
  return 0 if is_root?
  1 + parent.node_depth
end

- (Number) node_height

Returns height of the (sub)tree from the receiver node. Height of a node is defined as:

Height

Length of the longest downward path to a leaf from the node.

  • Height from a root node is height of the entire tree.

  • The height of a leaf node is zero.

Returns:

  • (Number)

    Height of the node.



809
810
811
812
# File 'lib/tree.rb', line 809

def node_height
  return 0 if is_leaf?
  1 + @children.collect { |child| child.node_height }.max
end

- (Number) out_degree

Returns the outgoing edge-count of the receiver node.

Out-degree is defined as:

Out-degree

The number of edges leaving the node (zero for leafs)

Returns:

  • (Number)

    The out-degree of this node.



909
910
911
# File 'lib/tree.rb', line 909

def out_degree
  is_leaf? ? 0 : children.size
end

- (Array?) parentage

Returns an array of ancestors of the receiver node in reversed order (the first element is the immediate parent of the receiver).

Returns nil if the receiver is a root node.

Returns:

  • (Array, nil)

    An array of ancestors of the receiver node, or nil if this is a root node.



199
200
201
202
203
204
205
206
207
208
209
210
# File 'lib/tree.rb', line 199

def parentage
  return nil if is_root?

  parentage_array = []
  prev_parent = self.parent
  while (prev_parent)
    parentage_array << prev_parent
    prev_parent = prev_parent.parent
  end

  parentage_array
end

- (Object) preordered_each {|child| ... }

Traverses the (sub)tree rooted at the receiver node in pre-ordered sequence. This is a synonym of #each.

Yields:

  • (child)

    Each child is passed to the block.

Yield Parameters:

See Also:



434
435
436
# File 'lib/tree.rb', line 434

def preordered_each(&block)  # :yields: node
  each(&block)
end

- (Tree::treeNode) previous_sibling

Returns the previous sibling of the receiver node. 'Previous' node is defined to be the node to left of the receiver node.

Will return nil if no predecessor node is present, or if the receiver is a root node.

Returns:

  • (Tree::treeNode)

    the previous sibling node, if present.

See Also:



675
676
677
678
679
680
# File 'lib/tree.rb', line 675

def previous_sibling
  return nil if is_root?

  myidx = parent.children.index(self)
  parent.children.at(myidx - 1) if myidx && myidx > 0
end

Pretty prints the (sub)tree rooted at the receiver node.

Parameters:

  • level (Number) (defaults to: 0)

    The indentation level (4 spaces) to start with.



527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
# File 'lib/tree.rb', line 527

def print_tree(level = 0)
  if is_root?
    print "*"
  else
    print "|" unless parent.is_last_sibling?
    print(' ' * (level - 1) * 4)
    print(is_last_sibling? ? "+" : "|")
    print "---"
    print(has_children? ? "+" : ">")
  end

  puts " #{name}"

  children { |child| child.print_tree(level + 1)}
end

- (Tree::TreeNode) remove!(child)

Removes the specified child node from the receiver node.

This method can also be used for pruning a sub-tree, in cases where the removed child node is the root of the sub-tree to be pruned.

The removed child node is orphaned but accessible if an alternate reference exists. If accessible via an alternate reference, the removed child will report itself as a root node for its sub-tree.

Parameters:

Returns:

  • (Tree::TreeNode)

    The removed child node, or nil if a nil was passed in as argument.

See Also:



300
301
302
303
304
305
306
307
# File 'lib/tree.rb', line 300

def remove!(child)
  return nil unless child

  @children_hash.delete(child.name)
  @children.delete(child)
  child.set_as_root!
  child
end

- (Tree::TreeNode) remove_all!

Removes all children from the receiver node. If an indepedent reference exists to the child nodes, then these child nodes report themselves as roots after this operation.

Returns:

See Also:



327
328
329
330
331
332
333
# File 'lib/tree.rb', line 327

def remove_all!
  @children.each { |child| child.set_as_root! }

  @children_hash.clear
  @children.clear
  self
end

- (Tree:TreeNode) remove_from_parent!

Removes the receiver node from its parent. The reciever node becomes the new root for its subtree.

If this is the root node, then does nothing.

Returns:

  • (Tree:TreeNode)

    self (the removed receiver node) if the operation is successful, nil otherwise.

See Also:



316
317
318
# File 'lib/tree.rb', line 316

def remove_from_parent!
  @parent.remove!(self) unless is_root?
end

- (Tree::TreeNode) root

TODO:

We should perhaps return nil as root's root.

Returns root node for the (sub)tree to which the receiver node belongs.

Note that a root node's root is itself (beware of any loop construct that may become infinite!)

Returns:



550
551
552
553
554
# File 'lib/tree.rb', line 550

def root
  root = self
  root = root.parent while !root.is_root?
  root
end

- (Array<Tree::TreeNode>) siblings {|sibling| ... }

TODO:

Fix the inconsistency of returning root as its own first/last sibling, and returning a nil array for siblings of the same root node.

TODO:

Also fix the inconsistency of returning nil for a root node, and an empty array for nodes which have no siblings.

Returns an array of siblings for the receiver node. The receiver node is excluded.

If a block is provided, yields each of the sibling nodes to the block. The root always has nil siblings.

Yields:

  • (sibling)

    Each sibling is passed to the block.

Yield Parameters:

Returns:

See Also:



627
628
629
630
631
632
633
634
635
636
637
# File 'lib/tree.rb', line 627

def siblings
  return nil if is_root?

  if block_given?
    parent.children.each { |sibling| yield sibling if sibling != self }
  else
    siblings = []
    parent.children {|my_sibling| siblings << my_sibling if my_sibling != self}
    siblings
  end
end

- (Number) size

Returns the total number of nodes in this (sub)tree, including the receiver node.

Size of the tree is defined as:

Size

Total number nodes in the subtree including the receiver node.

Returns:

  • (Number)

    Total number of nodes in this (sub)tree.



507
508
509
# File 'lib/tree.rb', line 507

def size
  @children.inject(1) {|sum, node| sum + node.size}
end

- (Object) to_json(*a)

Creates a JSON representation of this node including all it's children. This requires the JSON gem to be available, or else the operation fails with a warning message.

Returns:

  • The JSON representation of this subtree.

See Also:

Author:

Since:

  • 0.7.0



748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
# File 'lib/tree.rb', line 748

def to_json(*a)
  begin
    require 'json'

    json_hash = {
      "name"         => name,
      "content"      => content,
      JSON.create_id => self.class.name
    }

    if has_children?
      json_hash["children"] = children
    end

    return json_hash.to_json

  rescue LoadError
    warn "The JSON gem couldn't be loaded. Due to this we cannot serialize the tree to a JSON representation"
  end
end

- (String) to_s

Returns string representation of the receiver node. This method is primarily meant for debugging purposes.

Returns:

  • (String)

    A string representation of the node.



185
186
187
188
189
190
191
# File 'lib/tree.rb', line 185

def to_s
  "Node Name: #{@name}" +
    " Content: " + (@content || "<Empty>") +
    " Parent: " + (is_root?()  ? "<None>" : @parent.name) +
    " Children: #{@children.length}" +
    " Total Nodes: #{size()}"
end