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