Parent

Class/Module Index [+]

Quicksearch

Webgen::Node

Represents a file, a directory or a fragment. A node always belongs to a Tree.

All needed meta and processing information is associated with a Node. The meta information is available throught the #[] and meta_info accessors, the processing information through the node_info accessor.

Although node information should be changed by code, it is not advised to change meta information values in code since this may lead to unwanted behaviour!

Attributes

acn[R]

The absolute canonical name of this node.

alcn[R]

The absolute localized canonical name of this node.

children[R]

The child nodes of this node.

cn[R]

The canonical name of this node.

lang[R]

The language of this node.

lcn[R]

The localized canonical name of this node.

level[R]

The level of the node. The level specifies how deep the node is in the hierarchy.

meta_info[R]

Meta information associated with the node.

parent[R]

The parent node. This is in all but one case a Node object. The one exception is that the parent of the Tree#dummy_node is a Tree object.

path[R]

The full output path of this node.

tree[R]

The tree to which this node belongs.

Public Class Methods

new(parent, path, cn, meta_info = {}) click to toggle source

Create a new Node instance.

parent (immutable)

The parent node under which this nodes should be created.

path (immutable)

The full output path for this node. If this node is a directory, the path must have a trailing slash (dir/). If it is a fragment, the hash sign must be the first character of the path (#fragment). This can also be an absolute path like http://myhost.com/.

cn (immutable)

The canonical name for this node. Needs to be of the form basename.ext or basename where basename does not contain any dots. Also, the basename must not include a language part!

meta_info

A hash with meta information for the new node.

The language of a node is taken from the meta information lang and the entry is deleted from the meta information hash. The language cannot be changed afterwards! If no lang key is found, the node is language neutral.

# File lib/webgen/node.rb, line 77
def initialize(parent, path, cn, meta_info = {})
  @parent = parent
  @cn = cn.freeze
  @children = []
  reinit(path, meta_info)
  init_rest
end
url(name, make_absolute = true) click to toggle source

Construct an internal URL for the given name which can be an acn/alcn/path. If the parameter make_absolute is true, then a relative URL will be made absolute by prepending the special URL webgen:://webgen.localhost/.

# File lib/webgen/node.rb, line 227
def self.url(name, make_absolute = true)
  url = URI::parse(URI::escape(name, URL_UNSAFE_PATTERN))
  url = URI::parse('webgen://webgen.localhost/') + url unless url.absolute? || !make_absolute
  url
end

Public Instance Methods

<=>(other) click to toggle source

Sort nodes by using the meta info sort_info (or title if sort_info is not set) of both involved nodes.

# File lib/webgen/node.rb, line 210
def <=>(other)
  self_so = (@meta_info['sort_info'] && @meta_info['sort_info'].to_s) || @meta_info['title'] || ''
  other_so = (other['sort_info'] && other['sort_info'].to_s) || other['title'] || ''
  if self_so !~ /\D/ && other_so !~ /\D/
    self_so = self_so.to_i
    other_so = other_so.to_i
  end
  self_so <=> other_so
end
=~(pattern) click to toggle source

Return true if the alcn matches the pattern. See Webgen::Path.match for more information.

# File lib/webgen/node.rb, line 204
def =~(pattern)
  Webgen::Path.match(@alcn, pattern)
end
[](key) click to toggle source

Return the meta information item for key.

# File lib/webgen/node.rb, line 103
def [](key)
  @meta_info[key]
end
[]=(key, value) click to toggle source

Assign value to the meta information item for key.

# File lib/webgen/node.rb, line 108
def []=(key, value)
  @meta_info[key] = value
end
changed?() click to toggle source

Return true if the node has changed since the last webgen run. If it has changed, dirty is set to true.

Sends the message :node_changed? with self as argument unless the node is already dirty. A listener to this message should set the flag :dirty on the passed node if he thinks it is dirty.

# File lib/webgen/node.rb, line 161
def changed?
  if_not_checked(:node) do
    flag(:dirty) if meta_info_changed? || user_nodes_changed? ||
      node_info[:used_nodes].any? {|n| n != @alcn && (!tree[n] || tree[n].changed?)} ||
      node_info[:used_meta_info_nodes].any? {|n| n != @alcn && (!tree[n] || tree[n].meta_info_changed?)}
    website.blackboard.dispatch_msg(:node_changed?, self) unless flagged?(:dirty)
  end
  flagged?(:dirty)
end
find(opts = {}) click to toggle source
# File lib/webgen/node.rb, line 359
def find(opts = {})
  if opts[:alcn]
    opts[:alcn] = Path.make_absolute(is_directory? ? alcn : parent.alcn.sub(/#.*$/, ''), opts[:alcn].to_s)
  end
  opts[:levels] = 100000 unless opts.has_key?(:levels)

  result = find_nodes(opts, nil, 1)
  result.flatten! if result && (opts[:limit] || opts[:offset])
  result.sort!(opts[:sort]) if result
  result.children = result.children[(opts[:offset].to_s.to_i)..(opts[:limit] ? opts[:offset].to_s.to_i + opts[:limit].to_s.to_i - 1 : -1)]
  result
end
flag(*keys) click to toggle source

Flag the node with the keys and dispatch the message :node_flagged with self and keys as arguments. See flagged for valid keys.

# File lib/webgen/node.rb, line 143
def flag(*keys)
  @flags += keys
  website.blackboard.dispatch_msg(:node_flagged, self, keys)
end
flagged?(key) click to toggle source

Check if the node is flagged with one of the following:

:created

Has the node been created or has it been read from the cache?

:reinit

Does the node need to be reinitialized?

:dirty

Set by other objects to true if they think the object has changed since the last run. Must not be set to false once it is true!

:dirty_meta_info

Set by other objects to true if the meta information of the node has changed since the last run. Must not be set to false once it is true!

# File lib/webgen/node.rb, line 137
def flagged?(key)
  @flags.include?(key)
end
in_lang(lang) click to toggle source

Return the node with the same canonical name but in language lang or, if no such node exists, an unlocalized version of the node. If no such node is found either, nil is returned.

# File lib/webgen/node.rb, line 245
def in_lang(lang)
  avail = @tree.node_access[:acn][@acn]
  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
in_subtree_of?(node) click to toggle source

Check if the this node is in the subtree which is spanned by node. The check is performed using only the parent information of the involved nodes, NOT the actual path/alcn values!

# File lib/webgen/node.rb, line 236
def in_subtree_of?(node)
  temp = self
  temp = temp.parent while temp != tree.dummy_root && temp != node
  temp != tree.dummy_root
end
inspect() click to toggle source

Return an informative representation of the node.

# File lib/webgen/node.rb, line 199
def inspect
  "<##{self.class.name}: alcn=#{@alcn}>"
end
is_directory?() click to toggle source

Check if the node is a directory.

# File lib/webgen/node.rb, line 118
def is_directory?; @path[-1] == // && !is_fragment?; end
is_file?() click to toggle source

Check if the node is a file.

# File lib/webgen/node.rb, line 121
def is_file?; !is_directory? && !is_fragment?; end
is_fragment?() click to toggle source

Check if the node is a fragment.

# File lib/webgen/node.rb, line 124
def is_fragment?; @cn[0] == ## end
is_root?() click to toggle source

Check if the node is the root node.

# File lib/webgen/node.rb, line 127
def is_root?; self == tree.root;  end
meta_info_changed?() click to toggle source

Return true if the meta information of the node has changed.

Sends the message :node_meta_info_changed? with self as argument unless the meta information of the node is already dirty. A listener to this message should set the flag :dirt_meta_info on the passed node if he thinks that the node's meta information is dirty.

# File lib/webgen/node.rb, line 186
def meta_info_changed?
  if_not_checked(:meta_info) do
    website.blackboard.dispatch_msg(:node_meta_info_changed?, self) unless flagged?(:dirty_meta_info)
  end
  flagged?(:dirty_meta_info)
end
node_info() click to toggle source

Return the node information hash which contains information for processing the node.

# File lib/webgen/node.rb, line 113
def node_info
  tree.node_info[@alcn] ||= {}
end
reinit(path, meta_info = {}) click to toggle source

Re-initializes an already initialized node and resets it to its pristine state.

# File lib/webgen/node.rb, line 86
def reinit(path, meta_info = {})
  old_path = @path if defined?(@path)
  @path = path.freeze
  @lang = Webgen::LanguageManager.language_for_code(meta_info.delete('lang'))
  @lang = nil unless is_file?
  @meta_info = meta_info
  @flags = Set.new([:dirty, :created])
  if defined?(@tree)
    @tree.node_access[:path].delete(old_path) if old_path
    @tree.register_path(self)
    self.node_info.clear
    self.node_info[:used_nodes] = Set.new
    self.node_info[:used_meta_info_nodes] = Set.new
  end
end
resolve(path, lang = nil, use_passive_sources = true) click to toggle source

Return the node representing the given path which can be an acn/alcn. The path can be absolute (i.e. starting with a slash) or relative to the current node. If no node exists for the given path or if the path is invalid, nil is returned.

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.

# File lib/webgen/node.rb, line 263
def resolve(path, lang = nil, use_passive_sources = true)
  orig_path = path
  url = self.class.url(@alcn) + self.class.url(path, false)

  path = url.path + (url.fragment.nil? ? '' : '#' + url.fragment)
  return nil if path =~ /^\/\.\./

  node = @tree[path, :alcn]
  if !node || node.acn == path
    (node = (@tree[path, :acn] || @tree[path + '/', :acn])) && (node = node.in_lang(lang))
  end
  if !node && use_passive_sources && !website.config['passive_sources'].empty?
    nodes = website.blackboard.invoke(:create_nodes_from_paths, [path])
    node = resolve(orig_path, lang, false)
    node.node_info[:used_meta_info_nodes] += nodes.collect {|n| n.alcn} if node
  end
  node
end
route_to(other) click to toggle source

Return the relative path to the given path other. The parameter other can be a Node or a String.

# File lib/webgen/node.rb, line 284
def route_to(other)
  my_url = self.class.url(@path)
  other_url = if other.kind_of?(Node)
                self.class.url(other.routing_node(@lang).path)
              elsif other.kind_of?(String)
                my_url + other
              else
                raise ArgumentError, "improper class for argument"
              end

  # resolve any '.' and '..' paths in the target url
  if other_url.path =~ /\/\.\.?\// && other_url.scheme == 'webgen'
    other_url.path = Pathname.new(other_url.path).cleanpath.to_s
  end
  route = my_url.route_to(other_url).to_s
  (route == '' ? File.basename(self.path) : route)
end
routing_node(lang, log_warning = true) click to toggle source

Return the routing node in language lang which is the node that is used when routing to this node. The returned node can differ from the node itself in case of a directory where the routing node is the directory index node. If show_warning is true and this node is a directory node, then a warning is logged if no associated index file is found.

# File lib/webgen/node.rb, line 306
def routing_node(lang, log_warning = true)
  if !is_directory?
    self
  else
    key = [alcn, :index_node, lang]
    vcache = website.cache.volatile
    return vcache[key] if vcache.has_key?(key)

    index_path = self.meta_info['index_path']
    if index_path.nil?
      vcache[key] = self
    else
      index_node = resolve(index_path, lang)
      if index_node
        vcache[key] = index_node
        log(:info) { "Directory index path for <#{alcn}> => <#{index_node}>" }
      elsif log_warning
        vcache[key] = self
        log(:warn) { "No directory index path found for directory <#{alcn}>" }
      end
    end
    vcache[key] || self
  end
end
to_s() click to toggle source

Return the string representation of the node which is just the alcn.

# File lib/webgen/node.rb, line 194
def to_s
  @alcn
end
unflag(*keys) click to toggle source

Remove the flags keys from the node and dispatch the message :node_unflagged with self and keys as arguments.

# File lib/webgen/node.rb, line 150
def unflag(*keys)
  @flags.subtract(keys)
  website.blackboard.dispatch_msg(:node_unflagged, self, keys)
end

Protected Instance Methods

find_nodes(opts, parent, level) click to toggle source
# File lib/webgen/node.rb, line 372
def find_nodes(opts, parent, level)
  result = ProxyNode.new(parent, self)

  children.each do |child|
    c_result = child.find_nodes(opts, result, level + 1)
    result.children << c_result unless c_result.nil?
  end if opts[:levels] && level <= opts[:levels]

  (!result.children.empty? || find_match?(opts) ? result : nil)
end

Private Instance Methods

find_match?(opts) click to toggle source
# File lib/webgen/node.rb, line 384
def find_match?(opts)
  (!opts[:alcn] || self =~ opts[:alcn])
end
if_not_checked(type) click to toggle source

Only run the code in the block if this node has not already been checked. Different checks are supported by setting a different type value.

# File lib/webgen/node.rb, line 412
def if_not_checked(type)
  array = (website.cache.volatile[:node_change_checking] ||= {})[type] ||= []
  if !array.include?(self)
    array << self
    yield
    array.delete(self)
  end
end
init_rest() click to toggle source

Do the rest of the initialization.

# File lib/webgen/node.rb, line 394
def init_rest
  @lcn = Path.lcn(@cn, @lang)
  @acn = (@parent.kind_of?(Tree) ? '' : @parent.acn.sub(/#.*$/, '') + @cn)
  @alcn = (@parent.kind_of?(Tree) ? '' : @parent.alcn.sub(/#.*$/, '') + @lcn)

  @level = -1
  @tree = @parent
  (@level += 1; @tree = @tree.parent) while !@tree.kind_of?(Tree)

  @tree.register_node(self)
  @parent.children << self unless @parent == @tree

  self.node_info[:used_nodes] = Set.new
  self.node_info[:used_meta_info_nodes] = Set.new
end
method_missing(name, *args, &block) click to toggle source

Delegate missing methods to a processor. The current node is placed into the argument array as the first argument before the method name is invoked on the processor.

# File lib/webgen/node.rb, line 423
def method_missing(name, *args, &block)
  if node_info[:processor]
    website.cache.instance(node_info[:processor]).send(name, *([self] + args), &block)
  else
    super
  end
end
user_nodes_changed?() click to toggle source

Return true if any node matching a pattern from the meta information used_nodes has changed.

# File lib/webgen/node.rb, line 172
def user_nodes_changed?
  pattern = [@meta_info['used_nodes']].flatten.compact.collect {|pat| Webgen::Path.make_absolute(parent.alcn, pat)}
  tree.node_access[:alcn].any? do |path, n|
    pattern.any? {|pat| n =~ pat && n.changed?}
  end if pattern.length > 0
end

[Validate]

Generated with the Darkfish Rdoc Generator 2.