rtm 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. data/README +38 -3
  2. data/lib/rtm.rb +25 -47
  3. data/lib/rtm/axes.rb +7 -4
  4. data/lib/rtm/axes/association.rb +1 -1
  5. data/lib/rtm/axes/associations.rb +1 -1
  6. data/lib/rtm/axes/characteristic.rb +1 -1
  7. data/lib/rtm/axes/characteristics.rb +1 -1
  8. data/lib/rtm/axes/topic.rb +3 -3
  9. data/lib/rtm/axes/topics.rb +3 -3
  10. data/lib/rtm/engine.rb +48 -5
  11. data/lib/rtm/extensions.rb +58 -8
  12. data/lib/rtm/io.rb +2 -1
  13. data/lib/rtm/io/tmapix_from.rb +155 -0
  14. data/lib/rtm/io/tmapix_to.rb +223 -0
  15. data/lib/rtm/io/to_hash.rb +79 -41
  16. data/lib/rtm/io/to_jtm.rb +1 -1
  17. data/lib/rtm/io/to_rdf.rb +20 -5
  18. data/lib/rtm/io/to_string.rb +13 -2
  19. data/lib/rtm/io/to_yaml.rb +39 -11
  20. data/lib/rtm/navigation.rb +1 -15
  21. data/lib/rtm/navigation/association/players.rb +1 -1
  22. data/lib/rtm/navigation/name/characteristics.rb +1 -1
  23. data/lib/rtm/navigation/occurrence/characteristics.rb +1 -1
  24. data/lib/rtm/navigation/topic/characteristics.rb +1 -1
  25. data/lib/rtm/navigation/topic/players.rb +1 -1
  26. data/lib/rtm/navigation/topic/supertypes.rb +21 -17
  27. data/lib/rtm/navigation/topic/traverse.rb +1 -1
  28. data/lib/rtm/navigation/topic/types.rb +6 -4
  29. data/lib/rtm/psi.rb +6 -0
  30. data/lib/rtm/sugar.rb +42 -29
  31. data/lib/rtm/sugar/association/hash_access.rb +3 -3
  32. data/lib/rtm/sugar/occurrence/dynamic_value.rb +39 -56
  33. data/lib/rtm/sugar/occurrence/external.rb +53 -0
  34. data/lib/rtm/sugar/reifiable/reifier.rb +21 -0
  35. data/lib/rtm/sugar/role/counterparts.rb +12 -6
  36. data/lib/rtm/sugar/topic/best_name.rb +74 -0
  37. data/lib/rtm/sugar/topic/characteristics.rb +10 -10
  38. data/lib/rtm/sugar/topic/counterparts.rb +131 -119
  39. data/lib/rtm/sugar/topic/scoped.rb +102 -53
  40. data/lib/rtm/sugar/topic/topic_ref.rb +63 -12
  41. data/lib/rtm/sugar/topic/typed.rb +50 -2
  42. data/lib/rtm/sugar/topic_map/query_cache.rb +66 -0
  43. data/lib/rtm/sugar/topic_map/themes.rb +53 -0
  44. data/lib/rtm/sugar/typed/types.rb +1 -1
  45. data/lib/rtm/validation.rb +2 -2
  46. data/lib/rtm/version.rb +18 -6
  47. data/spec/rtm/axes/string_spec.rb +7 -7
  48. data/spec/rtm/axes/strings_spec.rb +10 -10
  49. data/spec/rtm/io/tmapix_from_spec.rb +76 -0
  50. data/spec/rtm/io/tmapix_to_spec.rb +159 -0
  51. data/spec/rtm/io/to_hash_spec.rb +90 -0
  52. data/spec/rtm/io/to_rdf_spec.rb +37 -0
  53. data/spec/rtm/io/to_string_spec.rb +122 -0
  54. data/spec/rtm/io/to_yaml_spec.rb +89 -0
  55. data/spec/rtm/sugar/occurrence/dynamic_value_spec.rb +156 -1
  56. data/spec/rtm/sugar/occurrence/external_spec.rb +129 -0
  57. data/spec/rtm/sugar/reifiable/reifier_spec.rb +41 -0
  58. data/spec/rtm/sugar/role/counterparts_spec.rb +174 -172
  59. data/spec/rtm/sugar/topic/best_name_spec.rb +25 -0
  60. data/spec/rtm/sugar/topic/characteristics_spec.rb +20 -5
  61. data/spec/rtm/sugar/topic/counterparts_spec.rb +41 -1
  62. data/spec/rtm/sugar/topic/hash_access_spec.rb +1 -1
  63. data/spec/rtm/sugar/topic/scoped_spec.rb +178 -114
  64. data/spec/rtm/sugar/topic/topic_ref_spec.rb +10 -10
  65. data/spec/rtm/sugar/topic/typed_spec.rb +196 -134
  66. data/spec/rtm/sugar/topic_map/themes_spec.rb +67 -0
  67. data/spec/rtm/sugar/typed/types_spec.rb +1 -1
  68. data/spec/rtm/tmapi/core/association_spec.rb +2 -2
  69. data/spec/rtm/tmapi/core/datatype_aware_spec.rb +236 -0
  70. data/spec/rtm/tmapi/core/name_spec.rb +186 -1
  71. data/spec/rtm/tmapi/core/occurrence_spec.rb +24 -67
  72. data/spec/rtm/tmapi/core/reifiable_spec.rb +2 -2
  73. data/spec/rtm/tmapi/core/scoped_spec.rb +40 -2
  74. data/spec/rtm/tmapi/core/topic_map_spec.rb +98 -30
  75. data/spec/rtm/tmapi/core/topic_spec.rb +558 -82
  76. data/spec/rtm/tmapi/core/variant_spec.rb +3 -3
  77. data/spec/rtm_spec.rb +0 -1
  78. data/spec/spec_helper.rb +7 -2
  79. data/test/javalibs/junit-4.5.jar +0 -0
  80. data/test/javalibs/tmapi-2.0-tests.jar +0 -0
  81. data/test/tmapi_tests.rb +25 -0
  82. metadata +66 -11
  83. data/lib/rtm/io/ontopia_io.rb +0 -25
  84. data/lib/rtm/io/tmapix.rb +0 -234
  85. data/lib/rtm/sugar/occurrence/externalize.rb +0 -31
  86. data/spec/rtm/io/tmapix_spec.rb +0 -85
  87. data/test/base_unit_test.rb +0 -161
  88. data/test/base_unit_test_tmapi.rb +0 -165
