rtm 0.1.1 → 0.1.3

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.
@@ -54,6 +54,8 @@ module RTM::AR
54
54
  end
55
55
 
56
56
  def self.create(base_locator, params={})
57
+ bl_uri = URI.parse(base_locator)
58
+ raise "The locator for the Topic Map must be absolute! \"#{base_locator}\" is not an absolute locator." unless bl_uri.absolute?
57
59
  tm = self.wrap(TMDM::TopicMap.find_or_create_by_base_locator(base_locator))
58
60
  yield tm if block_given?
59
61
  tm
@@ -119,6 +121,7 @@ module RTM::AR
119
121
 
120
122
  # internal helper for by_item_identifier, doesn't wrap result
121
123
  def _by_item_identifier(iid)
124
+ iid = RTM::LocatorHelpers.iid2iri(iid) if RTM::LocatorHelpers.is_a_iid?(iid)
122
125
  ii = __getobj__.locators.find_by_reference(resolve(iid)) #, :include => [ :topic_map_construct ])
123
126
  return ii.topic_map_construct if ii
124
127
  nil
@@ -132,6 +135,7 @@ module RTM::AR
132
135
 
133
136
  # internal helper for topic_by_item_identifier!, doesn't wrap result
134
137
  def _topic_by_item_identifier!(iid)
138
+ iid = RTM::LocatorHelpers.iid2iri(iid) if RTM::LocatorHelpers.is_a_iid?(iid)
135
139
  ii = __getobj__.locators.find_or_create_by_reference(resolve(iid))#, :include => [ :topic_map_construct ])
136
140
  return ii.topic_map_construct if ii.topic_map_construct && ii.topic_map_construct_type =~ /::Topic$/
137
141
  top2 = _topic_by_subject_identifier(resolve(iid))
@@ -187,6 +191,8 @@ module RTM::AR
187
191
  raise "Locator may not be nil" unless iri
188
192
  if RTM::LocatorHelpers.is_a_slo?(iri)
189
193
  _topic_by_subject_locator(iri)
194
+ elsif RTM::LocatorHelpers.is_a_iid?(iri)
195
+ _topic_by_item_identifier(iri)
190
196
  elsif URI.parse(iri).absolute?
191
197
  _topic_by_subject_identifier(iri)
192
198
  else
@@ -198,13 +204,22 @@ module RTM::AR
198
204
  raise "Locator may not be nil" unless iri
199
205
  if RTM::LocatorHelpers.is_a_slo?(iri)
200
206
  _topic_by_subject_locator!(iri)
207
+ elsif RTM::LocatorHelpers.is_a_iid?(iri)
208
+ _topic_by_item_identifier!(iri)
201
209
  elsif URI.parse(iri).absolute?
202
210
  _topic_by_subject_identifier!(iri)
203
211
  else
204
212
  _topic_by_item_identifier!(iri)
205
213
  end
206
214
  end
207
-
215
+
216
+ %w[topic association role name occurrence variant].each do |x|
217
+ eval <<-EOI
218
+ def _#{x}_by_id(id)
219
+ __getobj__.#{x}s.find(id)
220
+ end
221
+ EOI
222
+ end
208
223
  public
209
224
  # returns an item identifier from the topic_map if it exists
210
225
  def item_identifier(iid)
@@ -248,8 +263,11 @@ module RTM::AR
248
263
  #
249
264
  # Returns nil if the Topic does not exist.
250
265
  #
266
+ # It's also possible to pass a number, which is used to fetch a topic using the internal id. In this case, an exception is thrown, if the topic does not exist.
267
+ #
251
268
  def topic_by_locator(iri)
252
269
  return iri if iri.is_a? Topic
270
+ return topic_by_id(iri) if iri.is_a? Integer
253
271
  # @tblc ||= {}
254
272
  # t = @tblc[iri]
255
273
  # return t if t
@@ -263,9 +281,11 @@ module RTM::AR
263
281
  # its (absolute) subject identifier or its (absolute and by "=" prepended) subject locator)
