module Pruning module Processing # Contains methods that store the tree and prune everything # except the branches with requested indicator class Pruner def initialize(tree) @tree = tree end def prune_tree(indicator_ids) pruned_tree = @tree prune_subtree(pruned_tree, indicator_ids) pruned_tree end private # Depth First Search implementation # With pruning on the same sweep def prune_subtree(nodes, indicator_ids) nodes_to_examine = nodes.dup nodes_to_examine.each do |node| if indicator_node?(node) indicator_not_wanted = !indicator_ids.include?(node['id']) nodes.delete(node) if indicator_not_wanted else no_wanted_children = prune_subtree(children(node), indicator_ids) nodes.delete(node) if no_wanted_children end end nodes.empty? end def children(node) node.fetch('sub_themes', false) || node.fetch('categories', false) || node.fetch('indicators', false) || [] end def indicator_node?(node) children(node).empty? end end end end