require File.expand_path(File.join(File.dirname(__FILE__), '..', 'fathom')) # TODO: Move this into a proper configuration module # require 'spira' # @repository = RDF::Repository.new # Spira.add_repository(:default, @repository) class Fathom::Node # See notes in the spec about this. # include Spira::Resource attr_reader :name, :distribution, :description, :values def initialize(opts={}) symbolize_keys!(opts) @name = opts[:name] assert_distribution(opts) @description = opts[:description] @values = opts[:values] assert_links(opts) end def name_sym return nil unless self.name @name_sym ||= self.name.to_s.downcase.gsub(/\s+|-+/, '_').to_sym end def parents @parents ||= [] end def add_parent(parent) self.parents << parent self.add_accessor_for_node(parent) parent.register_child(self) end def register_child(child) raise "Cannot register a child if this node is not a parent already. Use add_parent to the other node or add_child to this node." unless child.parents.include?(self) unless children.include?(child) self.add_accessor_for_node(child) children << child end true end def children @children ||= [] end def add_child(child) self.children << child self.add_accessor_for_node(child) child.register_parent(self) end def register_parent(parent) raise "Cannot register a parent if this node is not a child already. Use add_child to the other node or add_parent to this node." unless parent.children.include?(self) unless parents.include?(parent) self.add_accessor_for_node(parent) parents << parent end true end def simple_inspect self.name ? "#{self.name} (#{self.class.to_s})" : self.class.to_s end def inspect "#{self.class.to_s}: " + [ self.name, self.description, "children:", self.children.map {|e| e.simple_inspect }.inspect, "parents: ", self.parents.map {|e| e.simple_inspect }.inspect, ].compact.join(", ") end protected # Quick and dirty extract from ActiveSupport's same method def symbolize_keys!(h) h.keys.each do |key| h[(key.to_sym rescue key) || key] = h.delete(key) end h end def add_accessor_for_node(node) return false unless node.respond_to?(:name_sym) and node.name_sym return false if self.respond_to?(node.name_sym) (class << self; self; end).module_eval do define_method node.name_sym do node end end end def assert_links(opts) found = opts[:parents] found ||= opts[:parent] found ||= [] found = [found] unless found.is_a?(Array) found.each do |parent| add_parent(parent) end found = opts[:children] found ||= opts[:child] found ||= [] found = [found] unless found.is_a?(Array) found.each do |child| add_child(child) end end def assert_distribution(opts) case opts[:distribution] when Class @distribution = opts[:distribution] when Symbol class_name = opts[:distribution].to_s.downcase.split(/_+/).map {|t| t[0].chr.upcase + t[1..-1]}.join if Fathom::Distributions.constants.include?(class_name) @distribution = "Fathom::Distributions::#{class_name}".constantize end end @distribution ||= Fathom::Distributions::Gaussian end end if __FILE__ == $0 include Fathom # TODO: Is there anything you want to do to run this file on its own? # Node.new end