data/README CHANGED
@@ -1,4 +1,39 @@
1
- Copyright: Copyright 2009 Topic Maps Lab, University of Leipzig.
2
- License: Apache License, Version 2.0
1
+ ==== Ruby Topic Maps (RTM)
2
+ RTM is a Topic Maps engine written in Ruby. See http://rtm.topicmapslab.de/ for instructions.
3
+ Several backends and extensions are available as separate gems.
3
4
 
4
- See http://rtm.topicmapslab.de/ for instructions.
5
+ ==== Overview
6
+ From a developer's perspective, RTM is a schema-less database management system.
7
+ The Topic Maps standard (described below) on which RTM is based provides a way of creating a self-describing schema just by using it.
8
+
9
+ ==== Quickstart
10
+ require 'rtm'
11
+ connection = RTM.connect # uses the default Ontopia in-memory backend
12
+ topic_map = connection.create "http://example.org/my_topic_map/"
13
+ some_topic = topicmap.get!("identifier_of_the_topic")
14
+ some_topic["-"] = "default name for the topic"
15
+ topic_map.to_xtm("my_xtm_file.xtm")
16
+
17
+ ==== Topic Maps
18
+ Topic Maps is an international industry standard (ISO13250) for interchangeably representing information
19
+ about the structure of information resources used to define topics, and the relationships between topics.
20
+ A set of one or more interrelated documents that employs the notation defined by this International Standard is called a topic map.
21
+ A topic map defines a multidimensional topic space - a space in which the locations are topics,
22
+ and in which the distances between topics are measurable in terms of the number of intervening topics
23
+ which must be visited in order to get from one topic to another, and the kinds of relationships that define
24
+ the path from one topic to another, if any, through the intervening topics, if any.
25
+ In addition, information objects can have properties, as well as values for those properties, assigned to them.
26
+ The Topic Maps Data Model which is used in this implementation can be found on http://www.isotopicmaps.org/sam/sam-model/.
27
+
28
+ ==== Backends
29
+ * rtm-ontopia: JRuby only, recommended, uses Ontopia: http://code.google.com/p/ontopia/
30
+ * rtm-tinytim: JRuby only, uses TinyTiM: http://tinytim.sourceforge.net/
31
+ * rtm-activerecord: uses a custom ActiveRecord schema
32
+
33
+ ==== Extensions
34
+ * rtm-tmql: Adds support for the Topic Maps Query Language (TMQL), http://isotopicmaps.org/tmql/
35
+ * rtm-tmcl: Adds support for the Topic Maps Constraint Language (TMCL), http://isotopicmaps.org/tmcl/
36
+
37
+ ==== License
38
+ Copyright 2009 Topic Maps Lab, University of Leipzig.
39
+ Apache License, Version 2.0
data/lib/rtm.rb CHANGED
@@ -1,12 +1,15 @@
1
- # (J)RTM: (J)Ruby Topic Maps.
2
- # Copyright: Topic Maps Lab www.topicmapslab.de
3
- # License: Apache License, Version 2.0
4
- # Project lead: Benjamin Bock bock(at)informatik.uni-leipzig.de
5
- # Responsible for (J)RTM: Arnim Bleier bleier(at)informatik.uni-leipzig.de
6
- # Responsible for Documentation: Uta Schulze uta.schulze(at)informatik.uni-leipzig.de
7
- # Responsible for ActiveTM: Daniel Exner exner(at)informatik.uni-leipzig.de
8
-
9
- $: << File.expand_path(File.dirname(__FILE__))
1
+ # Ruby Topic Maps (RTM)
2
+ # Copyright: Topic Maps Lab http://www.topicmapslab.de
3
+ # License: Apache License, Version 2.0
4
+ # Project lead: Benjamin Bock bock(at)informatik.uni-leipzig.de
5
+ # Developers: Benjamin Bock bock(at)informatik.uni-leipzig.de
6
+ # Arnim Bleier bleier(at)informatik.uni-leipzig.de
7
+ # Uta Schulze uta.schulze(at)informatik.uni-leipzig.de
8
+ # Daniel Exner exner(at)informatik.uni-leipzig.de
9
+ # Testing: Uta Schulze uta.schulze(at)informatik.uni-leipzig.de
10
+ # Documentation: Uta Schulze uta.schulze(at)informatik.uni-leipzig.de
11
+
12
+ $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__))
10
13
 
