# frozen-string-literal: true
# Copyright (C) 2020 Thomas Baron
#
# This file is part of term_utils.
#
# term_utils is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, version 3 of the License.
#
# term_utils is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with term_utils. If not, see .
module TermUtils
# Represents a general-purpose tree node that holds a key-value pair.
class PropertyTreeNode
# @return [PropertyTreeNode]
attr_accessor :parent_node
# @return [Array]
attr_accessor :child_nodes
# @return [Object]
attr_accessor :key
# @return [Object]
attr_accessor :value
# Creates a new PropertyTreeNode.
# @param opts [Hash]
# option opts [Object] :key
# option opts [Object] :value
def initialize(opts = {}, &block)
@parent_node = nil
@child_nodes = nil
@key = opts.fetch(:key, nil)
@value = opts.fetch(:value, nil)
block.call(self) if block
end
# For dup method.
def initialize_dup(other)
@parent_node = nil
if other.child_nodes
@child_nodes = []
other.child_nodes.each do |n|
new_node = n.dup
new_node.parent_node = self
@child_nodes << new_node
end
end
super
end
# Tests whether this one is the head of the tree (i.e. has no parent).
# @return [Boolean]
def head?
@parent_node == nil
end
# Tests whether this one is a leaf of the tree (i.e. has no child).
# @return [Boolean]
def leaf?
@child_nodes == nil
end
# Returns the child node identified by a given key.
# @param key [Object]
# @return [PropertyTreeNode, nil]
def child_node(key)
if @child_nodes
@child_nodes.find { |n| n.key == key }
end
end
# Creates a new node and adds it as a child.
# @param opts [Hash]
# @option opts [Object] :key
# @option opts [Object] :value
# @return [PropertyTreeNode]
def define_node(opts = {}, &block)
new_node = TermUtils::PropertyTreeNode.new(opts)
new_node.parent_node = self
@child_nodes = [] unless @child_nodes
@child_nodes << new_node
block.call(new_node) if block
new_node
end
# Builds the path of keys.
# @return [Array