Class: Webgen::Tree

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

Overview

Represents a tree of nodes.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(website) ⇒ Tree

Create a new Tree object for the website.



27
28
29
30
31
# File 'lib/webgen/tree.rb', line 27

def initialize(website)
  @website = website
  @node_access = {:alcn => {}, :acn => {}, :dest_path => {}, :translation_key => {}}
  @dummy_root = Node.new(self, '', '')
end

Instance Attribute Details

#dummy_rootObject (readonly)

The dummy root.

This is the default node that gets created when the Tree is created so that the real root node can be treated like any other node. It has only one child, namely the real root node of the tree.



15
16
17
# File 'lib/webgen/tree.rb', line 15

def dummy_root
  @dummy_root
end

#node_accessObject (readonly)

Direct access to the hashes for node resolving.

Only use this for reading purposes! If you just want to get a specific node for an alcn/acn/destination path, use #node instead.



21
22
23
# File 'lib/webgen/tree.rb', line 21

def node_access
  @node_access
end

#websiteObject (readonly)

The website to which the Tree object belongs.



24
25
26
# File 'lib/webgen/tree.rb', line 24

def website
  @website
end

Instance Method Details

#[](path) ⇒ Object

Access a node via its :alcn.



39
40
41
# File 'lib/webgen/tree.rb', line 39

def [](path)
  @node_access[:alcn][path]
end

#delete_node(node) ⇒ Object

Delete the node and all of its children from the tree.

The message :before_node_deleted is sent with the to-be-deleted node before the node is actually deleted from the tree.



128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/webgen/tree.rb', line 128

def delete_node(node)
  return if node.nil? || !node.kind_of?(Node) || node == @dummy_root

  node.children.dup.each {|child| delete_node(child)}

  @website.blackboard.dispatch_msg(:before_node_deleted, node)
  node.parent.children.delete(node)
  @node_access[:alcn].delete(node.alcn)
  @node_access[:acn][node.acn].delete(node)
  @node_access[:translation_key][translation_key(node)].delete(node)
  @node_access[:dest_path].delete(node.dest_path) unless node.meta_info['no_output']
end

#node(path, type = :alcn) ⇒ Object

Access a node via a path of a specific type.

If type is :alcn (default) then path has to be an absolute localized canonical name, if type is acn then path has to be an absolute canonical name and if type is :dest_path then path needs to be a destination path.

Returns the requested Node or nil if such a node does not exist.



50
51
52
53
54
55
56
57
58
# File 'lib/webgen/tree.rb', line 50

def node(path, type = :alcn)
  case type
  when :alcn then @node_access[type][path]
  when :acn then @node_access[type][path] && @node_access[type][path].first
  when :dest_path then @node_access[type][path]
  else
    raise ArgumentError, "Unknown type '#{type}' for resolving path <#{path}>"
  end
end

#register_node(node) ⇒ Object

Utility method called by Node#initialize. This method should not be used directly!



101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/webgen/tree.rb', line 101

def register_node(node)
  if @node_access[:alcn].has_key?(node.alcn)
    raise "Can't have two nodes with same alcn: #{node}"
  else
    @node_access[:alcn][node.alcn] = node
  end
  (@node_access[:acn][node.acn] ||= []) << node
  (@node_access[:translation_key][translation_key(node)] ||= []) << node
  if node.meta_info['no_output']
    # ignore node dest path
  elsif @node_access[:dest_path].has_key?(node.dest_path)
    raise "Can't have two nodes with same destination path: #{node.dest_path}"
  else
    @node_access[:dest_path][node.dest_path] = node
  end
end

#resolve_node(path, lang, msg_on_failure = false) ⇒ Object

Return the node representing the given path which can be an alcn/acn/destination path (name resolution is done in the specified order). The path has to be absolute, i.e. starting with a slash.

If the path is an alcn and a node is found, it is returned. If the path is an acn, the correct localized node according to lang is returned or if no such node exists but an unlocalized version does, the unlocalized node is returned. If the path is a destination path, the node with this destination path is returned.

If no node is found for the given path or if the path is invalid, nil is returned and, if msg_on_failure is true, the message :node_resolution_failed (with parameters path and lang) is dispatched.



72
73
74
75
76
77
78
79
80
# File 'lib/webgen/tree.rb', line 72

def resolve_node(path, lang, msg_on_failure = false)
  node = self.node(path, :alcn)
  if !node || node.acn == path
    (node = (self.node(path, :acn) || self.node(path + '/', :acn))) && (node = translate_node(node, lang))
  end
  node = self.node(path, :dest_path) if !node
  @website.blackboard.dispatch_msg(:node_resolution_failed, path, lang) if !node && msg_on_failure
  node
end

#rootObject

The real root node of the tree.



34
35
36
# File 'lib/webgen/tree.rb', line 34

def root
  @dummy_root.children.first
end

#translate_node(node, lang) ⇒ Object

Return the translation of the node to the language lang or, if no such node exists, an unlocalized version of the node. If no such node is found either, nil is returned.



84
85
86
87
88
89
90
91
92
93
# File 'lib/webgen/tree.rb', line 84

def translate_node(node, lang)
  avail = @node_access[:translation_key][translation_key(node)]
  avail.find do |n|
    n = n.parent while n.is_fragment?
    n.lang == lang
  end || avail.find do |n|
    n = n.parent while n.is_fragment?
    n.lang.nil?
  end
end

#translations(node) ⇒ Object

Return all translations of the node.



96
97
98
# File 'lib/webgen/tree.rb', line 96

def translations(node)
  @node_access[:translation_key][translation_key(node)].dup
end