module Tree::Utils::TreeMergeHandler

Provides utility methods to merge two {Tree::TreeNode} based trees. @since 0.9.0

Public Instance Methods

merge(other_tree) click to toggle source

Merge two trees that share the same root node and returns a new tree.

The new tree contains the contents of the merge between other_tree and self. Duplicate nodes (coming from other_tree) will NOT be overwritten in self.

@author Darren Oakley (github.com/dazoakley)

@param [Tree::TreeNode] other_tree The other tree to merge with. @return [Tree::TreeNode] the resulting tree following the merge.

@raise [TypeError] This exception is raised if other_tree is not a

{Tree::TreeNode}.

@raise [ArgumentError] This exception is raised if other_tree does not

have the same root node as self.
# File lib/tree/utils/tree_merge_handler.rb, line 63
def merge(other_tree)
  check_merge_prerequisites(other_tree)
  merge_trees(self.root.dup, other_tree.root)
end
merge!(other_tree) click to toggle source

Merge in another tree (that shares the same root node) into this tree. Duplicate nodes (coming from other_tree) will NOT be overwritten in self.

@author Darren Oakley (github.com/dazoakley)

@param [Tree::TreeNode] other_tree The other tree to merge with.

@raise [TypeError] This exception is raised if other_tree is not a

{Tree::TreeNode}.

@raise [ArgumentError] This exception is raised if other_tree does not

have the same root node as self.
# File lib/tree/utils/tree_merge_handler.rb, line 81
def merge!(other_tree)
  check_merge_prerequisites( other_tree )
  merge_trees( self.root, other_tree.root )
end

Private Instance Methods

check_merge_prerequisites(other_tree) click to toggle source

Utility function to check that the conditions for a tree merge are met.

@author Darren Oakley (github.com/dazoakley)

@see merge @see merge!

# File lib/tree/utils/tree_merge_handler.rb, line 94
def check_merge_prerequisites(other_tree)
  unless other_tree.is_a?(Tree::TreeNode)
    raise TypeError,
          'You can only merge in another instance of Tree::TreeNode'
  end

  unless self.root.name == other_tree.root.name
    raise ArgumentError,
          'Unable to merge trees as they do not share the same root'
  end
end
merge_trees(tree1, tree2) click to toggle source

Utility function to recursively merge two subtrees.

@author Darren Oakley (github.com/dazoakley)

@param [Tree::TreeNode] tree1 The target tree to merge into. @param [Tree::TreeNode] tree2 The donor tree (that will be merged

into target).

@raise [Tree::TreeNode] The merged tree.

# File lib/tree/utils/tree_merge_handler.rb, line 114
def merge_trees(tree1, tree2)
  names1 = tree1.has_children? ? tree1.children.map { |child| child.name } : []
  names2 = tree2.has_children? ? tree2.children.map { |child| child.name } : []

  names_to_merge = names2 - names1
  names_to_merge.each do |name|
    tree1 << tree2[name].detached_subtree_copy
  end

  tree1.children.each do |child|
    merge_trees( child, tree2[child.name] ) unless tree2[child.name].nil?
  end

  tree1
end