11
14
  module RTM
12
15
  module Topic
@@ -49,6 +52,9 @@ module RTM
49
52
  attr_accessor :engine
50
53
  end
51
54
 
55
+ module TopicMapSystem
56
+ end
57
+
52
58
  module ItemIdentifier
53
59
  end
54
60
 
@@ -57,14 +63,14 @@ module RTM
57
63
 
58
64
  module SubjectLocator
59
65
  end
60
-
61
- module TopicMapSystem
66
+
67
+ module DatatypeAware
62
68
  end
63
69
  end
64
70
 
65
71
  require 'rtm/version'
66
- require "rtm/engine"
67
72
  require 'rtm/extensions'
73
+ require "rtm/engine"
68
74
  require 'rtm/psi'
69
75
  require "rtm/navigation"
70
76
  require "rtm/axes"
@@ -84,41 +90,9 @@ module RTM
84
90
  # RTM.connect(:implementation => :merged) -> Merged TMAPI backend
85
91
  #
86
92
  def self.connect(params = {}, *args)
87
- implementation = params[:implementation]
88
-
89
- unless implementation
90
- if Engine.list.first
91
- implementation = Engine.list.first
92
- warn("No engine implementation was specified for RTM.connect. Using the first already loaded engine (#{implementation.inspect}).")
93
- else
94
- if RUBY_PLATFORM =~ /java/
95
- implementation = :ontopia
96
- else
97
- implementation = :activerecord
98
- warn("No engine implementation was specified for RTM.connect. Choosing default (#{implementation.inspect}).")
99
- end
100
- end
101
- params[:implementation] = implementation
102
- end
103
-
104
- unless Engine.list.include?(implementation)
105
- warn("Requested engine '#{implementation}' not loaded. Trying to autoload it.")
106
- Engine.load(implementation)
107
- if Engine.list.include?(implementation)
108
- warn("Autoloading '#{implementation}' was successful")
109
- else
110
- raise "Autoloading '#{implementation}' failed. Make sure rtm-#{implementation} exists and is installed or require it manually."
111
- end
112
- end
113
-
114
- engine = RTM::Engine[implementation]
115
-
93
+ engine = Engine.load!(params[:implementation])
116
94
  connection = engine.new(params)
