rtm 0.1.1 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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