Class: Jsus::Util::Tree

Inherits:
Object
  • Object
show all
Defined in:
lib/jsus/util/tree.rb

Overview

Jsus::Tree is a basic hierarchical tree structure class What it does, basically, is maintaining hierarchical filesystem-like structure (with node names like /namespace/inner/item) and supporting lookups via #glob method.

Examples:

tree = Jsus::Tree.new
tree["/folder/item_0"] = "Hello"
tree["/folder/item_1"] = "World"
tree["/other/soul"]    = "Empty"
tree.glob("/*")         # => 3 Jsus::Node-s (`root`, `folder`, `other`)
tree.glob("/**/*")      # => 6 Jsus::Node-s (`root`, `folder`, `other`, `item_0`, `item_1`, `soul`)
tree["/something"]      # => nil
tree["/folder/item_1"]  # => Jsus::Node
tree["/other/soul"] = nil
tree.leaves(true)       # => 2 Jsus::Node-s (no `soul` node)
tree.leaves(false)      # => 3 Jsus::Node-s

Defined Under Namespace

Classes: Node

Constant Summary collapse

PATH_SEPARATOR =
"/"

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.components_from_path(path) ⇒ Object Also known as: get_path_components

Splits path into components Jsus::Tree.components_from_path("/hello/world") # => ["hello", "world"]



32
33
34
35
36
# File 'lib/jsus/util/tree.rb', line 32

def components_from_path(path)
  raise "Empty path given: #{path.inspect}" if !path || path == ""
  path = path.to_s.dup
  path.split(PATH_SEPARATOR).reject {|comp| comp == "" }
end

.path_from_components(components) ⇒ Object

Joins components into a pathspec Jsus::Tree.path_from_components(["hello", "world"]) # => "/hello/world"



41
42
43
# File 'lib/jsus/util/tree.rb', line 41

def path_from_components(components)
  "#{PATH_SEPARATOR}#{components.join(PATH_SEPARATOR)}"
end

Instance Method Details

#[](path) ⇒ Jsus::Util::Tree::Node

Note:

returns nil when node has no assigned value

Parameters:

  • path (String)

Returns:

See Also:



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

def [](path)
  node = lookup(path)
  node ? node.value : nil
end

#find_nodes_matching(pathspec) ⇒ Array

Searches for nodes by a given pathspec

Parameters:

  • pathspec (String)

Returns:

  • (Array)

    nodes for given pathspec

See Also:



182
183
184
185
186
# File 'lib/jsus/util/tree.rb', line 182

def find_nodes_matching(pathspec)
  self.class.get_path_components(pathspec).inject([root]) do |nodes, component|
    nodes.map {|node| node.find_children_matching(component) }.flatten
  end
end

#glob(pathspec) ⇒ Array

Returns values for nodes matching given pathspec.

Parameters:

  • pathspec (String)

Returns:

  • (Array)

    values for nodes matching given pathspec

See Also:



192
193
194
# File 'lib/jsus/util/tree.rb', line 192

def glob(pathspec)
  find_nodes_matching(pathspec).map {|node| node.value }
end

#insert(full_path, value = nil) ⇒ Object Also known as: []=

Inserts a node with given value into the tree

Parameters:

  • full (String)

    node path

  • value (Object) (defaults to: nil)


200
201
202
203
204
# File 'lib/jsus/util/tree.rb', line 200

def insert(full_path, value = nil)
  node = create_all_nodes_if_needed(full_path)
  node.value = value
  node
end

#leaves(only_with_value = true) ⇒ Array

Returns list of leaves.

Parameters:

  • whether (Boolean)

    to return only leaves with values

Returns:

  • (Array)

    list of leaves



223
224
225
226
227
# File 'lib/jsus/util/tree.rb', line 223

def leaves(only_with_value = true)
  result = []
  traverse {|node| result << node if !only_with_value || node.value }
  result
end

#lookup(path) ⇒ Jsus::Util::Tree::Node

Looks up a node by direct path. Does not support wildcards

Parameters:

  • path (String)

Returns:



156
157
158
159
160
161
162
163
# File 'lib/jsus/util/tree.rb', line 156

def lookup(path)
  path_components = self.class.get_path_components(path)
  path_components.inject(root) do |result, component|
    if result
      result.find_child(component)
    end
  end
end

#rootJsus::Util::Tree::Node

Returns root node of the tree.

Returns:



148
149
150
# File 'lib/jsus/util/tree.rb', line 148

def root
  @root ||= Node.new("/", nil)
end

#traverse(all_nodes = false) { ... } ⇒ Object

Traverses the tree (BFS).

Parameters:

  • whether (Boolean)

    to traverse non-leaves nodes

Yields:

  • traversed node



211
212
213
214
215
216
217
218
# File 'lib/jsus/util/tree.rb', line 211

def traverse(all_nodes = false)
  node_list = [root]
  while !node_list.empty?
    node = node_list.shift
    yield node if all_nodes || !node.has_children?
    node.children.each {|child| node_list << child }
  end
end