117
-
118
- @connections ||= {}
119
- @connections[implementation] ||= []
120
- @connections[implementation] << connection
121
-
95
+ add_connection(connection)
122
96
  connection
123
97
  end
124
98
 
@@ -128,7 +102,7 @@ module RTM
128
102
  # connections -> Hash
129
103
  #
130
104
  def self.connections
131
- @connections ||= {}
105
+ @connections ||= Hash.new{|h,k| h[k] = []}
132
106
  @connections
133
107
  end
134
108
 
@@ -153,4 +127,8 @@ module RTM
153
127
  self.included_modules.each {|im| klass.extend(im)}
154
128
  end
155
129
 
130
+ private
131
+ def self.add_connection(connection)
132
+ self.connections[connection.class.identifier] << connection
133
+ end
156
134
  end
data/lib/rtm/axes.rb CHANGED
@@ -226,7 +226,8 @@ module RTM
226
226
  end
227
227
  end
228
228
 
229
- module RTM::Topic
229
+ module RTM::AxesExtension;end
230
+ module RTM::AxesExtension::Topic
230
231
 
231
232
  # Changes from TMAPI-mode to Axes-mode.
232
233
  #
@@ -238,7 +239,7 @@ module RTM::Topic
238
239
  end
239
240
  end
240
241
 
241
- module RTM::Name
242
+ module RTM::AxesExtension::Name
242
243
 
243
244
  # Changes from TMAPI-mode to Axes-mode.
244
245
  #
@@ -250,7 +251,7 @@ module RTM::Name
250
251
  end
251
252
  end
252
253
 
253
- module RTM::Occurrence
254
+ module RTM::AxesExtension::Occurrence
254
255
 
255
256
  # Changes from TMAPI-mode to Axes-mode.
256
257
  #
@@ -262,7 +263,7 @@ module RTM::Occurrence
262
263
  end
263
264
  end
264
265
 
265
- module RTM::Association
266
+ module RTM::AxesExtension::Association
266
267
 
267
268
  # Changes from TMAPI-mode to Axes-mode.
268
269
  #
@@ -288,6 +289,8 @@ class String
288
289
  end
289
290
  end
290
291
 
292
+ RTM.register_extension(RTM::AxesExtension)
293
+
291
294
  require "rtm/axes/topics"
292
295
  require "rtm/axes/associations"
293
296
  require "rtm/axes/characteristics"
@@ -10,7 +10,7 @@ module RTM::Axes
10
10
  # Returns all Role players of Roles in this Association.
11
11
  #
12
12
  # The optional identifier specifies the type of the Roles to be considered.
13
- # The identifier may be a Topic or Topic-Reference.
13
+ # The identifier may be a topic reference.
14
14
  #
15
15
  # Multiple instances of the same Topic are possible.
16
16
  # The result may be empty.
@@ -18,7 +18,7 @@ module RTM::Axes
18
18
  # Returns all Role players of Roles in these Associations.
19
19
  #
20
20
  # The optional identifier specifies the type of the Roles to be considered.
21
- # The identifier may be a Topic or Topic-Reference.
21
+ # The identifier may be a topic reference.
22
22
  #
23
23
  # Multiple instances of the same Topic are possible.
24
24
  # The result may be empty.
@@ -24,7 +24,7 @@ module RTM::Axes
24
24
  # Characteristic for its type. If the type
25
25
  # does not match, nil is returned.
26
26
  #
27
- # The identifier may be a Topic or Topic-Reference.
27
+ # The identifier may be a topic reference.
28
28
  #
29
29
  # :call-seq:
30
30
  # reverse_characteristics -> Topic
@@ -37,7 +37,7 @@ module RTM::Axes
37
37
  # Characteristics for their types. If the type
38
38
  # does not match, the Topic is not returned.
39
39
  #
40
- # The identifier may be a Topic or Topic-Reference.
40
+ # The identifier may be a topic reference.
41
41
  #
42
42
  # :call-seq:
43
43
  # reverse_characteristics -> Array of Topic
@@ -11,7 +11,7 @@ module RTM::Axes
11
11
  # If an identifier is given, only those Names and Occurrences are returned,
12
12
  # whose type or supertypes include the identifier.
13
13
  #
14
- # Identifier may be a Topic or Topic-Reference.
14
+ # Identifier may be a topic reference.
15
15
  #
