rtm 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/activetopicmaps.rb +229 -0
- data/lib/rtm/backend/active_record/association_and_role.rb +54 -0
- data/lib/rtm/backend/active_record/locators.rb +53 -0
- data/lib/rtm/backend/active_record/name_variant_occurrence.rb +44 -0
- data/lib/rtm/backend/active_record/quaaxtm2rtm.rb +113 -0
- data/lib/rtm/backend/active_record/quaaxtm2rtmviews.rb +134 -0
- data/lib/rtm/backend/active_record/set_wrapper.rb +98 -0
- data/lib/rtm/backend/active_record/tm_construct.rb +62 -0
- data/lib/rtm/backend/active_record/tm_delegator.rb +420 -0
- data/lib/rtm/backend/active_record/tm_set_delegator.rb +195 -0
- data/lib/rtm/backend/active_record/tmdm.rb +0 -1
- data/lib/rtm/backend/active_record/topic.rb +153 -0
- data/lib/rtm/backend/active_record/topic_map.rb +285 -0
- data/lib/rtm/backend/active_record.rb +9 -1350
- data/lib/rtm/io/to_jtm.rb +5 -1
- metadata +74 -68
@@ -0,0 +1,98 @@
|
|
1
|
+
module RTM::AR
|
2
|
+
class Topics < TMSetDelegator
|
3
|
+
def wrap(obj)
|
4
|
+
Topic.wrap(obj)
|
5
|
+
end
|
6
|
+
end
|
7
|
+
class TopicMapConstructs < TMSetDelegator
|
8
|
+
def wrap(obj)
|
9
|
+
TopicMapConstruct.wrap(obj)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
class Associations < TMSetDelegator
|
13
|
+
def wrap(obj)
|
14
|
+
Association.wrap(obj)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
class TopicNames < TMSetDelegator
|
18
|
+
def wrap(obj)
|
19
|
+
TopicName.wrap(obj)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
class Occurrences < TMSetDelegator
|
23
|
+
def wrap(obj)
|
24
|
+
Occurrence.wrap(obj)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
class AssociationRoles < TMSetDelegator
|
28
|
+
def wrap(obj)
|
29
|
+
AssociationRole.wrap(obj)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
class Reifiables < TMSetDelegator
|
33
|
+
def wrap(obj)
|
34
|
+
TopicMapConstruct.wrap(obj)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
class Variants < TMSetDelegator
|
38
|
+
def wrap(obj)
|
39
|
+
Variant.wrap(obj)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
class TopicMaps < TMSetDelegator
|
43
|
+
def [](obj)
|
44
|
+
# support for getting topic_map by base_locator
|
45
|
+
if obj.is_a? String
|
46
|
+
# return wrap(__getobj__.find { |tm| tm.base_locator == obj })
|
47
|
+
return wrap(TMDM::TopicMap.find_by_base_locator(obj))
|
48
|
+
end
|
49
|
+
# normal index retrieval
|
50
|
+
super
|
51
|
+
end
|
52
|
+
|
53
|
+
def wrap(obj)
|
54
|
+
TopicMap.wrap(obj)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
class Locators < TMSetDelegator
|
58
|
+
def [](obj)
|
59
|
+
# support for getting locators by reference
|
60
|
+
if obj.is_a? String
|
61
|
+
return wrap(__getobj__.find { |tm| tm.reference == obj })
|
62
|
+
end
|
63
|
+
# normal index retrieval
|
64
|
+
super
|
65
|
+
end
|
66
|
+
def wrap(obj)
|
67
|
+
return nil unless obj
|
68
|
+
return obj if obj.respond_to? :__getobj__
|
69
|
+
case obj.class.name
|
70
|
+
when "RTM::AR::TMDM::ItemIdentifier"
|
71
|
+
ItemIdentifier.wrap(obj)
|
72
|
+
when "RTM::AR::TMDM::SubjectIdentifier"
|
73
|
+
SubjectIdentifier.wrap(obj)
|
74
|
+
when "RTM::AR::TMDM::SubjectLocator"
|
75
|
+
SubjectLocator.wrap(obj)
|
76
|
+
else
|
77
|
+
Locator.wrap(obj)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
class ItemIdentifiers < Locators
|
83
|
+
def wrap(obj)
|
84
|
+
ItemIdentifier.wrap(obj)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
class SubjectIdentifiers < Locators
|
88
|
+
def wrap(obj)
|
89
|
+
SubjectIdentifier.wrap(obj)
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
class SubjectLocators < Locators
|
94
|
+
def wrap(obj)
|
95
|
+
SubjectLocator.wrap(obj)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module RTM::AR
|
2
|
+
class TopicMapConstruct < TMDelegator
|
3
|
+
include RTM::TopicMapConstruct
|
4
|
+
|
5
|
+
def self.abstract_class?
|
6
|
+
self == TopicMapConstruct
|
7
|
+
end
|
8
|
+
property_set :item_identifiers, :aka => [:ii, :iid, :source_locators], :type => :ItemIdentifier, :wrap => true,
|
9
|
+
#:create => :item_identifier, :create_aka => :cii
|
10
|
+
:add => true, :remove => true
|
11
|
+
|
12
|
+
delegate :remove, :to => :destroy
|
13
|
+
|
14
|
+
delegate :id
|
15
|
+
# property_parent :parent # mmh..
|
16
|
+
|
17
|
+
property :topic_map, :rw => true, :type => :TopicMap, :wrap => true
|
18
|
+
|
19
|
+
#class_delegate :create
|
20
|
+
|
21
|
+
def self.wrap(obj)
|
22
|
+
return nil unless obj
|
23
|
+
raise "Double wrapping" if obj.respond_to?(:__getobj__)
|
24
|
+
case obj.class.name
|
25
|
+
when "RTM::AR::TMDM::Topic"
|
26
|
+
Topic.wrap(obj)
|
27
|
+
when "RTM::AR::TMDM::Variant"
|
28
|
+
Variant.wrap(obj)
|
29
|
+
when "RTM::AR::TMDM::TopicName"
|
30
|
+
TopicName.wrap(obj)
|
31
|
+
when "RTM::AR::TMDM::Occurrence"
|
32
|
+
Occurrence.wrap(obj)
|
33
|
+
when "RTM::AR::TMDM::Association"
|
34
|
+
Association.wrap(obj)
|
35
|
+
when "RTM::AR::TMDM::AssociationRole"
|
36
|
+
AssociationRole.wrap(obj)
|
37
|
+
when "RTM::AR::TMDM::TopicMap"
|
38
|
+
TopicMap.wrap(obj)
|
39
|
+
else
|
40
|
+
raise "Can't wrap object. Class for wrapping #{obj.class} unknown (object: #{obj})"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.find(*args)
|
45
|
+
res = RTM::AR::TMDM.const_get(name.split("::").last).find(*args)
|
46
|
+
if res.respond_to? :each
|
47
|
+
TopicMapConstructs.wrap(res)
|
48
|
+
else
|
49
|
+
TopicMapConstruct.wrap(res)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
class Reifiable < TopicMapConstruct
|
55
|
+
include RTM::Reifiable
|
56
|
+
|
57
|
+
def self.abstract_class?
|
58
|
+
self == Reifiable
|
59
|
+
end
|
60
|
+
property :reifier, :type => :Topic, :rw => :true, :wrap => true
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,420 @@
|
|
1
|
+
module RTM::AR
|
2
|
+
class TMDelegator
|
3
|
+
def initialize(obj)
|
4
|
+
@obj = obj
|
5
|
+
end
|
6
|
+
|
7
|
+
def __getobj__
|
8
|
+
@obj
|
9
|
+
end
|
10
|
+
|
11
|
+
def __setobj__(obj)
|
12
|
+
@obj = obj
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.delegate(sym, options={})
|
16
|
+
to = options[:to] || sym
|
17
|
+
module_eval(<<-EOS, "(__TMDELEGATOR__)", 1)
|
18
|
+
def #{sym}(*args, &block)
|
19
|
+
__getobj__.send(:#{to}, *args, &block)
|
20
|
+
end
|
21
|
+
EOS
|
22
|
+
|
23
|
+
if options[:rw]
|
24
|
+
module_eval(<<-EOS, "(__TMDELEGATOR2__)", 1)
|
25
|
+
def #{sym}=(*args, &block)
|
26
|
+
__getobj__.send(:#{to}=, *args, &block)
|
27
|
+
#{options[:save] ? "__getobj__.save" : "" }
|
28
|
+
end
|
29
|
+
EOS
|
30
|
+
end
|
31
|
+
|
32
|
+
if options[:aka]
|
33
|
+
options[:aka] = [options[:aka]] unless options[:aka].respond_to? :each
|
34
|
+
options[:aka].each do |aka|
|
35
|
+
module_eval(<<-EOS, "(__TMDELEGATOR3__)", 1)
|
36
|
+
alias :#{aka} :#{sym}
|
37
|
+
EOS
|
38
|
+
|
39
|
+
if options[:rw]
|
40
|
+
module_eval(<<-EOS, "(__TMDELEGATOR3__)", 1)
|
41
|
+
alias :#{aka}= :#{sym}=
|
42
|
+
EOS
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.class_delegate(sym, options={})
|
49
|
+
module_eval(<<-EOS, "(__TMDELEGATOR__)", 1)
|
50
|
+
class << self
|
51
|
+
def #{sym}(*args, &block)
|
52
|
+
__getobj__.send(:#{sym}, *args, &block)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
EOS
|
56
|
+
|
57
|
+
if options[:aka]
|
58
|
+
options[:aka] = [options[:aka]] unless options[:aka].respond_to? :each
|
59
|
+
options[:aka].each do |aka|
|
60
|
+
module_eval(<<-EOS, "(__TMDELEGATOR2__)", 1)
|
61
|
+
class << self
|
62
|
+
alias :#{aka} :#{sym}
|
63
|
+
end
|
64
|
+
EOS
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.parent(sym, options={})
|
70
|
+
module_eval(<<-EOS, "(__TMDELEGATOR__)", 1)
|
71
|
+
def #{sym}
|
72
|
+
TopicMapConstruct.wrap(__getobj__.send(:#{sym}))
|
73
|
+
end
|
74
|
+
EOS
|
75
|
+
aka_property(sym, [:parent, :p])
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.property_set(prop, options={})
|
79
|
+
# puts "In #{self.name.to_s.ljust(20)} we have type #{options[:type].to_s.ljust(20)} for property #{prop}"
|
80
|
+
if options[:wrap]
|
81
|
+
#puts "#{self}: #{options[:type]}"
|
82
|
+
module_eval(<<-EOS, "(__AR_DELEGATOR_PROPERTY_SET_W__)", 1)
|
83
|
+
def #{prop}(*args)
|
84
|
+
if args.size == 0
|
85
|
+
# fetch normal
|
86
|
+
#{options[:type]}s.wrap(__getobj__.#{prop}, self, :#{options[:type]})
|
87
|
+
else
|
88
|
+
# fetch with filter
|
89
|
+
#puts args.inspect
|
90
|
+
# TODO enhance/fix condition transform code
|
91
|
+
a = {}.merge(args.first)
|
92
|
+
if a[:type] && !a[:ttype]
|
93
|
+
a[:ttype] = a[:type]
|
94
|
+
a.delete(:type)
|
95
|
+
end
|
96
|
+
a.each do |k,v|
|
97
|
+
if v.respond_to?(:__getobj__)
|
98
|
+
a[(k.to_s + "_id").to_sym] = v.id
|
99
|
+
end
|
100
|
+
end
|
101
|
+
#{options[:type]}s.wrap(__getobj__.#{prop}.find(:all, :conditions=> a), self, :#{options[:type]})
|
102
|
+
end
|
103
|
+
end
|
104
|
+
EOS
|
105
|
+
else
|
106
|
+
module_eval(<<-EOS, "(__AR_DELEGATOR_PROPERTY_SET_NW__)", 1)
|
107
|
+
def #{prop}
|
108
|
+
__getobj__.#{prop}
|
109
|
+
end
|
110
|
+
EOS
|
111
|
+
end
|
112
|
+
|
113
|
+
if options[:create]
|
114
|
+
# some :create_args:
|
115
|
+
#
|
116
|
+
# create_locator reference:string
|
117
|
+
# [ :name => :reference, :type => :String]
|
118
|
+
#
|
119
|
+
# create_topic_name value:String, scope:Collection
|
120
|
+
# create_topic_name value:String, type: Topic, scope:Collection
|
121
|
+
# [ {:name => :value, :type => :String}, {:name => :type, :type => :Topic, :optional => true}, {:name => :scope, :type => :Collection} ]
|
122
|
+
#
|
123
|
+
# create_occurrence value:String, type: Topic, scope:Collection
|
124
|
+
# create_occurrence resource: Locator, type: Topic, scope:Collection
|
125
|
+
# [ {:name => :value, :type => [:String, :Locator]}, {:name => :type, :type => :Topic}, {:name => :scope, :type => :Collection} ]
|
126
|
+
#
|
127
|
+
# create_association_role player:topic, type: topic
|
128
|
+
# [ {:name => :player, :type => :Topic}, {:name => :type, :type => :Topic}]
|
129
|
+
#
|
130
|
+
# create_variant value:string, :scope:Collection
|
131
|
+
# create_variant resource:locator, :scope:Collection
|
132
|
+
# [ {:name => :value, :type => [:String, :Locator]}, {:name => :scope, :type => :Collection}]
|
133
|
+
|
134
|
+
module_eval(<<-EOS, "(__AR_DELEGATOR_PROPERTY_SET_CREATE__)", 1)
|
135
|
+
def create_#{ options[:create]}(*args, &block)
|
136
|
+
arg_defs = #{ (options[:create_args] || nil ).inspect}
|
137
|
+
|
138
|
+
a = parse_args(args, arg_defs)
|
139
|
+
|
140
|
+
a = enhance_args_hash(a, arg_defs) if arg_defs
|
141
|
+
|
142
|
+
a = a.reject{|k,v| v.nil?}
|
143
|
+
|
144
|
+
# hack to change :type to :ttype for AR backend
|
145
|
+
# puts a.inspect unless a.is_a? Hash
|
146
|
+
if a[:type] && !a[:ttype]
|
147
|
+
a[:ttype] = a[:type]
|
148
|
+
a.delete(:type)
|
149
|
+
end
|
150
|
+
if [:Locator,:ItemIdentifier, :SubjectIdentifier, :SubjectLocator].include?(:#{options[:type]})
|
151
|
+
unless a[:topic_map]
|
152
|
+
a[:topic_map] = topic_map.__getobj__
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
if block_given?
|
157
|
+
obj = #{options[:type]}.wrap( __getobj__.#{options[:create]}s.new(a) )
|
158
|
+
yield obj
|
159
|
+
obj.save
|
160
|
+
else
|
161
|
+
obj = #{options[:type]}.wrap( __getobj__.#{options[:create]}s.create(a) )
|
162
|
+
end
|
163
|
+
obj
|
164
|
+
end
|
165
|
+
EOS
|
166
|
+
|
167
|
+
if options[:create_aka]
|
168
|
+
aka_property("create_#{options[:create]}", options[:create_aka])
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
if options[:add]
|
173
|
+
module_eval(<<-RUBY, "(__AR_DELEGATOR_PROPERTY_SET_ADD__)", 1)
|
174
|
+
def add_#{prop.to_s.singularize}(*args, &block)
|
175
|
+
#{prop}.add(*args, &block)
|
176
|
+
end
|
177
|
+
RUBY
|
178
|
+
aka_property("add_#{prop.to_s.singularize}", options[:aka].map{|a| "add_#{a}"})
|
179
|
+
aka_property("add_#{prop.to_s.singularize}", options[:aka].map{|a| "a#{a}"})
|
180
|
+
end
|
181
|
+
|
182
|
+
if options[:remove]
|
183
|
+
module_eval(<<-RUBY, "(__AR_DELEGATOR_PROPERTY_SET_REMOVE__)", 1)
|
184
|
+
def remove_#{prop.to_s.singularize}(*args, &block)
|
185
|
+
#{prop}.remove(*args, &block)
|
186
|
+
end
|
187
|
+
RUBY
|
188
|
+
aka_property("remove_#{prop.to_s.singularize}", options[:aka].map{|a| "remove_#{a}"})
|
189
|
+
aka_property("remove_#{prop.to_s.singularize}", options[:aka].map{|a| "r#{a}"})
|
190
|
+
end
|
191
|
+
|
192
|
+
# TODO: aliases for property_set.add as add_property
|
193
|
+
|
194
|
+
aka_property(prop, options[:aka]) if options[:aka]
|
195
|
+
end
|
196
|
+
|
197
|
+
private
|
198
|
+
def parse_args(args, arg_defs)
|
199
|
+
a = {}
|
200
|
+
a = args.pop if args.last.is_a? Hash
|
201
|
+
# We are finished if there are no more parameters or we have no arg_def.
|
202
|
+
# Special case: non optional parameters must have been in the Hash, just a hash is also allowed.
|
203
|
+
return a if args.size == 0 || arg_defs == nil
|
204
|
+
|
205
|
+
# we have some args
|
206
|
+
if args.size == arg_defs.size # all are given
|
207
|
+
return args2hash(a, args,arg_defs)
|
208
|
+
elsif args.size == arg_defs.reject { |d| d[:optional]}
|
209
|
+
return args2hash(a, args, arg_defs.reject {|d| d[:optional]})
|
210
|
+
end
|
211
|
+
#warn("Functions with more than one optional parameter are not supported. This will only work if the left out ones are the last.")
|
212
|
+
return args2hash(a, args,arg_defs)
|
213
|
+
end
|
214
|
+
|
215
|
+
def args2hash(a, args, arg_defs)
|
216
|
+
arg_defs.zip(args) do |argd,arg|
|
217
|
+
a[argd[:name]] = arg
|
218
|
+
end
|
219
|
+
|
220
|
+
return a
|
221
|
+
end
|
222
|
+
|
223
|
+
def enhance_args_hash(a, arg_defs)
|
224
|
+
#puts "enhance_args: #{a.inspect} ---\n#{arg_defs.inspect}"
|
225
|
+
return a if a.empty?
|
226
|
+
arg_defs.each do |argd|
|
227
|
+
#puts "enhancing #{argd[:name]}, which is a #{a[argd[:name]].class}"
|
228
|
+
if argd[:type] == :Topic
|
229
|
+
if a[argd[:name]].is_a? String
|
230
|
+
a[argd[:name]] = topic_map._topic_by_locator!(a[argd[:name]])
|
231
|
+
elsif a[argd[:name]].is_a?(RTM::Topic)
|
232
|
+
a[argd[:name]] = a[argd[:name]].__getobj__
|
233
|
+
end
|
234
|
+
end
|
235
|
+
if argd[:type] == :Locator || (argd[:type].respond_to?(:include?) && argd[:type].include?(:Locator))
|
236
|
+
a[argd[:name]] = a[argd[:name]].to_s
|
237
|
+
end
|
238
|
+
end
|
239
|
+
a
|
240
|
+
end
|
241
|
+
|
242
|
+
public
|
243
|
+
def self.property(prop, options={})
|
244
|
+
module_eval(<<-EOS, "(__AR_DELEGATOR_PROPERTY__)", 1)
|
245
|
+
def #{prop}
|
246
|
+
#{options[:wrap]? "#{options[:type]}.wrap":""}( __getobj__.#{prop})
|
247
|
+
end
|
248
|
+
EOS
|
249
|
+
|
250
|
+
if options[:rw]
|
251
|
+
case options[:type]
|
252
|
+
when :Topic
|
253
|
+
module_eval(<<-EOS, "(__AR_DELEGATOR_PROPERTY2__)", 1)
|
254
|
+
def #{prop}=(obj)
|
255
|
+
obj = topic_map.topic_by_locator!(obj) unless obj.is_a? #{options[:type]}
|
256
|
+
__getobj__.#{prop} = obj.__getobj__
|
257
|
+
__getobj__.save
|
258
|
+
end
|
259
|
+
EOS
|
260
|
+
when :TopicMap
|
261
|
+
module_eval(<<-EOS, "(__AR_DELEGATOR_PROPERTY2__)", 1)
|
262
|
+
def #{prop}=(obj)
|
263
|
+
obj = RTM.create obj.to_s unless obj.is_a? #{options[:type]}
|
264
|
+
__getobj__.#{prop} = obj.__getobj__
|
265
|
+
__getobj__.save
|
266
|
+
end
|
267
|
+
EOS
|
268
|
+
when :String, :Locator
|
269
|
+
module_eval(<<-EOS, "(__AR_DELEGATOR_PROPERTY2__)", 1)
|
270
|
+
def #{prop}=(obj)
|
271
|
+
__getobj__.#{prop} = obj.to_s
|
272
|
+
__getobj__.save
|
273
|
+
end
|
274
|
+
EOS
|
275
|
+
else
|
276
|
+
raise "Don't know how to do wrapping for #{options[:type]}"
|
277
|
+
end
|
278
|
+
|
279
|
+
end
|
280
|
+
|
281
|
+
aka_property(prop, options[:aka]) if options[:aka]
|
282
|
+
end
|
283
|
+
|
284
|
+
def self.aka_property(prop, aka)
|
285
|
+
aka = [aka].flatten
|
286
|
+
aka.each do |a|
|
287
|
+
#puts "generating alias #{a} for #{prop}"
|
288
|
+
module_eval(<<-EOS, "(__AR_DELEGATOR_AKA_PROPERTY__)", 1)
|
289
|
+
alias :#{a} :#{prop}
|
290
|
+
EOS
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
def self.index_property_set(prop, options={})
|
295
|
+
r = options[:rule]
|
296
|
+
module_eval(<<-EOS, "(__AR_DELEGATOR_INDEX_PROPERTY_SET__)", 1)
|
297
|
+
def direct_#{prop}_roles
|
298
|
+
# prefetch typing topics
|
299
|
+
rtype = @ips_#{prop}_rtype ||= self.topic_map.get("#{r[:role_type]}")
|
300
|
+
atype = @ips_#{prop}_atype ||= self.topic_map.get("#{r[:association_type]}")
|
301
|
+
otype = @ips_#{prop}_otype ||= self.topic_map.get("#{r[:other_role_type]}")
|
302
|
+
# return nothing if any of the typing topics does not exist
|
303
|
+
return [] unless rtype && atype && otype
|
304
|
+
# we do that only here and not earlier because some might me nil
|
305
|
+
rtype = rtype.id
|
306
|
+
atype = atype.id
|
307
|
+
otype = otype.id
|
308
|
+
self.__getobj__.roles.map{|r|
|
309
|
+
r.ttype_id != nil &&
|
310
|
+
r.ttype_id == rtype &&
|
311
|
+
r.parent.roles.size == #{r[:association_arity]} &&
|
312
|
+
r.parent != nil &&
|
313
|
+
r.parent.ttype_id == atype &&
|
314
|
+
(r2 = r.parent.roles.select{|r2| r2.ttype_id != nil &&
|
315
|
+
r2.ttype_id == otype}.first) &&
|
316
|
+
r2}.select{|r2| r2}.map{|r2| AssociationRole.wrap(r2)}
|
317
|
+
end
|
318
|
+
def direct_#{prop}
|
319
|
+
direct_#{prop}_roles.map{|r2| r2.player}.uniq
|
320
|
+
end
|
321
|
+
EOS
|
322
|
+
|
323
|
+
if r[:transitive]
|
324
|
+
module_eval(<<-EOS, "(__AR_DELEGATOR_INDEX_PROPERTY_SET2__)", 1)
|
325
|
+
def #{prop}
|
326
|
+
d = todo = self.direct_#{prop}
|
327
|
+
while todo.size > 0
|
328
|
+
todo = todo.map{|dt| dt.direct_#{prop}}.flatten.uniq - d
|
329
|
+
d += todo
|
330
|
+
end
|
331
|
+
d
|
332
|
+
#d2 = self.direct_#{prop}.map {|dt| dt.#{prop}}.flatten
|
333
|
+
#(d+d2).uniq
|
334
|
+
end
|
335
|
+
EOS
|
336
|
+
else
|
337
|
+
if r[:infer]
|
338
|
+
module_eval(<<-EOS, "(__AR_DELEGATOR_INDEX_PROPERTY_SET3__)", 1)
|
339
|
+
def #{prop}
|
340
|
+
(self.direct_#{prop} + self.#{r[:infer]}.map{|d2| d2.direct_#{prop}}).flatten.uniq
|
341
|
+
end
|
342
|
+
EOS
|
343
|
+
elsif r[:infer_other]
|
344
|
+
module_eval(<<-EOS, "(__AR_DELEGATOR_INDEX_PROPERTY_SET4__)", 1)
|
345
|
+
def #{prop}
|
346
|
+
d = self.direct_#{prop}
|
347
|
+
(d + d.map{|d2| d2.#{r[:infer_other]}}).flatten.uniq
|
348
|
+
end
|
349
|
+
EOS
|
350
|
+
end
|
351
|
+
end
|
352
|
+
if r[:add]
|
353
|
+
module_eval(<<-EOS, "(__AR_DELEGATOR_INDEX_PROPERTY_SET5__)", 1)
|
354
|
+
def add_#{r[:add]}(t)
|
355
|
+
a = self.topic_map.create_association("#{r[:association_type]}")
|
356
|
+
a.create_role self, "#{r[:role_type]}"
|
357
|
+
a.create_role t, "#{r[:other_role_type]}"
|
358
|
+
a
|
359
|
+
# TODO add_x in index_property_set needs to trigger reload of the topics somewhere
|
360
|
+
end
|
361
|
+
def remove_#{r[:add]}(t)
|
362
|
+
direct_#{prop}_roles.select{|r| r.player == t}.each{|r| r.parent.remove}
|
363
|
+
# TODO remove_x in index_property_set needs to trigger reload of the topics somewhere
|
364
|
+
end
|
365
|
+
EOS
|
366
|
+
end
|
367
|
+
end
|
368
|
+
|
369
|
+
def self.equality(eqfields, options={})
|
370
|
+
field_condition = eqfields.map {|f| "self.#{f} == o.#{f}" }.join(" && ")
|
371
|
+
module_eval(<<-EOS, "(__AR_EQUALITY__)", 1)
|
372
|
+
def ==(o)
|
373
|
+
return false unless o
|
374
|
+
return true if #{field_condition}
|
375
|
+
false
|
376
|
+
end
|
377
|
+
EOS
|
378
|
+
end
|
379
|
+
def eql?(o)
|
380
|
+
return false unless o
|
381
|
+
return true if self.class == o.class && self.id == o.id
|
382
|
+
false
|
383
|
+
end
|
384
|
+
def hash
|
385
|
+
return self.id.hash
|
386
|
+
end
|
387
|
+
|
388
|
+
def self.wrapper_cache
|
389
|
+
module_eval(<<-EOS, "(__AR_WRAPPER_CACHE__)", 1)
|
390
|
+
def self.wrap(obj)
|
391
|
+
return nil unless obj
|
392
|
+
raise "Double wrapping" if obj.respond_to?(:__getobj__)
|
393
|
+
t = self.wrapped(obj)
|
394
|
+
if t
|
395
|
+
t.__setobj__(obj)
|
396
|
+
return t
|
397
|
+
end
|
398
|
+
self.new(obj)
|
399
|
+
end
|
400
|
+
|
401
|
+
def self.wrapped(unwrapped_obj)
|
402
|
+
@@wrapped ||= {}
|
403
|
+
return @@wrapped[unwrapped_obj.id] if unwrapped_obj.respond_to? :id
|
404
|
+
@@wrapped[unwrapped_obj]
|
405
|
+
end
|
406
|
+
def self.reset_wrapped
|
407
|
+
@@wrapped = {}
|
408
|
+
end
|
409
|
+
def initialize(*args)
|
410
|
+
super
|
411
|
+
@@wrapped ||= {}
|
412
|
+
@@wrapped[self.id]=self
|
413
|
+
end
|
414
|
+
EOS
|
415
|
+
end
|
416
|
+
|
417
|
+
alias :i :id
|
418
|
+
delegate :reload
|
419
|
+
end
|
420
|
+
end
|