# Copyright: Copyright 2009 Topic Maps Lab, University of Leipzig. # License: Apache License, Version 2.0 module RTM # Register a module as extension to RTM. # # Example: # module MyExtension # module Topic # def my_new_function_for_all_topics # # ... # end # end # RTM.register_extension(self) # end # def self.register_extension(module_with_modules) # puts "[RTMEXT] registering extension #{module_with_modules}" module_with_modules.constants.each do |sub_module| self.const_get(sub_module).register_extension(module_with_modules.const_get(sub_module)) if self.const_defined?(sub_module) end end # Extend a module or class with this method to make it a receiver for RTM extensions. # E.g. MyModule.extend(Extendable) or MyClass.extend(Extendable). # # A extension can then be registered using # MyModule.register_extension(MyExtension) # # The module will then keep track of all modules or classes it's included in. # These modules and classes are called implementations here. # If an extension is added later, the implementations will also be updated which would not be the case if normal includes were used. module Extendable # Register a module as an extension to an Entity in RTM. # An entity may be e.g. RTM::TopicMap, RTM::Topic or any Module which was extended with RTM::Extendable # # Besides normal ruby inclusion of the module, this module keeps track of its implementations which are also updated in this method. def register_extension(mod) include mod return unless @implementations @implementations.each do |impl| next if impl.ancestors.include?(mod) impl.send(:include, mod) end end # A standard Ruby hook to be notified about inclusions of this module. # This normally eliminates the need to register a module as implementa def included(klass) # super # puts "[RTMEXT] including #{self} into #{klass} in #{caller(1).first}" register_implementation(klass) klass.class_eval <<-EOS def self.included(klass2) self.ancestors.find {|anc| anc.respond_to?(:register_implementation)}.register_implementation(klass2) end EOS end # Register an implementation to this module. # Registred implementations will be updated if later any extensions are added. # This method should normally be called from the included hook. # Due to Ruby's restrictions on calling protected methods from other modules extending the very same module Extendable, # this method must be public. def register_implementation(klass) @implementations ||= [] @implementations << klass end end [ TopicMapSystem, Construct, Reifiable, DatatypeAware, Scoped, Typed, TopicMap, Topic, Name, Occurrence, Variant, Association, Role, Locator, ItemIdentifier, SubjectIdentifier, SubjectLocator ].each{|mod| mod.extend(Extendable)} end