16
16
  # The result may be empty.
17
17
  #
@@ -68,7 +68,7 @@ module RTM::Axes
68
68
  #
69
69
  # The optional
70
70
  # identifier specifies the type of the Roles to be considered.
71
- # The identifier may be a Topic or Topic-Reference.
71
+ # The identifier may be a topic reference.
72
72
  #
73
73
  # Multiple instances of the same Association are possible.
74
74
  # The result may be empty.
@@ -177,7 +177,7 @@ module RTM::Axes
177
177
  # The current Topic is deducted ones from the returned Array.
178
178
  # The result may be empty.
179
179
  #
180
- # The identifier may be a Topic or Topic-Reference.
180
+ # The identifier may be a topic reference.
181
181
  #
182
182
  # :call-seq:
183
183
  # traverse(identifier) -> Array of Topics
@@ -19,7 +19,7 @@ module RTM::Axes
19
19
  # If an identifier is given, only those Names and Occurrences are returned,
20
20
  # whose type or supertypes include the identifier.
21
21
  #
22
- # Identifier may be a Topic or Topic-Reference.
22
+ # Identifier may be a topic reference.
23
23
  #
24
24
  # The result may be empty.
25
25
  #
@@ -90,7 +90,7 @@ module RTM::Axes
90
90
  #
91
91
  # The optional
92
92
  # identifier specifies the type of the Roles to be considered.
93
- # The identifier may be a Topic or Topic-Reference.
93
+ # The identifier may be a topic reference.
94
94
  #
95
95
  # Multiple instances of the same Association are possible.
96
96
  # The result may be empty.
@@ -209,7 +209,7 @@ module RTM::Axes
209
209
  # Each Topic is deducted ones from the returned Array.
210
210
  # The result may be empty.
211
211
  #
212
- # The identifier may be a Topic or Topic-Reference.
212
+ # The identifier may be a topic reference.
213
213
  #
214
214
  # :call-seq:
215
215
  # traverse(identifier) -> Array of Topics
data/lib/rtm/engine.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  module RTM
2
- class Engine
2
+ class Engine
3
+ include RTM::TopicMapSystem
4
+
3
5
  def self.abstract?
4
6
  self == Engine
5
7
  end
@@ -38,21 +40,62 @@ module RTM
38
40
  end
39
41
 
40
42
  def self.load(engine_name)
41
- begin
43
+ if Object.const_defined?("Gem") && rtmgem = Gem.loaded_specs["rtm"]
42
44
  require "rtm/#{engine_name}"
43
- rescue LoadError
45
+ else
44
46
  engine_path = File.expand_path(File.join(File.dirname(__FILE__), "../../../rtm-#{engine_name}/lib"))
45
47
  if File.directory?(engine_path)
46
- $:.unshift engine_path
48
+ $LOAD_PATH.unshift engine_path
47
49
  require "rtm/#{engine_name}"
48
50
  end
49
51
  end
52
+ self[engine_name]
53
+ end
54
+
55
+ def self.load!(engine_name=nil)
56
+ engine_name = self.detect unless engine_name
57
+ unless list.include?(engine_name)
58
+ warn("Requested engine '#{engine_name}' not loaded. Trying to autoload it.")
59
+ engine = load(engine_name)
60
+ if list.include?(engine_name)
61
+ warn("Autoloading '#{engine_name}' was successful")
62
+ else
63
+ raise "Autoloading '#{engine_name}' failed. Make sure rtm-#{engine_name} exists and is installed or require it manually."
64
+ end
65
+ end
66
+ engine || load(engine_name)
50
67
  end
51
68
 
69
+ def self.detect(preferred=nil)
70
+ if preferred # return the users preference, if given
71
+ implementation = preferred
72
+ elsif engine_name = ENV['RTM_IMPLEMENTATION'] # inspect system environment
73
+ implementation = engine_name.to_sym
74
+ elsif engine_name = ENV['RTM_ENGINE'] # inspect system environment (alternative)
75
+ implementation = engine_name.to_sym
76
+ elsif implementation = self.list.first # check if one is already loaded
77
+ warn("No engine implementation was specified for RTM.connect. Using the first already loaded engine (#{implementation.inspect}).")
78
+ else
79
+ implementation = self.default # use hardcoded default
80
+ warn("No engine implementation was specified for RTM.connect. Choosing default (#{implementation.inspect}).")
81
+ implementation
82
+ end
83
+ implementation
84
+ end
85
+
86
+ def self.default
87
+ if RUBY_PLATFORM =~ /java/
88
+ :ontopia
89
+ else
90
+ :activerecord
91
+ end
92
+ end
93
+
52
94
  attr_reader :connections
