rtm-activerecord 0.2.0
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.
- data/DISCLAIMER +13 -0
- data/LICENSE +201 -0
- data/README +4 -0
- data/lib/rtm/activerecord/001_initial_schema.rb +119 -0
- data/lib/rtm/activerecord/association_and_role.rb +54 -0
- data/lib/rtm/activerecord/base.rb +83 -0
- data/lib/rtm/activerecord/connect.rb +106 -0
- data/lib/rtm/activerecord/io/from_xtm2.rb +266 -0
- data/lib/rtm/activerecord/io/from_xtm2_libxml.rb +97 -0
- data/lib/rtm/activerecord/io/to_jtm.rb +141 -0
- data/lib/rtm/activerecord/io/to_string.rb +130 -0
- data/lib/rtm/activerecord/io/to_xtm1.rb +162 -0
- data/lib/rtm/activerecord/io/to_xtm2.rb +163 -0
- data/lib/rtm/activerecord/io/to_yaml.rb +132 -0
- data/lib/rtm/activerecord/literal_index.rb +38 -0
- data/lib/rtm/activerecord/locators.rb +58 -0
- data/lib/rtm/activerecord/merging.rb +310 -0
- data/lib/rtm/activerecord/name_variant_occurrence.rb +86 -0
- data/lib/rtm/activerecord/persistent_code_output.rb +22 -0
- data/lib/rtm/activerecord/quaaxtm2rtm.rb +116 -0
- data/lib/rtm/activerecord/quaaxtm2rtmviews.rb +137 -0
- data/lib/rtm/activerecord/set_wrapper.rb +101 -0
- data/lib/rtm/activerecord/sugar/association/hash_access.rb +22 -0
- data/lib/rtm/activerecord/sugar/role/counterparts.rb +56 -0
- data/lib/rtm/activerecord/sugar/topic/characteristics.rb +15 -0
- data/lib/rtm/activerecord/sugar/topic/counterparts.rb +18 -0
- data/lib/rtm/activerecord/sugar/topic/hash_access.rb +78 -0
- data/lib/rtm/activerecord/sugar/topic/identifier_direct.rb +14 -0
- data/lib/rtm/activerecord/sugar/topic/predefined_associations.rb +53 -0
- data/lib/rtm/activerecord/tm_construct.rb +66 -0
- data/lib/rtm/activerecord/tm_delegator.rb +417 -0
- data/lib/rtm/activerecord/tm_set_delegator.rb +226 -0
- data/lib/rtm/activerecord/tmdm.rb +309 -0
- data/lib/rtm/activerecord/topic.rb +204 -0
- data/lib/rtm/activerecord/topic_map.rb +435 -0
- data/lib/rtm/activerecord/traverse_associations.rb +90 -0
- data/lib/rtm/activerecord.rb +106 -0
- metadata +120 -0
@@ -0,0 +1,226 @@
|
|
1
|
+
# Copyright: Copyright 2009 Topic Maps Lab, University of Leipzig.
|
2
|
+
# License: Apache License, Version 2.0
|
3
|
+
|
4
|
+
module RTM::AR
|
5
|
+
class TMSetDelegator < TMDelegator
|
6
|
+
include Enumerable
|
7
|
+
# attr_reader :content_class_name
|
8
|
+
def initialize(obj,parent,type)
|
9
|
+
@obj = obj
|
10
|
+
@parent = parent
|
11
|
+
@type = type
|
12
|
+
end
|
13
|
+
|
14
|
+
# This class method wraps a Set completely while the instance method wraps one single contained object
|
15
|
+
def self.wrap(obj, parent=nil, type=nil)
|
16
|
+
return nil unless obj
|
17
|
+
raise "Double wrapping" if obj.respond_to?(:__getobj__)
|
18
|
+
self.new(obj, parent, type)
|
19
|
+
end
|
20
|
+
|
21
|
+
def add(obj)
|
22
|
+
return unless obj
|
23
|
+
|
24
|
+
old = @obj.detect { |x| x == obj } # can't that be done easier?
|
25
|
+
if old
|
26
|
+
old.merge obj
|
27
|
+
else
|
28
|
+
if obj.respond_to? :__getobj__
|
29
|
+
@obj << obj.__getobj__
|
30
|
+
else
|
31
|
+
case @type
|
32
|
+
when :Topic
|
33
|
+
@obj << @parent.topic_map.get!(obj).__getobj__
|
34
|
+
@parent.__getobj__.reload
|
35
|
+
|
36
|
+
when :ItemIdentifier
|
37
|
+
if @parent.class.name.to_s =~ /::Topic$/
|
38
|
+
tbi = @parent.topic_map._item_identifier(obj)
|
39
|
+
if tbi && tmc=tbi.topic_map_construct
|
40
|
+
if tmc.class.name =~ /::Topic$/
|
41
|
+
return @parent if tmc == @parent.__getobj__
|
42
|
+
result = Topic.wrap(tmc).merge @parent
|
43
|
+
return result
|
44
|
+
else
|
45
|
+
raise "Duplicate Item Identifier"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
tbsi = @parent.topic_map._subject_identifier(obj.to_s)
|
49
|
+
if tbsi
|
50
|
+
if t=tbsi.topic
|
51
|
+
return @parent if t == @parent.__getobj__
|
52
|
+
result = Topic.wrap(t).merge @parent
|
53
|
+
# after merging, we still need to add the II
|
54
|
+
result.__getobj__.item_identifiers.create(:reference => obj.to_s, :topic_map_id => @parent.topic_map.__getobj__.id)
|
55
|
+
return result
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
result = @obj << @parent.topic_map._item_identifier!(obj.to_s)
|
60
|
+
return result
|
61
|
+
|
62
|
+
when :SubjectIdentifier
|
63
|
+
# check for existing item identifier
|
64
|
+
puts
|
65
|
+
puts "trying to add SI to a topic"
|
66
|
+
tbi = @parent.topic_map._item_identifier(obj)
|
67
|
+
if tbi && tmc=tbi.construct
|
68
|
+
puts "something with this II exists"
|
69
|
+
if tmc.class.name =~ /::Topic$/
|
70
|
+
puts "it exists as a topic"
|
71
|
+
puts tmc == @parent.__getobj__
|
72
|
+
return @parent if tmc == @parent.__getobj__
|
73
|
+
|
74
|
+
puts "trying to merge"
|
75
|
+
puts "BEFORE"
|
76
|
+
begin
|
77
|
+
result = Topic.wrap(tmc).merge(@parent)
|
78
|
+
rescue Exception => e
|
79
|
+
puts e.inspect
|
80
|
+
raise e
|
81
|
+
end
|
82
|
+
puts "AFTER"
|
83
|
+
puts "done merging, now adding SI"
|
84
|
+
|
85
|
+
#result = @parent.merge(Topic.wrap(tmc))
|
86
|
+
# after merging, we still need to add the SI
|
87
|
+
result.__getobj__.subject_identifiers.create(:reference => obj.to_s, :topic_map_id => @parent.topic_map.__getobj__.id)
|
88
|
+
puts "done adding SI, now reloading"
|
89
|
+
result.reload
|
90
|
+
puts "done reloading"
|
91
|
+
return result
|
92
|
+
else
|
93
|
+
warn("This subject identifier IRI already belongs to another topic map construct (not a topic)")
|
94
|
+
end
|
95
|
+
end
|
96
|
+
puts "checking for existing SI"
|
97
|
+
# check for existing subject identifier
|
98
|
+
tbsi = @parent.topic_map._subject_identifier(obj.to_s)
|
99
|
+
if tbsi
|
100
|
+
puts "SI exists"
|
101
|
+
if true && t=tbsi.topic #the single = is intentional, the "true &&" just makes netbeans not raise a warning
|
102
|
+
return @parent if t == @parent.__getobj__
|
103
|
+
result = Topic.wrap(t).merge @parent
|
104
|
+
return result
|
105
|
+
end
|
106
|
+
end
|
107
|
+
@obj.create(:reference => obj.to_s, :topic_map_id => @parent.topic_map.__getobj__.id)
|
108
|
+
|
109
|
+
when :SubjectLocator
|
110
|
+
tbsl = @parent.topic_map._subject_locator(obj.to_s)
|
111
|
+
if tbsl
|
112
|
+
if true && t=tbsl.topic #the single = is intentional, the "true &&" just makes netbeans not raise a warning
|
113
|
+
return @parent if t == @parent.__getobj__
|
114
|
+
result = Topic.wrap(t).merge @parent
|
115
|
+
return result
|
116
|
+
end
|
117
|
+
end
|
118
|
+
@obj.create(:reference => obj.to_s, :topic_map_id => @parent.topic_map.__getobj__.id)
|
119
|
+
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
alias :<< :add
|
125
|
+
|
126
|
+
def add_all(objs)
|
127
|
+
return unless objs
|
128
|
+
objs.each {|obj| add(obj)}
|
129
|
+
true
|
130
|
+
end
|
131
|
+
|
132
|
+
def each(&b)
|
133
|
+
@obj.each { |e| yield wrap(e)}
|
134
|
+
end
|
135
|
+
|
136
|
+
def size
|
137
|
+
@obj.size
|
138
|
+
end
|
139
|
+
alias :length :size
|
140
|
+
|
141
|
+
def empty?
|
142
|
+
@obj.empty?
|
143
|
+
end
|
144
|
+
|
145
|
+
def delete(obj)
|
146
|
+
obj = obj.__getobj__ if obj.respond_to? :__getobj__
|
147
|
+
case @type
|
148
|
+
when :ItemIdentifier, :SubjectIdentifier, :SubjectLocator
|
149
|
+
obj = @obj.find_by_reference(@parent.topic_map.resolve(obj.to_s)) if obj.is_a? String
|
150
|
+
when :Topic
|
151
|
+
obj = @parent.topic_map.get!(obj).__getobj__
|
152
|
+
end
|
153
|
+
@obj.delete(obj)
|
154
|
+
# item_identifiers: remove also from topicMap
|
155
|
+
#removed_event obj if respond_to? :removed_event
|
156
|
+
end
|
157
|
+
alias :remove :delete
|
158
|
+
|
159
|
+
def include?(obj)
|
160
|
+
return @obj.include?(obj.__getobj__)
|
161
|
+
#@obj.each { |e| return true if e == obj } # T#ODO support for get
|
162
|
+
#false
|
163
|
+
end
|
164
|
+
|
165
|
+
def first
|
166
|
+
wrap(@obj.entries.first)
|
167
|
+
end
|
168
|
+
def last
|
169
|
+
wrap(@obj.entries.last)
|
170
|
+
end
|
171
|
+
|
172
|
+
def to_s
|
173
|
+
"[#{@obj.entries.map { |e| wrap(e).to_s }.join(", ") }]"
|
174
|
+
end
|
175
|
+
def [](i)
|
176
|
+
wrap(@obj[i])
|
177
|
+
end
|
178
|
+
|
179
|
+
def content_class
|
180
|
+
# @content_class ||= RTM.const_get(@content_class_name)
|
181
|
+
@content_class ||= RTM.const_get("#{@content_class_name}MemImpl")
|
182
|
+
end
|
183
|
+
|
184
|
+
def find(*args)
|
185
|
+
res = @obj.find(*args)
|
186
|
+
if res.respond_to? :each
|
187
|
+
Constructs.wrap(res)
|
188
|
+
else
|
189
|
+
Construct.wrap(res)
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
def &(other)
|
194
|
+
@obj.to_a & other.to_a
|
195
|
+
end
|
196
|
+
|
197
|
+
alias :old_method_missing :method_missing
|
198
|
+
def method_missing(method_name, *args)
|
199
|
+
if @obj.size > 0 && first.respond_to?(method_name) && (![:__getobj__, :__setobj__].include?(method_name))
|
200
|
+
a = []
|
201
|
+
inject(a) {|all,single| all << single.send(method_name, *args)}
|
202
|
+
a
|
203
|
+
else
|
204
|
+
old_method_missing(method_name, *args)
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
alias :old_respond_to? :respond_to?
|
209
|
+
def respond_to?(method_name)
|
210
|
+
resp = old_respond_to?(method_name)
|
211
|
+
return resp if resp # i.e. if true
|
212
|
+
return false if [:__getobj__, :__setobj__].include?(method_name)
|
213
|
+
# ... and ask first child otherwise
|
214
|
+
@obj.size > 0 && first.respond_to?(method_name)
|
215
|
+
end
|
216
|
+
|
217
|
+
def ==(x)
|
218
|
+
self.to_a == x.to_a
|
219
|
+
end
|
220
|
+
|
221
|
+
# TMSetDelegator#to_a doesn't help as thought, but maybe we come back to that l8r...
|
222
|
+
#def to_a
|
223
|
+
# @obj.map {|o| wrap(o)}
|
224
|
+
#end
|
225
|
+
end
|
226
|
+
end
|
@@ -0,0 +1,309 @@
|
|
1
|
+
# Copyright: Copyright 2009 Topic Maps Lab, University of Leipzig.
|
2
|
+
# License: Apache License, Version 2.0
|
3
|
+
|
4
|
+
old_verbose=$VERBOSE
|
5
|
+
$VERBOSE=false
|
6
|
+
require 'active_record'
|
7
|
+
$VERBOSE=old_verbose
|
8
|
+
|
9
|
+
module RTM::AR
|
10
|
+
# The Active Record TMDM backend
|
11
|
+
module TMDM
|
12
|
+
# Moves all fields in a collection to another owner (for classes using belongs_to in AR::Base class)
|
13
|
+
module Movable
|
14
|
+
# Takes a list of [field,from, to] arguments.
|
15
|
+
# RTM::AR::TMDM::ItemIdentifier.move_all(
|
16
|
+
# ["construct_id", other.__getobj__.id, self.__getobj__.id],
|
17
|
+
# ["construct_type", other.__getobj__.class.name, self.__getobj__.class.name]
|
18
|
+
# )
|
19
|
+
# or
|
20
|
+
# RTM::AR::TMDM::Variant.move_all(["name_id", other.__getobj__.id, self.__getobj__.id])
|
21
|
+
|
22
|
+
#
|
23
|
+
def move_all(*args)
|
24
|
+
raise "All parameters must have a size of 3: [field_name, from, to]" unless args.all?{|a| a.size == 3}
|
25
|
+
set_part = ""
|
26
|
+
where_part = ""
|
27
|
+
args.each do |field, from, to|
|
28
|
+
set_part += ", " unless set_part.empty?
|
29
|
+
where_part += " and " unless where_part.empty?
|
30
|
+
from = "'#{from}'" unless from.is_a? Numeric
|
31
|
+
to = "'#{to}'" unless to.is_a? Numeric
|
32
|
+
where_part += "#{field} = #{from}"
|
33
|
+
set_part += "#{field} = #{to}"
|
34
|
+
end
|
35
|
+
#puts "setpart: #{set_part.inspect}\nwherepart: #{where_part.inspect}"
|
36
|
+
res = self.update_all(set_part, where_part)
|
37
|
+
#puts "result: #{res.inspect}"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class Construct < ActiveRecord::Base
|
42
|
+
self.store_full_sti_class = false
|
43
|
+
extend Movable
|
44
|
+
class << self
|
45
|
+
def abstract_class?
|
46
|
+
self == Construct
|
47
|
+
end
|
48
|
+
def alias_ar_relation(new,old)
|
49
|
+
alias_method new, old
|
50
|
+
alias_method "#{new}=", "#{old}="
|
51
|
+
end
|
52
|
+
alias :alias_belongs_to :alias_ar_relation
|
53
|
+
alias :alias_has_many :alias_ar_relation
|
54
|
+
def belongs_to_with_alias(name, synonym)
|
55
|
+
belongs_to name
|
56
|
+
alias_belongs_to synonym, name
|
57
|
+
end
|
58
|
+
def has_many_with_alias(name, synonym, *args)
|
59
|
+
has_many name, *args
|
60
|
+
alias_has_many synonym, name
|
61
|
+
end
|
62
|
+
def belongs_to_parent(parent)
|
63
|
+
belongs_to parent
|
64
|
+
alias_belongs_to :parent, parent
|
65
|
+
end
|
66
|
+
def this_is_a_typed_object
|
67
|
+
belongs_to :ttype, :class_name => "Topic", :foreign_key => :ttype_id
|
68
|
+
module_eval(<<-EOS, "(__RTM_AR_TMDM_TYPED_OBJECT__)", 1)
|
69
|
+
def type=(ptype)
|
70
|
+
self.ttype=ptype
|
71
|
+
end
|
72
|
+
def type
|
73
|
+
self.ttype
|
74
|
+
end
|
75
|
+
EOS
|
76
|
+
end
|
77
|
+
end
|
78
|
+
has_many :item_identifiers, :as => :construct, :dependent => :destroy
|
79
|
+
def topic_map
|
80
|
+
parent.topic_map
|
81
|
+
end
|
82
|
+
def move_to(new_parent)
|
83
|
+
self.parent = new_parent
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
class Reifiable < Construct
|
88
|
+
def self.abstract_class?
|
89
|
+
self == Reifiable
|
90
|
+
end
|
91
|
+
has_one :reifier, :class_name => "Topic", :as => :reified
|
92
|
+
end
|
93
|
+
class ScopedObject < Reifiable
|
94
|
+
def self.abstract_class?
|
95
|
+
self == ScopedObject
|
96
|
+
end
|
97
|
+
has_many :scoped_objects_topics, :as => :scoped_object, :dependent => :destroy
|
98
|
+
has_many :scope, :through => :scoped_objects_topics, :source => :topic
|
99
|
+
# def scope
|
100
|
+
# self.scoped_objects_topics.map { |sot| sot.topic }
|
101
|
+
# end
|
102
|
+
# def add_scoping_topic(topic) # this is not ruby-ish but at least it works, would need a complete association proxy instead...
|
103
|
+
# sot = ScopedObjectsTopic.create :topic => topic, :scoped_object => self
|
104
|
+
# self
|
105
|
+
# # sot = ScopedObjectsTopic.new :topic => topic, :scoped_object => self
|
106
|
+
# # self.scoped_objects_topics << sot
|
107
|
+
# # self
|
108
|
+
# end
|
109
|
+
# def remove_scoping_topic(topic) # this is not ruby-ish but at least it works, would need a complete association proxy instead...
|
110
|
+
# self.scoped_objects_topics.select { |sot| sot.topic == topic }.destroy
|
111
|
+
# self
|
112
|
+
# end
|
113
|
+
end
|
114
|
+
class ScopedObjectsTopic < ActiveRecord::Base
|
115
|
+
self.store_full_sti_class = false
|
116
|
+
extend Movable
|
117
|
+
belongs_to :topic, :class_name => 'RTM::AR::TMDM::Topic'
|
118
|
+
belongs_to :scoped_object, :polymorphic => true
|
119
|
+
belongs_to :association, :class_name => 'RTM::AR::TMDM::Association', :foreign_key => "scoped_object_id"
|
120
|
+
belongs_to :name, :class_name => 'RTM::AR::TMDM::Name', :foreign_key => "scoped_object_id"
|
121
|
+
belongs_to :variant, :class_name => 'RTM::AR::TMDM::Variant', :foreign_key => "scoped_object_id"
|
122
|
+
belongs_to :occurrence, :class_name => 'RTM::AR::TMDM::Occurrence', :foreign_key => "scoped_object_id"
|
123
|
+
end
|
124
|
+
|
125
|
+
class Locator < ActiveRecord::Base
|
126
|
+
self.store_full_sti_class = false
|
127
|
+
extend Movable
|
128
|
+
class << self
|
129
|
+
def abstract_class?
|
130
|
+
self == Locator
|
131
|
+
end
|
132
|
+
end
|
133
|
+
belongs_to :topic_map
|
134
|
+
end
|
135
|
+
|
136
|
+
class ItemIdentifier < Locator
|
137
|
+
belongs_to :construct, :polymorphic => true
|
138
|
+
def to_s
|
139
|
+
self.reference
|
140
|
+
end
|
141
|
+
def move_to(new_tmc)
|
142
|
+
#puts "\n\nmoving\n\t#{self.inspect}\n\nto\n\t#{new_tmc.inspect}"
|
143
|
+
#self.update_all "construct_id = #{new_tmc.id}, construct_type = '#{new_tmc.class.name}'",
|
144
|
+
#puts "changing id"
|
145
|
+
#puts self.construct_id = new_tmc.id
|
146
|
+
#puts "changing type"
|
147
|
+
#puts self.construct_type = new_tmc.class.name
|
148
|
+
self.construct = new_tmc
|
149
|
+
#puts "saving"
|
150
|
+
self.save
|
151
|
+
#
|
152
|
+
# das geht!!!
|
153
|
+
#self.class.update( self.id, "construct_id" => new_tmc.id)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
class SubjectLocator < Locator
|
157
|
+
belongs_to :topic
|
158
|
+
def to_s
|
159
|
+
self.reference
|
160
|
+
end
|
161
|
+
end
|
162
|
+
class SubjectIdentifier < Locator
|
163
|
+
belongs_to :topic
|
164
|
+
def to_s
|
165
|
+
self.reference
|
166
|
+
end
|
167
|
+
end
|
168
|
+
# http://www.isotopicmaps.org/sam/sam-model/#d0e736
|
169
|
+
class Topic < Construct
|
170
|
+
belongs_to :reified, :polymorphic => true
|
171
|
+
belongs_to_parent :topic_map
|
172
|
+
has_many :subject_locators, :dependent => :destroy
|
173
|
+
has_many :subject_identifiers, :dependent => :destroy
|
174
|
+
has_many :occurrences, :dependent => :destroy
|
175
|
+
has_many_with_alias :names, :topic_names, :dependent => :destroy
|
176
|
+
has_many_with_alias :roles, :association_roles, :include => :association
|
177
|
+
has_many :associations, :through => :roles, :dependent => :destroy
|
178
|
+
#has_many :played_types, :through => :association_roles, :source => :type
|
179
|
+
|
180
|
+
has_many :typed_associations, :class_name => "Association", :foreign_key => :ttype_id
|
181
|
+
has_many :typed_roles, :class_name => "Role", :foreign_key => :ttype_id
|
182
|
+
has_many :typed_names, :class_name => "Name", :foreign_key => :ttype_id
|
183
|
+
has_many :typed_occurrences, :class_name => "Occurrence", :foreign_key => :ttype_id
|
184
|
+
|
185
|
+
has_many :scoped_objects_topics
|
186
|
+
has_many :scoped_associations, :through => :scoped_objects_topics, :source => :association,
|
187
|
+
:conditions => "scoped_objects_topics.scoped_object_type = 'RTM::AR::TMDM::Association'"
|
188
|
+
has_many :scoped_names, :through => :scoped_objects_topics, :source => :name,
|
189
|
+
:conditions => "scoped_objects_topics.scoped_object_type = 'RTM::AR::TMDM::Name'"
|
190
|
+
has_many :scoped_variants, :through => :scoped_objects_topics, :source => :variant,
|
191
|
+
:conditions => "scoped_objects_topics.scoped_object_type = 'RTM::AR::TMDM::Variant'"
|
192
|
+
has_many :scoped_occurrences, :through => :scoped_objects_topics, :source => :occurrence,
|
193
|
+
:conditions => "scoped_objects_topics.scoped_object_type = 'RTM::AR::TMDM::Occurrence'"
|
194
|
+
|
195
|
+
# def scoped_objects
|
196
|
+
# self.scoped_objects_topics.collect { |a| a.scoped_object } # temporary hack polymorphic has_many_through
|
197
|
+
# end
|
198
|
+
def scoped
|
199
|
+
scoped_associations + scoped_names + scoped_variants + scoped_occurrences
|
200
|
+
end
|
201
|
+
|
202
|
+
def typed
|
203
|
+
typed_associations + typed_roles + typed_names + typed_occurrences
|
204
|
+
end
|
205
|
+
|
206
|
+
end
|
207
|
+
|
208
|
+
class Role < Reifiable
|
209
|
+
belongs_to_parent :association
|
210
|
+
belongs_to_with_alias :topic, :player
|
211
|
+
this_is_a_typed_object
|
212
|
+
end
|
213
|
+
|
214
|
+
class Name < ScopedObject
|
215
|
+
belongs_to_parent :topic
|
216
|
+
this_is_a_typed_object
|
217
|
+
has_many :variants, :dependent => :destroy
|
218
|
+
end
|
219
|
+
|
220
|
+
class Association < ScopedObject
|
221
|
+
belongs_to_parent :topic_map
|
222
|
+
this_is_a_typed_object
|
223
|
+
has_many_with_alias :roles, :roles, :dependent => :destroy
|
224
|
+
def create_role(rplayer, ttype)
|
225
|
+
Role.create :parent => self, :player => rplayer, :ttype => ttype
|
226
|
+
end
|
227
|
+
alias :create_association_role :create_role
|
228
|
+
has_many :players, :through => :roles, :source => :topic
|
229
|
+
has_many :types, :through => :roles, :source => :ttype
|
230
|
+
end
|
231
|
+
|
232
|
+
class AssociationCache < Construct
|
233
|
+
set_table_name "associations_cache"
|
234
|
+
belongs_to_parent :topic_map
|
235
|
+
this_is_a_typed_object
|
236
|
+
has_many_with_alias :roles, :association_roles
|
237
|
+
belongs_to :role1, :class_name => "RTM::AR::TMDM::Role", :foreign_key => "role1_id"
|
238
|
+
belongs_to :player1, :class_name => "RTM::AR::TMDM::Topic", :foreign_key => "player1_id"
|
239
|
+
belongs_to :type1, :class_name => "RTM::AR::TMDM::Topic", :foreign_key => "type1_id"
|
240
|
+
belongs_to :role2, :class_name => "RTM::AR::TMDM::Role", :foreign_key => "role2_id"
|
241
|
+
belongs_to :player2, :class_name => "RTM::AR::TMDM::Topic", :foreign_key => "player2_id"
|
242
|
+
belongs_to :type2, :class_name => "RTM::AR::TMDM::Topic", :foreign_key => "type2_id"
|
243
|
+
# rolecount -> rcnt
|
244
|
+
end
|
245
|
+
|
246
|
+
class Occurrence < ScopedObject
|
247
|
+
belongs_to_parent :topic
|
248
|
+
this_is_a_typed_object
|
249
|
+
end
|
250
|
+
|
251
|
+
class Variant < ScopedObject
|
252
|
+
belongs_to_parent :name
|
253
|
+
def topic_map
|
254
|
+
parent.topic_map
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
class TopicMap < Reifiable
|
259
|
+
# real properties
|
260
|
+
has_many :topics, :dependent => :destroy, :include => [:subject_identifiers, :subject_locators]
|
261
|
+
has_many :associations, :dependent => :destroy, :include => :roles
|
262
|
+
|
263
|
+
# access to subproperties
|
264
|
+
has_many :locators, :class_name => "ItemIdentifier", :dependent => :destroy
|
265
|
+
has_many :subject_locators, :dependent => :destroy
|
266
|
+
has_many :subject_identifiers, :dependent => :destroy
|
267
|
+
|
268
|
+
has_many :names, :through => :topics
|
269
|
+
alias :topic_names :names
|
270
|
+
|
271
|
+
has_many :occurrences, :through => :topics
|
272
|
+
has_many :roles, :through => :associations
|
273
|
+
alias :association_roles :roles
|
274
|
+
|
275
|
+
%w[association role name occurrence].each do |m|
|
276
|
+
module_eval(<<-EOS, "(__AR_DELEGATOR_INDEX_PROPERTY_SET__)", 1)
|
277
|
+
def #{m}_types
|
278
|
+
topics.select{|t| t.#{m}s_typed.size > 0}
|
279
|
+
end
|
280
|
+
EOS
|
281
|
+
end
|
282
|
+
|
283
|
+
#typing
|
284
|
+
# has_many :association_types, :class_name => "Association", :foreign_key => :ttype_id
|
285
|
+
# has_many :role_types, :class_name => "Role", :foreign_key => :ttype_id
|
286
|
+
# has_many :name_types, :class_name => "Name", :foreign_key => :ttype_id
|
287
|
+
# has_many :occurrence_types, :class_name => "Occurrence", :foreign_key => :ttype_id
|
288
|
+
|
289
|
+
# has_many :association_types, :aka => :at, :type => :Topic, :wrap => true
|
290
|
+
# has_many :role_types, :aka => [:association_role_types,:art,:rt], :type => :Topic, :wrap => true
|
291
|
+
# has_many :name_types, :aka => [:name_types,:tnt,:nt], :type => :Topic, :wrap => true
|
292
|
+
# has_many :occurrence_types, :aka => :ot, :type => :Topic, :wrap => true
|
293
|
+
|
294
|
+
|
295
|
+
def topic_map
|
296
|
+
self
|
297
|
+
end
|
298
|
+
|
299
|
+
# # Creates a new Locator in this TopicMap
|
300
|
+
# def create_locator(reference, notation=nil)
|
301
|
+
# if notation
|
302
|
+
# ItemIdentifier.create :reference => reference, :notation => notation
|
303
|
+
# else
|
304
|
+
# ItemIdentifier.create :reference => reference # is there a better way to preserve the database default notation if none given?
|
305
|
+
# end
|
306
|
+
# end
|
307
|
+
end
|
308
|
+
end
|
309
|
+
end
|