rtm 0.1.1 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/activetopicmaps.rb +55 -6
- data/lib/rtm.rb +27 -8
- data/lib/rtm/backend/active_record.rb +29 -24
- data/lib/rtm/backend/active_record/association_and_role.rb +3 -24
- data/lib/rtm/backend/active_record/locators.rb +2 -0
- data/lib/rtm/backend/active_record/name_variant_occurrence.rb +5 -4
- data/lib/rtm/backend/active_record/tm_delegator.rb +0 -75
- data/lib/rtm/backend/active_record/tmdm.rb +5 -0
- data/lib/rtm/backend/active_record/topic.rb +10 -76
- data/lib/rtm/backend/active_record/topic_map.rb +30 -1
- data/lib/rtm/backend/active_record/traverse_associations.rb +86 -0
- data/lib/rtm/io/from_xtm2_libxml.rb +1 -1
- data/lib/rtm/locator_helpers.rb +16 -0
- data/lib/rtm/sugar/role/counterparts.rb +51 -0
- data/lib/rtm/sugar/topic/characteristics.rb +15 -0
- data/lib/rtm/sugar/topic/counterparts.rb +15 -0
- data/lib/rtm/sugar/topic/hash_access.rb +55 -0
- data/lib/rtm/sugar/topic/identifier_direct.rb +11 -0
- data/lib/rtm/sugar/topic/predefined_associations.rb +42 -0
- data/test/base_test.rb +153 -0
- metadata +84 -67
- data/lib/rtm/io/from_xtm2_jaxp.rb +0 -89
@@ -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/")
|
data/lib/rtm/locator_helpers.rb
CHANGED
@@ -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,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
|