95
+
53
96
  def initialize(params={})
54
97
  @params = params
55
98
  end
56
-
99
+
57
100
  end
58
101
  end
@@ -2,7 +2,7 @@
2
2
  # License: Apache License, Version 2.0
3
3
 
4
4
  module RTM
5
- # Register a module as extension.
5
+ # Register a module as extension to RTM.
6
6
  #
7
7
  # Example:
8
8
  # module MyExtension
@@ -14,16 +14,66 @@ module RTM
14
14
  # RTM.register_extension(self)
15
15
  # end
16
16
  #
17
- def self.register_extension(plugin_mod)
18
- plugin_mod.constants.each do |const|
19
- const_get(const).send(:include, plugin_mod.const_get(const) ) if const_defined?(const)
17
+ def self.register_extension(module_with_modules)
18
+ # puts "[RTMEXT] registering extension #{module_with_modules}"
19
+ module_with_modules.constants.each do |sub_module|
20
+ self.const_get(sub_module).register_extension(module_with_modules.const_get(sub_module)) if self.const_defined?(sub_module)
20
21
  end
21
22
  end
22
- module AR
23
- def self.register_extension(plugin_mod)
24
- plugin_mod.constants.each do |const|
25
- const_get(const).send(:include, plugin_mod.const_get(const) ) if const_defined?(const)
23
+
24
+ # Extend a module or class with this method to make it a receiver for RTM extensions.
25
+ # E.g. MyModule.extend(Extendable) or MyClass.extend(Extendable).
26
+ #
27
+ # A extension can then be registered using
28
+ # MyModule.register_extension(MyExtension)
29
+ #
30
+ # The module will then keep track of all modules or classes it's included in.
31
+ # These modules and classes are called implementations here.
32
+ # If an extension is added later, the implementations will also be updated which would not be the case if normal includes were used.
33
+ module Extendable
34
+ # Register a module as an extension to an Entity in RTM.
35
+ # An entity may be e.g. RTM::TopicMap, RTM::Topic or any Module which was extended with RTM::Extendable
36
+ #
37
+ # Besides normal ruby inclusion of the module, this module keeps track of its implementations which are also updated in this method.
38
+ def register_extension(mod)
39
+ include mod
40
+ return unless @implementations
41
+ @implementations.each do |impl|
42
+ next if impl.ancestors.include?(mod)
43
+ impl.send(:include, mod)
44
+ end
45
+ end
46
+
47
+ # A standard Ruby hook to be notified about inclusions of this module.
48
+ # This normally eliminates the need to register a module as implementa
49
+ def included(klass)
50
+ # super
51
+ # puts "[RTMEXT] including #{self} into #{klass} in #{caller(1).first}"
52
+ register_implementation(klass)
53
+ klass.class_eval do
54
+ def self.included(klass2)
55
+ # puts "[RTMIMPLEXT] #{self} was included into #{klass2} in #{caller(1).first}"
56
+ # self.ancestors.select {|anc| anc.respond_to?(:register_implementation)}.each{|anc| anc.register_implementation(klass2) }
57
+ self.ancestors.find {|anc| anc.respond_to?(:register_implementation)}.register_implementation(klass2)
58
+ end
26
59
  end
27
60
  end
61
+
62
+ # Register an implementation to this module.
63
+ # Registred implementations will be updated if later any extensions are added.
64
+ # This method should normally be called from the included hook.
65
+ # Due to Ruby's restrictions on calling protected methods from other modules extending the very same module Extendable,
66
+ # this method must be public.
67
+ def register_implementation(klass)
68
+ # super if self.class.superclass.respond_to?(:register_implementation)
69
+ @implementations ||= []
70
+ @implementations << klass
71
+ end
28
72
  end
73
+ [
74
+ TopicMapSystem, Construct, Reifiable,
75
+ DatatypeAware, Scoped, Typed,
76
+ TopicMap, Topic, Name, Occurrence, Variant, Association, Role,
77
+ Locator, ItemIdentifier, SubjectIdentifier, SubjectLocator
78
+ ].each{|mod| mod.extend(Extendable)}
29
79
  end