module RTM # Topology information about a Topic Map. # This class provides some statistical and structural information about a topic map. # All methods take an optional modifier OR block which specifies how a Topic Maps construct shall be transformed before it is returned. # Some modifiers are defined in the sub module Modifier. class Topology # @return [RTM::TopicMap] The topic map this topology provides information about. attr_reader :topic_map def initialize(topic_map) @topic_map = topic_map end # A list of constructs defined in TMDM which have a (single) type SINGLE_TYPED_CONSTRUCTS = %w[name occurrence association role] # A list of constructs defined in TMDM which may have multiple types TYPED_CONSTRUCTS = ["topic"] + SINGLE_TYPED_CONSTRUCTS # A list of constructs defined in TMDM which are scopeable SCOPEABLE_CONSTRUCTS = %w[name variant occurrence association] SINGLE_TYPED_CONSTRUCTS.each do |item| # define_method "#{item}_types" do |modifier=nil, &block| eval(<<-EOS) def #{item}_types(modifier=nil, &block) modifier ||= block || Modifier.default @#{item}_types ||= Hash[@topic_map.#{item}_types.map{|i| [modifier.call(i), i.typed_#{item}s.size]}] end def #{item}_types_count(modifier=nil, &block) @#{item}_types_count ||= @topic_map.#{item}_types.size end EOS end SCOPEABLE_CONSTRUCTS.each do |item| eval(<<-EOS) def #{item}_themes(modifier=nil, &block) modifier ||= block || Modifier.default @#{item}_themes ||= Hash[@topic_map.#{item}_themes.map{|i| [modifier.call(i), i.scoped_#{item}s.size]}] end def #{item}_themes_count(modifier=nil, &block) @#{item}_themes_count ||= @topic_map.#{item}_themes.size end EOS end # The number of topics in this topic map # @return [Number] def topics_count(modifier=nil, &block) @topic_map.topics.size end # The number of associations in this topic map # @return [Number] def associations_count(modifier=nil, &block) @topic_map.associations.size end # The following are not available in RTM yet # def names_count # @topic_map.names.size # end # def occurrences_count # @topic_map.occurrences.size # end # def variants_count # @topic_map.variants.size # end # All topology information in one step # @return [Hash] with all topology information. Keys correspond to method names, values to their returned results. def all(modifier=nil, &block) modifier ||= block || Modifier.default puts "modifier: #{modifier.inspect}" ms = self.methods - Object.new.methods - %w[topic_map all] Hash[ms.map {|m| [m, self.send(m, modifier)]}] end # String representation of all topology information # @return [String] with all topology information def to_s(modifier=nil, &block) modifier ||= block || Modifier.best_name all(modifier).sort_by{|k,v| k}.map {|k,v| "#{k}: #{v.inspect}"}.join("\n") end # Manages Modifiers which may be applied to Constructs (or only to Topics?!) module Modifier # The nop Modifier just returns the construct given as is: {|x| x} # # @return [#call] The nop Modifier which is a callable object which takes one argument and returns this argument. def nop Proc.new {|x| x} end # The best_name Modifier returns the best name for a Construct: {|x| x.best_name} # # @return [#call] The best_name Modifier returns a name suitable for human consumption def best_name Proc.new {|x| x.best_name} end # The reference Modifier returns a reference for a Construct: {|x| x.reference} # # @return [#call] The reference Modifier returns a name suitable for human consumption def reference Proc.new {|x| x.reference} end # Make all instance methods available as class methods, too. extend self # The default modifier is {#nop} # @return [#call] the default modifier attr_reader :default # Set the default modifier @default = nop end # The TopologyExtension for RTM::TopicMap adds an #topology method to a topic map which provides an overview over a topic map. module TopologyExtension # Topology information about this TopicMap. # @return [Topology] an object which provides some topology information def topology RTM::Topology.new(self) end RTM::TopicMap.register_extension(self) end end end