264
282
  #
265
283
  # If there is no topic with this item identifier, subject identifier or subject locator, it is created.
284
+ # Please be aware, the creation does not work with the internal (numeric) ids.
266
285
  #
267
286
  def topic_by_locator!(iri)
268
287
  return iri if iri.is_a? Topic
288
+ return topic_by_id(iri) if iri.is_a? Integer
269
289
  # @tblc ||= {}
270
290
  # t = @tblc[iri]
271
291
  # return t if t
@@ -275,6 +295,15 @@ module RTM::AR
275
295
  end
276
296
  alias :get! :topic_by_locator!
277
297
 
298
+ %w[topic association role name occurrence variant].each do |x|
299
+ eval <<-EOI
300
+ def #{x}_by_id(id)
301
+ #{x.camelize}.wrap(_#{x}_by_id(id))
302
+ end
303
+ alias :#{x[0].chr}id :#{x}_by_id
304
+ EOI
305
+ end
306
+
278
307
  # I am not sure if this is at all correct. TMDM doesn't say a word about it
279
308
  # and the approach to compare topic maps is CXTM. I chose this because we
280
309
  # should (at least at the time of writing) have only one topic with a given
@@ -0,0 +1,86 @@
1
+ module RTM::AR
2
+ module TraverseAssociations
3
+ def define_association(prop, options={})
4
+ r = options[:rule]
5
+ module_eval(<<-EOS, "(__AR_DELEGATOR_DEFINE_ASSOCIATION__)", 1)
6
+ def direct_#{prop}_roles
7
+ # prefetch typing topics
8
+ rtype = @ips_#{prop}_rtype ||= self.topic_map.get("#{r[:role_type]}")
9
+ atype = @ips_#{prop}_atype ||= self.topic_map.get("#{r[:association_type]}")
10
+ otype = @ips_#{prop}_otype ||= self.topic_map.get("#{r[:other_role_type]}")
11
+ # return nothing if any of the typing topics does not exist
12
+ return [] unless rtype && atype && otype
13
+ # we do that only here and not earlier because some might me nil
14
+ rtype = rtype.id
15
+ atype = atype.id
16
+ otype = otype.id
17
+ self.__getobj__.roles.map{|r|
18
+ r.ttype_id != nil &&
19
+ r.ttype_id == rtype &&
20
+ r.parent.roles.size == #{r[:association_arity]} &&
21
+ r.parent != nil &&
22
+ r.parent.ttype_id == atype &&
23
+ (r2 = r.parent.roles.select{|r2| r2.ttype_id != nil &&
24
+ r2.ttype_id == otype}.first) &&
25
+ r2}.select{|r2| r2}.map{|r2| AssociationRole.wrap(r2)}
26
+ end
27
+ def direct_#{prop}
28
+ direct_#{prop}_roles.map{|r2| r2.player}.uniq
29
+ end
30
+ EOS
31
+
32
+ if r[:transitive]
33
+ module_eval(<<-EOS, "(__AR_DELEGATOR_DEFINE_ASSOCIATION2__)", 1)
34
+ def #{prop}
35
+ d = todo = self.direct_#{prop}
36
+ while todo.size > 0
37
+ todo = todo.map{|dt| dt.direct_#{prop}}.flatten.uniq - d
38
+ d += todo
39
+ end
40
+ d
41
+ #d2 = self.direct_#{prop}.map {|dt| dt.#{prop}}.flatten
42
+ #(d+d2).uniq
43
+ end
44
+ EOS
45
+ else
46
+ if r[:infer] && r[:infer_other] # this part is not testet at all!
47
+ module_eval(<<-EOS, "(__AR_DELEGATOR_DEFINE_ASSOCIATION3a__)", 1)
48
+ def #{prop}
49
+ dps = (self + self.#{r[:infer]}).flatten.uniq
50
+ dcps = dps.map{|d2| d2.direct_#{prop}}
51
+ (dcps + dcps.map{|d2| d2.#{r[:infer_other]}}).flatten.uniq
52
+ end
53
+ EOS
54
+ elsif r[:infer]
55
+ module_eval(<<-EOS, "(__AR_DELEGATOR_DEFINE_ASSOCIATION3__)", 1)
56
+ def #{prop}
57
+ (self.direct_#{prop} + self.#{r[:infer]}.map{|d2| d2.direct_#{prop}}).flatten.uniq
58
+ end
59
+ EOS
60
+ elsif r[:infer_other]
61
+ module_eval(<<-EOS, "(__AR_DELEGATOR_DEFINE_ASSOCIATION4__)", 1)
62
+ def #{prop}
63
+ d = self.direct_#{prop}
64
+ (d + d.map{|d2| d2.#{r[:infer_other]}}).flatten.uniq
65
+ end
66
+ EOS
67
+ end
68
+ end
69
+ if r[:add]
70
+ module_eval(<<-EOS, "(__AR_DELEGATOR_DEFINE_ASSOCIATION_ADD_REMOVE__)", 1)
71
+ def add_#{r[:add]}(t)
72
+ a = self.topic_map.create_association("#{r[:association_type]}")
73
+ a.create_role self, "#{r[:role_type]}"
74
+ a.create_role t, "#{r[:other_role_type]}"
75
+ a
76
+ # TODO add_x in define_association needs to trigger reload of the topics somewhere
77
+ end
78
+ def remove_#{r[:add]}(t)
79
+ direct_#{prop}_roles.select{|r| r.player == t}.each{|r| r.parent.remove}
80
+ # TODO remove_x in define_association needs to trigger reload of the topics somewhere
81
+ end
82
+ EOS
83
+ end
84
+ end
85
+ end
86
+ end
@@ -33,7 +33,7 @@ module XML
33
33
  # Acts as Callback structure for the LibXML-Ruby SAX Parser and calls
34
34
  # a REXML SAX2Listener API.
35
35
  class LibXMLSax2wrapper
36
- include XML::SaxParser::Callbacks
36
+ include LibXML::XML::SaxParser::Callbacks
37
37
  def initialize(rexml_sax2listener)
38
38
  @dest = rexml_sax2listener
39
39
  @ns = Hash.new("http://www.topicmaps.org/xtm/")
@@ -19,5 +19,21 @@ module RTM
19
19
  def self.is_a_slo?(iri)
20
20
  iri.to_s[0] == "="[0]
21
21
  end
22
+
23
+ def self.iid2iri(slo)
24
+ slo = slo.to_s
25
+ slo = slo[1..-1].lstrip if slo[0] == "^"[0] # remove = if slo starts with it
26
+ slo
27
+ end
28
+ def self.iri2iid(iri)
29
+ return "^#{iri}" if slo[0] == "="[0]
30
+ iri
31
+ end
32
+
33
+ # returns true if the String or Locator given starts with "^".
34
+ # This catches only the prefixing-style, not the local-identifier (non-absolute-iri) style
35
+ def self.is_a_iid?(iri)
36
+ iri.to_s[0] == "^"[0]
37
+ end
22
38
  end
23
39
  end
@@ -0,0 +1,51 @@
1
+ module RTM::Sugar
2
+ module Role
3
+ module Counterparts
4
+ # This method fetches all roles from the parent association of this role, except itself (i.e. current role).
5
+ # A filter-hash may be used to filter for the type of the other role (:otype =>topic_reference).
6
+ # Examples:
7
+ # this_role.counterparts # returns all
8
+ # this_role.counterparts(:otype => some_topic) # returns only other roles which have type some_topic
9
+ # this_role.counterparts(:otype => "some_reference") # as above, looking up the reference first
10
+ def counterparts(filter={})
11
+ self.parent.roles.reject{|r| r.id==self.id}.
12
+ select{|r| filter[:otype] ? r.type == self.topic_map.get(filter[:otype]) : true}
13
+ end
14
+
15
+ # This methods fetches all players of the parent association of this role, except the player of itself.
16
+ # It accepts a filter-hash like the counterparts-method.
17
+ def counterplayers(*args)
18
+ self.counterparts(*args).map{|r| r.player}
19
+ end
20
+
21
+ # Fetches the other role, if the parent association is binary.
22
+ def counterpart
23
+ n = self.parent.roles.size
24
+ raise "Association must be unary or binary to use counterpart method. Please use counterparts for n-ary associations." if n > 2
25
+ return nil if n == 1
26
+ self.counterparts.first
27
+ end
28
+
29
+ # Fetches the player of the other role, if the parent association is binary.
30
+ def counterplayer
31
+ n = self.parent.roles.size
32
+ raise "Association must be unary or binary to use counterplayer method. Please use counterplayers for n-ary associations." if n > 2
33
+ return nil if n == 1
34
+ self.counterparts.first.player
35
+ end
36
+
37
+ # Fetches all roles of the (binary) parent associations which play the same role in the same with the counterplayer
38
+ # TODO: filter not only otype but also atype and rtype.
39
+ def peers
40
+ cp = self.counterpart
41
+ cp.player.roles.select{|r| r.type == cp.type}.map{|r| r.counterpart}
42
+ end
43
+ # Fetches all players of roles being in the same association with another topic as self
44
+ # Example: current_role is a role of player "me" and type "employee"
45
+ # current_role.peerplayers # returns all employees of my company (including me)
46
+ def peerplayers
47
+ self.peers.map{|r| r.player}
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,15 @@
1
+ module RTM::Sugar
2
+ module Topic
3
+ module Characteristics
4
+ def characteristics
5
+ topic_names.to_a + occurrences.to_a
6
+ end
7
+ def internal_occurrences
8
+ occurrences.select{|o| o.datatype != RTM::PSI[:IRI]}
9
+ end
10
+ def external_occurrences
11
+ occurrences.select{|o| o.datatype == RTM::PSI[:IRI]}
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ module RTM::Sugar
2
+ module Topic
3
+ module Counterparts
4
+ def counterparts(filter={})
5
+ self.roles.
6
+ select{|r| filter[:rtype] ? r.type == self.topic_map.get(filter[:rtype]) : true}.
7
+ select{|r| filter[:atype] ? r.parent.type == self.topic_map.get(filter[:atype]) : true}.
8
+ inject([]){|all,r| all+=r.counterparts(filter)}
9
+ end
10
+ def counterplayers(*args)
11
+ return self.counterparts(*args).map{|r| r.player}
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,55 @@
1
+ module RTM::Sugar
2
+ module Topic
3
+ module HashAccess
4
+ def [](cref)
5
+ raise "Characteristic reference must be a String" unless cref.is_a? String
6
+ is_name, type_reference, scope_reference = resolve_characteristic(cref)
7
+ if is_name
8
+ type_reference = RTM::PSI[:name_type] if type_reference == :any
9
+ names.select{|n| n.type == topic_map.get(type_reference)}
10
+ else
11
+ raise "No occurrence type given" if type_reference == :any
12
+ occurrences.select{|o| o.type == topic_map.get(type_reference)}
13
+ end
14
+ end
15
+
16
+ def []=(cref, value)
17
+ is_name, type_reference, scope_reference = resolve_characteristic(cref)
18
+ if is_name
19
+ nametype = type_reference || topic_map.get!(RTM::PSI[:name_type])
20
+ n = create_name(value, nametype)
21
+ n
22
+ else
23
+ raise "No occurrence type given" if type_reference == :any
24
+ o = create_occurrence(value, type_reference)
25
+ o
26
+ end
27
+ end
28
+
29
+ private
30
+ def resolve_characteristic(ref)
31
+ ref =~ /^(-\s*)?(.+)?$/
32
+ is_name = $1 ? true : false
33
+ type, scope = resolve_type_and_scope($2)
34
+ [is_name, type, scope]
35
+ end
36
+
37
+ def resolve_type_and_scope(ref)
38
+ return [ref, :ucs] if ref.is_a? Topic
39
+ type, scope = ref.split('@', -1)
40
+ if type.blank?
41
+ type = :any
42
+ else
43
+ type.strip!
44
+ end
45
+ if scope
46
+ scope = scope.strip.split(/\s+/)
47
+ scope = :ucs if scope.blank?
48
+ else
49
+ scope = :any
50
+ end
51
+ [type, scope]
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,11 @@
1
+ module RTM::Sugar
2
+ module Topic
3
+ module IdentifierDirect
4
+ def identifiers
5
+ subject_identifiers.map{|si| si.to_s} +
6
+ subject_locators.map{|sl| "=#{sl.to_s}"} +
7
+ item_identifiers.map{|ii| "^#{ii.to_s}"}
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,42 @@
1
+ module RTM::Sugar
2
+ module Topic
3
+ module PredefinedAssociations
4
+ extend RTM::AR::TraverseAssociations
5
+ # maybe these pairs could be declared each with a single statement and a reversible option
6
+ define_association :types, :type => :Topic, :rule => {
7
+ :transitive => false,
8
+ :role_type => RTM::PSI[:instance],
9
+ :association_type => RTM::PSI[:type_instance],
10
+ :association_arity => 2,
11
+ :other_role_type => RTM::PSI[:type],
12
+ :infer_other => :supertypes,
13
+ :add => :type,
14
+ }
15
+ define_association :instances, :type => :Topic, :rule => {
16
+ :transitive => false,
17
+ :role_type => RTM::PSI[:type],
18
+ :association_type => RTM::PSI[:type_instance],
19
+ :association_arity => 2,
20
+ :other_role_type => RTM::PSI[:instance],
21
+ :infer => :subtypes,
22
+ :add => :instance,
23
+ }
24
+ define_association :supertypes, :type => :Topic, :rule => {
25
+ :transitive => true,
26
+ :role_type => RTM::PSI[:subtype],
27
+ :association_type => RTM::PSI[:supertype_subtype],
28
+ :association_arity => 2,
29
+ :other_role_type => RTM::PSI[:supertype],
30
+ :add => :supertype,
31
+ }
32
+ define_association :subtypes, :type => :Topic, :rule => {
33
+ :transitive => true,
34
+ :role_type => RTM::PSI[:supertype],
35
+ :association_type => RTM::PSI[:supertype_subtype],
36
+ :association_arity => 2,
37
+ :other_role_type => RTM::PSI[:subtype],
38
+ :add => :subtype,
39
+ }
40
+ end
41
+ end
42
+ end
data/test/base_test.rb ADDED
@@ -0,0 +1,153 @@
1
+ #
2
+ # Some basic tests... feel free to add more :)
3
+ #
4
+
5
+
6
+ $:.unshift File.join(File.dirname(__FILE__),'..','lib')
7
+
8
+ require 'test/unit'
9
+ require 'rtm'
10
+
11
+ class BaseTest < Test::Unit::TestCase
12
+ # There are a bunch of global assertions in here so it cannot be parallelized
13
+ # with other tests, that's why it is all in one. What can we do about that?
14
+ def test_connect
15
+ assert RTM.connect, "Connection to memory backend failed"
16
+ assert_equal 0, RTM[].size, "There should be no topic maps in a newly created environment."
17
+ base_locator = "http://rtm.rubyforge.org/tests/base_test"
18
+ m = RTM.create base_locator
19
+ assert_equal 1, RTM[].size, "After creation of a topic map, there should be one."
20
+ assert_kind_of RTM::TopicMap, m, "RTM.create should create something which includes RTM::TopicMap"
21
+ assert_equal base_locator, m.base_locator, "The base_locator should be initialized properly."
22
+ assert m.respond_to?(:topics), "The topic map should respond to :topics"
23
+ assert m.respond_to?(:associations), "The topic map should respond to :topics"
24
+ assert_equal 0, m.topics.size, "A new topic map should have no topics."
25
+ assert_equal 0, m.associations.size, "A new topic map should have no associations."
26
+ assert m.reifier.nil?, "A new topic map should not be reified yet."
27
+ assert_equal 0, m.item_identifiers.size, "A new topic map should "
28
+
29
+ # assigning a reifier
30
+ m.reifier = "a_topic_which_reifies_the_topic_map"
31
+ assert_equal 1, m.topics.size, "A topic should have been created to reify the topic map."
32
+ assert_kind_of RTM::Topic, m.reifier, "A reifier should be a Topic."
33
+
34
+ assert_equal m, m.topics.first.reified, "The only topic out there should reify the map (not generally, but here)."
35
+ assert_equal m.base_locator, m.topics.first.reified.base_locator, "The only topic out there should reify the map. Check base locator."
36
+ assert_equal m.__getobj__, m.topics.first.reified.__getobj__, "The only topic out there should reify the map. Look inside."
37
+
38
+ t = m.create_topic
39
+ assert_equal 2, m.topics.size, "There should be 2 topics after creating the second one."
40
+ assert_kind_of RTM::Topic, t, "The created topic should really be one."
41
+ assert_kind_of RTM::TopicMap, m
42
+ assert_equal m, t.parent, "The Topic Map should be the parent of our new topic."
43
+ # The next tests may look a bit unneeded, but they at least also test the properties be available and initialized somehow.
44
+ assert_equal 0, t.item_identifiers.size, "New topic has no item_identifiers."
45
+ assert_equal 0, t.subject_identifiers.size, "New topic has no subject_identifiers."
46
+ assert_equal 0, t.subject_locators.size, "New topic has no subject_locators."
47
+ assert !t.valid?, "Without item identifiers nor subject identifiers the topic must not be valid."
48
+ assert_equal 0, t.names.size, "New topic has no names."
49
+ assert_equal 0, t.occurrences.size, "New topic has no occurrences."
50
+ assert_equal 0, t.roles_played.size, "New topic plays no roles."
51
+ assert_nil t.reified, "New topic does not reify a statement."
52
+
53
+ n = t.create_name
54
+ assert_equal 1, t.names.size, "The topic should have one name now."
55
+ assert_kind_of RTM::TopicName, n
56
+ assert_kind_of RTM::Topic, n.parent, "You won't believe but this should be a Topic and right now it not..."
57
+ # TODO the following assertion does not work - it crashes pp... but why?
58
+ #assert_equal t, n.parent, "The parent of the name should be the topic on which it was created."
59
+ assert_equal 0, n.item_identifiers.size, "I wonder if someone will ever read that."
60
+ assert_kind_of RTM::TopicName, n, "The topic name shoud be a TopicName... makes sence, he?"
61
+ assert_equal 0, n.variants.size, "According to Lars Heuer and Robert Barta that should always be 0, not only now."
62
+ assert_nil n.value, "We haven't set a value yet, where should it come from."
63
+ assert_nil n.type, "I am really tired of writing this stuff."
64
+ assert_equal 0, n.scope.size, "Should I really be more serious with this stuff?"
65
+ assert_nil n.reifier, "No, I guess not... who could ever stand that."
66
+
67
+ v = n.create_variant
68
+ assert_equal 1, n.variants.size, "The topic should have one name now."
69
+ assert_kind_of RTM::Variant, v
70
+ assert_kind_of RTM::TopicName, v.parent, "You won't believe but this should be a Topic and right now it not..."
71
+ # TODO the following assertion does not work - it crashes pp... but why?
72
+ #assert_equal t, v.parent, "The parent of the name should be the topic on which it was created."
73
+ assert_equal 0, v.item_identifiers.size, "I wonder if someone will ever read that."
74
+ assert_kind_of RTM::Variant, v, "The variant should be a Variant... makes sence, he?"
75
+ assert_nil v.value, "We haven't set a value yet, where should it come from."
76
+ assert_nil v.datatype, "No datatype set, yet."
77
+ assert_equal 0, v.scope.size, "Should I really be more serious with this stuff?"
78
+ assert_nil v.reifier, "No, I guess not... who could ever stand that."
79
+ assert !v.valid?
80
+
81
+ o = t.create_occurrence
82
+ assert_equal 1, t.occurrences.size, "The topic should have one name now."
83
+ assert_kind_of RTM::Occurrence, o
84
+ assert_kind_of RTM::Topic, o.parent, "You won't believe but this should be a Topic and right now it not..."
85
+ # TODO the following assertion does not work - it crashes pp... but why?
86
+ #assert_equal t, o.parent, "The parent of the name should be the topic on which it was created."
87
+ assert_equal 0, o.item_identifiers.size, "I wonder if someone will ever read that."
88
+ assert_kind_of RTM::Occurrence, o, "The occurrence shoud be a Occurrence... makes sence, he?"
89
+ assert_nil o.value, "We haven't set a value yet, where should it come from."
90
+ assert_nil o.type, "I am really tired of writing this stuff."
91
+ assert_nil o.datatype
92
+ assert_equal 0, n.scope.size, "Should I really be more serious with this stuff?"
93
+ assert_nil n.reifier, "No, I guess not... who could ever stand that."
94
+
95
+ a = m.create_association
96
+ assert_nil a.type
97
+ assert_equal 0, a.roles.size
98
+ assert_kind_of RTM::Association, a
99
+ assert_kind_of RTM::TopicMap, a.parent
100
+ assert_equal m, a.parent
101
+ assert_equal 0, a.scope.size
102
+ assert !a.valid?
103
+
104
+ r1 = a.create_role
105
+ assert_nil r1.type
106
+ assert_nil r1.player
107
+ assert_kind_of RTM::AssociationRole, r1
108
+ assert_kind_of RTM::Association, r1.parent
109
+ assert_equal 1, a.roles.size
110
+
111
+
112
+ t.item_identifiers << "nr1"
113
+ assert_equal 1, t.item_identifiers.size
114
+ fii = t.item_identifiers.first
115
+ assert_equal "http://rtm.rubyforge.org/tests/base_test#nr1", fii.to_s
116
+ assert_kind_of RTM::Locator, fii
117
+ assert_kind_of RTM::ItemIdentifier, fii #needed?
118
+ # TODO: invalidate cache/reload value somehow
119
+ #assert_equal 1, m.item_identifiers.size, "If you see this, it is probably because TopicMap#item_identifiers.size is cached which is wrong in this case."
120
+
121
+ t.subject_identifiers << "si1"
122
+ fsi = t.subject_identifiers.first
123
+ assert_equal "si1", fsi.to_s
124
+ assert_kind_of RTM::Locator, fsi
125
+ assert_kind_of RTM::SubjectIdentifier, fsi #needed?
126
+
127
+ t.subject_locators << "sl1"
128
+ fsl = t.subject_locators.first
129
+ assert_equal "sl1", fsl.to_s
130
+ assert_kind_of RTM::Locator, fsl
131
+ assert_kind_of RTM::SubjectLocator, fsl #needed?
132
+
133
+ # create roles with topics
134
+ # some more stuff.
135
+
136
+
137
+ # to be in associations_test later:
138
+ tm = RTM.create "urn:/associations_test"
139
+ a1 = tm.create_association "urn:/assoc_type_with_absolute_uri"
140
+ assert_not_nil a1.type
141
+ assert_equal a1.type, tm.get("urn:/assoc_type_with_absolute_uri")
142
+
143
+ a2 = tm.create_association :type => "urn:/assoc_type_with_absolute_uri_using_hash"
144
+ assert_not_nil a2.type
145
+ assert_equal a2.type, tm.get("urn:/assoc_type_with_absolute_uri_using_hash")
146
+
147
+ a3 = tm.create_association "relative_type"
148
+ assert_not_nil a3.type
149
+ assert_equal a3.type, tm.get("relative_type")
150
+
151
+
152
+ end
153
+ end