rtm 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -41,1354 +41,13 @@ end
41
41
  module RTM::AR
42
42
  require 'uri'
43
43
  require 'rtm/backend/active_record/tmdm'
44
-
45
- class TMDelegator
46
- def initialize(obj)
47
- @obj = obj
48
- end
49
-
50
- def __getobj__
51
- @obj
52
- end
53
-
54
- def __setobj__(obj)
55
- @obj = obj
56
- end
57
-
58
- def self.delegate(sym, options={})
59
- to = options[:to] || sym
60
- module_eval(<<-EOS, "(__TMDELEGATOR__)", 1)
61
- def #{sym}(*args, &block)
62
- __getobj__.send(:#{to}, *args, &block)
63
- end
64
- EOS
65
-
66
- if options[:rw]
67
- module_eval(<<-EOS, "(__TMDELEGATOR2__)", 1)
68
- def #{sym}=(*args, &block)
69
- __getobj__.send(:#{to}=, *args, &block)
70
- #{options[:save] ? "__getobj__.save" : "" }
71
- end
72
- EOS
73
- end
74
-
75
- if options[:aka]
76
- options[:aka] = [options[:aka]] unless options[:aka].respond_to? :each
77
- options[:aka].each do |aka|
78
- module_eval(<<-EOS, "(__TMDELEGATOR3__)", 1)
79
- alias :#{aka} :#{sym}
80
- EOS
81
-
82
- if options[:rw]
83
- module_eval(<<-EOS, "(__TMDELEGATOR3__)", 1)
84
- alias :#{aka}= :#{sym}=
85
- EOS
86
- end
87
- end
88
- end
89
- end
90
-
91
- def self.class_delegate(sym, options={})
92
- module_eval(<<-EOS, "(__TMDELEGATOR__)", 1)
93
- class << self
94
- def #{sym}(*args, &block)
95
- __getobj__.send(:#{sym}, *args, &block)
96
- end
97
- end
98
- EOS
99
-
100
- if options[:aka]
101
- options[:aka] = [options[:aka]] unless options[:aka].respond_to? :each
102
- options[:aka].each do |aka|
103
- module_eval(<<-EOS, "(__TMDELEGATOR2__)", 1)
104
- class << self
105
- alias :#{aka} :#{sym}
106
- end
107
- EOS
108
- end
109
- end
110
- end
111
-
112
- def self.parent(sym, options={})
113
- module_eval(<<-EOS, "(__TMDELEGATOR__)", 1)
114
- def #{sym}
115
- TopicMapConstruct.wrap(__getobj__.send(:#{sym}))
116
- end
117
- EOS
118
- aka_property(sym, [:parent, :p])
119
- end
120
-
121
- def self.property_set(prop, options={})
122
- # puts "In #{self.name.to_s.ljust(20)} we have type #{options[:type].to_s.ljust(20)} for property #{prop}"
123
- if options[:wrap]
124
- #puts "#{self}: #{options[:type]}"
125
- module_eval(<<-EOS, "(__AR_DELEGATOR_PROPERTY_SET_W__)", 1)
126
- def #{prop}(*args)
127
- if args.size == 0
128
- # fetch normal
129
- #{options[:type]}s.wrap(__getobj__.#{prop}, self, :#{options[:type]})
130
- else
131
- # fetch with filter
132
- #puts args.inspect
133
- # TODO enhance/fix condition transform code
134
- a = {}.merge(args.first)
135
- if a[:type] && !a[:ttype]
136
- a[:ttype] = a[:type]
137
- a.delete(:type)
138
- end
139
- a.each do |k,v|
140
- if v.respond_to?(:__getobj__)
141
- a[(k.to_s + "_id").to_sym] = v.id
142
- end
143
- end
144
- #{options[:type]}s.wrap(__getobj__.#{prop}.find(:all, :conditions=> a), self, :#{options[:type]})
145
- end
146
- end
147
- EOS
148
- else
149
- module_eval(<<-EOS, "(__AR_DELEGATOR_PROPERTY_SET_NW__)", 1)
150
- def #{prop}
151
- __getobj__.#{prop}
152
- end
153
- EOS
154
- end
155
-
156
- if options[:create]
157
- # some :create_args:
158
- #
159
- # create_locator reference:string
160
- # [ :name => :reference, :type => :String]
161
- #
162
- # create_topic_name value:String, scope:Collection
163
- # create_topic_name value:String, type: Topic, scope:Collection
164
- # [ {:name => :value, :type => :String}, {:name => :type, :type => :Topic, :optional => true}, {:name => :scope, :type => :Collection} ]
165
- #
166
- # create_occurrence value:String, type: Topic, scope:Collection
167
- # create_occurrence resource: Locator, type: Topic, scope:Collection
168
- # [ {:name => :value, :type => [:String, :Locator]}, {:name => :type, :type => :Topic}, {:name => :scope, :type => :Collection} ]
169
- #
170
- # create_association_role player:topic, type: topic
171
- # [ {:name => :player, :type => :Topic}, {:name => :type, :type => :Topic}]
172
- #
173
- # create_variant value:string, :scope:Collection
174
- # create_variant resource:locator, :scope:Collection
175
- # [ {:name => :value, :type => [:String, :Locator]}, {:name => :scope, :type => :Collection}]
176
-
177
- module_eval(<<-EOS, "(__AR_DELEGATOR_PROPERTY_SET_CREATE__)", 1)
178
- def create_#{ options[:create]}(*args, &block)
179
- arg_defs = #{ (options[:create_args] || nil ).inspect}
180
-
181
- a = parse_args(args, arg_defs)
182
-
183
- a = enhance_args_hash(a, arg_defs) if arg_defs
184
-
185
- a = a.reject{|k,v| v.nil?}
186
-
187
- # hack to change :type to :ttype for AR backend
188
- # puts a.inspect unless a.is_a? Hash
189
- if a[:type] && !a[:ttype]
190
- a[:ttype] = a[:type]
191
- a.delete(:type)
192
- end
193
- if [:Locator,:ItemIdentifier, :SubjectIdentifier, :SubjectLocator].include?(:#{options[:type]})
194
- unless a[:topic_map]
195
- a[:topic_map] = topic_map.__getobj__
196
- end
197
- end
198
-
199
- if block_given?
200
- obj = #{options[:type]}.wrap( __getobj__.#{options[:create]}s.new(a) )
201
- yield obj
202
- obj.save
203
- else
204
- obj = #{options[:type]}.wrap( __getobj__.#{options[:create]}s.create(a) )
205
- end
206
- obj
207
- end
208
- EOS
209
-
210
- if options[:create_aka]
211
- aka_property("create_#{options[:create]}", options[:create_aka])
212
- end
213
- end
214
-
215
- if options[:add]
216
- module_eval(<<-RUBY, "(__AR_DELEGATOR_PROPERTY_SET_ADD__)", 1)
217
- def add_#{prop.to_s.singularize}(*args, &block)
218
- #{prop}.add(*args, &block)
219
- end
220
- RUBY
221
- aka_property("add_#{prop.to_s.singularize}", options[:aka].map{|a| "add_#{a}"})
222
- aka_property("add_#{prop.to_s.singularize}", options[:aka].map{|a| "a#{a}"})
223
- end
224
-
225
- if options[:remove]
226
- module_eval(<<-RUBY, "(__AR_DELEGATOR_PROPERTY_SET_REMOVE__)", 1)
227
- def remove_#{prop.to_s.singularize}(*args, &block)
228
- #{prop}.remove(*args, &block)
229
- end
230
- RUBY
231
- aka_property("remove_#{prop.to_s.singularize}", options[:aka].map{|a| "remove_#{a}"})
232
- aka_property("remove_#{prop.to_s.singularize}", options[:aka].map{|a| "r#{a}"})
233
- end
234
-
235
- # TODO: aliases for property_set.add as add_property
236
-
237
- aka_property(prop, options[:aka]) if options[:aka]
238
- end
239
-
240
- private
241
- def parse_args(args, arg_defs)
242
- a = {}
243
- a = args.pop if args.last.is_a? Hash
244
- # We are finished if there are no more parameters or we have no arg_def.
245
- # Special case: non optional parameters must have been in the Hash, just a hash is also allowed.
246
- return a if args.size == 0 || arg_defs == nil
247
-
248
- # we have some args
249
- if args.size == arg_defs.size # all are given
250
- return args2hash(a, args,arg_defs)
251
- elsif args.size == arg_defs.reject { |d| d[:optional]}
252
- return args2hash(a, args, arg_defs.reject {|d| d[:optional]})
253
- end
254
- #warn("Functions with more than one optional parameter are not supported. This will only work if the left out ones are the last.")
255
- return args2hash(a, args,arg_defs)
256
- end
257
-
258
- def args2hash(a, args, arg_defs)
259
- arg_defs.zip(args) do |argd,arg|
260
- a[argd[:name]] = arg
261
- end
262
-
263
- return a
264
- end
265
-
266
- def enhance_args_hash(a, arg_defs)
267
- #puts "enhance_args: #{a.inspect} ---\n#{arg_defs.inspect}"
268
- return a if a.empty?
269
- arg_defs.each do |argd|
270
- #puts "enhancing #{argd[:name]}, which is a #{a[argd[:name]].class}"
271
- if argd[:type] == :Topic
272
- if a[argd[:name]].is_a? String
273
- a[argd[:name]] = topic_map._topic_by_locator!(a[argd[:name]])
274
- elsif a[argd[:name]].is_a?(RTM::Topic)
275
- a[argd[:name]] = a[argd[:name]].__getobj__
276
- end
277
- end
278
- if argd[:type] == :Locator || (argd[:type].respond_to?(:include?) && argd[:type].include?(:Locator))
279
- a[argd[:name]] = a[argd[:name]].to_s
280
- end
281
- end
282
- a
283
- end
284
-
285
- public
286
- def self.property(prop, options={})
287
- module_eval(<<-EOS, "(__AR_DELEGATOR_PROPERTY__)", 1)
288
- def #{prop}
289
- #{options[:wrap]? "#{options[:type]}.wrap":""}( __getobj__.#{prop})
290
- end
291
- EOS
292
-
293
- if options[:rw]
294
- case options[:type]
295
- when :Topic
296
- module_eval(<<-EOS, "(__AR_DELEGATOR_PROPERTY2__)", 1)
297
- def #{prop}=(obj)
298
- obj = topic_map.topic_by_locator!(obj) unless obj.is_a? #{options[:type]}
299
- __getobj__.#{prop} = obj.__getobj__
300
- __getobj__.save
301
- end
302
- EOS
303
- when :TopicMap
304
- module_eval(<<-EOS, "(__AR_DELEGATOR_PROPERTY2__)", 1)
305
- def #{prop}=(obj)
306
- obj = RTM.create obj.to_s unless obj.is_a? #{options[:type]}
307
- __getobj__.#{prop} = obj.__getobj__
308
- __getobj__.save
309
- end
310
- EOS
311
- when :String, :Locator
312
- module_eval(<<-EOS, "(__AR_DELEGATOR_PROPERTY2__)", 1)
313
- def #{prop}=(obj)
314
- __getobj__.#{prop} = obj.to_s
315
- __getobj__.save
316
- end
317
- EOS
318
- else
319
- raise "Don't know how to do wrapping for #{options[:type]}"
320
- end
321
-
322
- end
323
-
324
- aka_property(prop, options[:aka]) if options[:aka]
325
- end
326
-
327
- def self.aka_property(prop, aka)
328
- aka = [aka].flatten
329
- aka.each do |a|
330
- #puts "generating alias #{a} for #{prop}"
331
- module_eval(<<-EOS, "(__AR_DELEGATOR_AKA_PROPERTY__)", 1)
332
- alias :#{a} :#{prop}
333
- EOS
334
- end
335
- end
336
-
337
- def self.index_property_set(prop, options={})
338
- r = options[:rule]
339
- module_eval(<<-EOS, "(__AR_DELEGATOR_INDEX_PROPERTY_SET__)", 1)
340
- def direct_#{prop}_roles
341
- # prefetch typing topics
342
- rtype = @ips_#{prop}_rtype ||= self.topic_map.get("#{r[:role_type]}")
343
- atype = @ips_#{prop}_atype ||= self.topic_map.get("#{r[:association_type]}")
344
- otype = @ips_#{prop}_otype ||= self.topic_map.get("#{r[:other_role_type]}")
345
- # return nothing if any of the typing topics does not exist
346
- return [] unless rtype && atype && otype
347
- # we do that only here and not earlier because some might me nil
348
- rtype = rtype.id
349
- atype = atype.id
350
- otype = otype.id
351
- self.__getobj__.roles.map{|r|
352
- r.ttype_id != nil &&
353
- r.ttype_id == rtype &&
354
- r.parent.roles.size == #{r[:association_arity]} &&
355
- r.parent != nil &&
356
- r.parent.ttype_id == atype &&
357
- (r2 = r.parent.roles.select{|r2| r2.ttype_id != nil &&
358
- r2.ttype_id == otype}.first) &&
359
- r2}.select{|r2| r2}.map{|r2| AssociationRole.wrap(r2)}
360
- end
361
- def direct_#{prop}
362
- direct_#{prop}_roles.map{|r2| r2.player}.uniq
363
- end
364
- EOS
365
-
366
- if r[:transitive]
367
- module_eval(<<-EOS, "(__AR_DELEGATOR_INDEX_PROPERTY_SET2__)", 1)
368
- def #{prop}
369
- d = todo = self.direct_#{prop}
370
- while todo.size > 0
371
- todo = todo.map{|dt| dt.direct_#{prop}}.flatten.uniq - d
372
- d += todo
373
- end
374
- d
375
- #d2 = self.direct_#{prop}.map {|dt| dt.#{prop}}.flatten
376
- #(d+d2).uniq
377
- end
378
- EOS
379
- else
380
- if r[:infer]
381
- module_eval(<<-EOS, "(__AR_DELEGATOR_INDEX_PROPERTY_SET3__)", 1)
382
- def #{prop}
383
- (self.direct_#{prop} + self.#{r[:infer]}.map{|d2| d2.direct_#{prop}}).flatten.uniq
384
- end
385
- EOS
386
- elsif r[:infer_other]
387
- module_eval(<<-EOS, "(__AR_DELEGATOR_INDEX_PROPERTY_SET4__)", 1)
388
- def #{prop}
389
- d = self.direct_#{prop}
390
- (d + d.map{|d2| d2.#{r[:infer_other]}}).flatten.uniq
391
- end
392
- EOS
393
- end
394
- end
395
- if r[:add]
396
- module_eval(<<-EOS, "(__AR_DELEGATOR_INDEX_PROPERTY_SET5__)", 1)
397
- def add_#{r[:add]}(t)
398
- a = self.topic_map.create_association("#{r[:association_type]}")
399
- a.create_role self, "#{r[:role_type]}"
400
- a.create_role t, "#{r[:other_role_type]}"
401
- a
402
- # TODO add_x in index_property_set needs to trigger reload of the topics somewhere
403
- end
404
- def remove_#{r[:add]}(t)
405
- direct_#{prop}_roles.select{|r| r.player == t}.each{|r| r.parent.remove}
406
- # TODO remove_x in index_property_set needs to trigger reload of the topics somewhere
407
- end
408
- EOS
409
- end
410
- end
411
-
412
- def self.equality(eqfields, options={})
413
- field_condition = eqfields.map {|f| "self.#{f} == o.#{f}" }.join(" && ")
414
- module_eval(<<-EOS, "(__AR_EQUALITY__)", 1)
415
- def ==(o)
416
- return false unless o
417
- return true if #{field_condition}
418
- false
419
- end
420
- EOS
421
- end
422
- def eql?(o)
423
- return false unless o
424
- return true if self.class == o.class && self.id == o.id
425
- false
426
- end
427
- def hash
428
- return self.id.hash
429
- end
430
-
431
- def self.wrapper_cache
432
- module_eval(<<-EOS, "(__AR_WRAPPER_CACHE__)", 1)
433
- def self.wrap(obj)
434
- return nil unless obj
435
- raise "Double wrapping" if obj.respond_to?(:__getobj__)
436
- t = self.wrapped(obj)
437
- if t
438
- t.__setobj__(obj)
439
- return t
440
- end
441
- self.new(obj)
442
- end
443
-
444
- def self.wrapped(unwrapped_obj)
445
- @@wrapped ||= {}
446
- return @@wrapped[unwrapped_obj.id] if unwrapped_obj.respond_to? :id
447
- @@wrapped[unwrapped_obj]
448
- end
449
- def self.reset_wrapped
450
- @@wrapped = {}
451
- end
452
- def initialize(*args)
453
- super
454
- @@wrapped ||= {}
455
- @@wrapped[self.id]=self
456
- end
457
- EOS
458
- end
459
-
460
- alias :i :id
461
- delegate :reload
462
- end
463
-
464
- class TMSetDelegator < TMDelegator
465
- include Enumerable
466
- # attr_reader :content_class_name
467
- def initialize(obj,parent,type)
468
- @obj = obj
469
- @parent = parent
470
- @type = type
471
- end
472
-
473
- # This class method wraps a Set completely while the instance method wraps one single contained object
474
- def self.wrap(obj, parent=nil, type=nil)
475
- return nil unless obj
476
- raise "Double wrapping" if obj.respond_to?(:__getobj__)
477
- self.new(obj, parent, type)
478
- end
479
-
480
- def add(obj)
481
- return unless obj
482
-
483
- old = @obj.detect { |x| x == obj } # can't that be done easier?
484
- if old
485
- old.merge obj
486
- else
487
- if obj.respond_to? :__getobj__
488
- @obj << obj.__getobj__
489
- else
490
- case @type
491
- when :Topic
492
- @obj << @parent.topic_map.get!(obj).__getobj__
493
- @parent.__getobj__.reload
494
-
495
- when :ItemIdentifier
496
- if @parent.class.name.to_s =~ /::Topic$/
497
- tbi = @parent.topic_map._item_identifier(obj)
498
- if tbi && tmc=tbi.topic_map_construct
499
- if tmc.class.name =~ /::Topic$/
500
- return @parent if tmc == @parent.__getobj__
501
- result = Topic.wrap(tmc).merge @parent
502
- return result
503
- else
504
- raise "Duplicate Item Identifier"
505
- end
506
- end
507
- tbsi = @parent.topic_map._subject_identifier(obj.to_s)
508
- if tbsi
509
- if t=tbsi.topic
510
- return @parent if t == @parent.__getobj__
511
- result = Topic.wrap(t).merge @parent
512
- # after merging, we still need to add the II
513
- result.__getobj__.item_identifiers.create(:reference => obj.to_s, :topic_map_id => @parent.topic_map.__getobj__.id)
514
- return result
515
- end
516
- end
517
- end
518
- result = @obj << @parent.topic_map._item_identifier!(obj.to_s)
519
- return result
520
-
521
- when :SubjectIdentifier
522
- # check for existing item identifier
523
- tbi = @parent.topic_map._item_identifier(obj)
524
- if tbi && tmc=tbi.topic_map_construct
525
- if tmc.class.name =~ /::Topic$/
526
- return @parent if tmc == @parent.__getobj__
527
- result = Topic.wrap(tmc).merge @parent
528
- # after merging, we still need to add the SI
529
- result.__getobj__.subject_identifiers.create(:reference => obj.to_s, :topic_map_id => @parent.topic_map.__getobj__.id)
530
- return result
531
- else
532
- warn("This subject identifier IRI already belongs to another topic map construct (not a topic)")
533
- end
534
- end
535
- # check for existing subject identifier
536
- tbsi = @parent.topic_map._subject_identifier(obj.to_s)
537
- if tbsi
538
- if true && t=tbsi.topic #the single = is intentional, the "true &&" just makes netbeans not raise a warning
539
- return @parent if t == @parent.__getobj__
540
- result = Topic.wrap(t).merge @parent
541
- return result
542
- end
543
- end
544
- @obj.create(:reference => obj.to_s, :topic_map_id => @parent.topic_map.__getobj__.id)
545
-
546
- when :SubjectLocator
547
- tbsl = @parent.topic_map._subject_locator(obj.to_s)
548
- if tbsl
549
- if true && t=tbsl.topic #the single = is intentional, the "true &&" just makes netbeans not raise a warning
550
- return @parent if t == @parent.__getobj__
551
- result = Topic.wrap(t).merge @parent
552
- return result
553
- end
554
- end
555
- @obj.create(:reference => obj.to_s, :topic_map_id => @parent.topic_map.__getobj__.id)
556
-
557
- end
558
- end
559
- end
560
- end
561
- alias :<< :add
562
-
563
- def add_all(objs)
564
- return unless objs
565
- objs.each {|obj| add(obj)}
566
- true
567
- end
568
-
569
- def each(&b)
570
- @obj.each { |e| yield wrap(e)}
571
- end
572
-
573
- def size
574
- @obj.size
575
- end
576
- alias :length :size
577
-
578
- def empty?
579
- @obj.empty?
580
- end
581
-
582
- def delete(obj)
583
- obj = obj.__getobj__ if obj.respond_to? :__getobj__
584
- case @type
585
- when :ItemIdentifier, :SubjectIdentifier, :SubjectLocator
586
- obj = @obj.find_by_reference(@parent.topic_map.resolve(obj.to_s)) if obj.is_a? String
587
- end
588
- @obj.delete(obj)
589
- # item_identifiers: remove also from topicMap
590
- #removed_event obj if respond_to? :removed_event
591
- end
592
- alias :remove :delete
593
-
594
- def include?(obj)
595
- return @obj.include?(obj)
596
- #@obj.each { |e| return true if e == obj } # T#ODO support for get
597
- #false
598
- end
599
-
600
- def first
601
- wrap(@obj.entries.first)
602
- end
603
- def last
604
- wrap(@obj.entries.last)
605
- end
606
-
607
- def to_s
608
- "[#{@obj.entries.map { |e| wrap(e).to_s }.join(", ") }]"
609
- end
610
- def [](i)
611
- wrap(@obj[i])
612
- end
613
-
614
- def content_class
615
- # @content_class ||= RTM.const_get(@content_class_name)
616
- @content_class ||= RTM.const_get("#{@content_class_name}MemImpl")
617
- end
618
-
619
- def find(*args)
620
- res = @obj.find(*args)
621
- if res.respond_to? :each
622
- TopicMapConstructs.wrap(res)
623
- else
624
- TopicMapConstruct.wrap(res)
625
- end
626
- end
627
-
628
- def &(other)
629
- @obj.to_a & other.to_a
630
- end
631
-
632
- alias :old_method_missing :method_missing
633
- def method_missing(method_name, *args)
634
- if @obj.size > 0 && first.respond_to?(method_name) && (![:__getobj__, :__setobj__].include?(method_name))
635
- a = []
636
- inject(a) {|all,single| all << single.send(method_name, *args)}
637
- a
638
- else
639
- old_method_missing(method_name, *args)
640
- end
641
- end
642
-
643
- alias :old_respond_to? :respond_to?
644
- def respond_to?(method_name)
645
- resp = old_respond_to?(method_name)
646
- return resp if resp # i.e. if true
647
- return false if [:__getobj__, :__setobj__].include?(method_name)
648
- # ... and ask first child otherwise
649
- @obj.size > 0 && first.respond_to?(method_name)
650
- end
651
-
652
- # TMSetDelegator#to_a doesn't help as thought, but maybe we come back to that l8r...
653
- #def to_a
654
- # @obj.map {|o| wrap(o)}
655
- #end
656
- end
657
-
658
- class TopicMapConstruct < TMDelegator
659
- include RTM::TopicMapConstruct
660
-
661
- def self.abstract_class?
662
- self == TopicMapConstruct
663
- end
664
- property_set :item_identifiers, :aka => [:ii, :iid, :source_locators], :type => :ItemIdentifier, :wrap => true,
665
- #:create => :item_identifier, :create_aka => :cii
666
- :add => true, :remove => true
667
-
668
- delegate :remove, :to => :destroy
669
-
670
- delegate :id
671
- # property_parent :parent # mmh..
672
-
673
- property :topic_map, :rw => true, :type => :TopicMap, :wrap => true
674
-
675
- #class_delegate :create
676
-
677
- def self.wrap(obj)
678
- return nil unless obj
679
- raise "Double wrapping" if obj.respond_to?(:__getobj__)
680
- case obj.class.name
681
- when "RTM::AR::TMDM::Topic"
682
- Topic.wrap(obj)
683
- when "RTM::AR::TMDM::Variant"
684
- Variant.wrap(obj)
685
- when "RTM::AR::TMDM::TopicName"
686
- TopicName.wrap(obj)
687
- when "RTM::AR::TMDM::Occurrence"
688
- Occurrence.wrap(obj)
689
- when "RTM::AR::TMDM::Association"
690
- Association.wrap(obj)
691
- when "RTM::AR::TMDM::AssociationRole"
692
- AssociationRole.wrap(obj)
693
- when "RTM::AR::TMDM::TopicMap"
694
- TopicMap.wrap(obj)
695
- else
696
- raise "Can't wrap object. Class for wrapping #{obj.class} unknown (object: #{obj})"
697
- end
698
- end
699
-
700
- def self.find(*args)
701
- res = RTM::AR::TMDM.const_get(name.split("::").last).find(*args)
702
- if res.respond_to? :each
703
- TopicMapConstructs.wrap(res)
704
- else
705
- TopicMapConstruct.wrap(res)
706
- end
707
- end
708
- end
709
-
710
- class Reifiable < TopicMapConstruct
711
- include RTM::Reifiable
712
-
713
- def self.abstract_class?
714
- self == Reifiable
715
- end
716
- property :reifier, :type => :Topic, :rw => :true, :wrap => true
717
- end
718
-
719
- class TopicMap < Reifiable
720
- include RTM::TopicMap
721
- wrapper_cache
722
- property_set :topics, :aka => :t, :type => :Topic, :wrap => true,
723
- :create => :topic, :create_aka => :ct
724
-
725
- property_set :associations, :aka => [:a, :assocs], :type => :Association, :wrap => true,
726
- :create => :association, :create_aka => :ca,
727
- :create_args => [{:name => :type, :type => :Topic}]
728
-
729
-
730
- delegate :base_locator
731
-
732
- property_set :association_types, :aka => :at, :type => :Topic, :wrap => true
733
- property_set :association_role_types, :aka => [:role_types,:art,:rt], :type => :Topic, :wrap => true
734
- property_set :topic_name_types, :aka => [:name_types,:tnt,:nt], :type => :Topic, :wrap => true
735
- property_set :occurrence_types, :aka => :ot, :type => :Topic, :wrap => true
736
-
737
- property_set :topic_names, :aka => [:names,:n], :type => :TopicName, :wrap => :true
738
- property_set :occurrences, :aka => :o, :type => :Occurrence, :wrap => :true
739
- property_set :association_roles, :aka => [:roles, :r], :type => :AssociationRole, :wrap => :true
740
-
741
- def types
742
- topics.select{|t| t.instances.size > 0}
743
- end
744
- alias :topic_types :types
745
- def fast_types
746
-
747
- end
748
-
749
- # This fetches all topics who have no topic-instances (but they might be types for associations etc.).
750
- # See indivduals
751
- def non_types
752
- topics.select{|t| t.instances.size == 0}
753
- end
754
-
755
- # This fetches all topics which are not type for something else (including topics, associations etc.).
756
- # See non_types
757
- def individuals
758
- non_types.select{|t| t.associations_typed.size==0 && t.roles_typed.size==0 && t.names_typed.size==0 && t.occurrences_typed.size==0}
759
- end
760
- def instances
761
- topics.select{|t| t.types.size > 0}
762
- end
763
- def non_instances
764
- topics.reject{|t| t.types.size > 0}
765
- end
766
- def internal_occurrences
767
- occurrences.select{|o| o.datatype != RTM::PSI[:IRI]}
768
- end
769
- def external_occurrences
770
- occurrences.select{|o| o.datatype == RTM::PSI[:IRI]}
771
- end
772
-
773
- def self.create(base_locator, params={})
774
- tm = self.wrap(TMDM::TopicMap.find_or_create_by_base_locator(base_locator))
775
- yield tm if block_given?
776
- tm
777
- end
778
-
779
- def self.topic_maps
780
- TopicMaps.wrap(TMDM::TopicMap.find(:all))
781
- end
782
-
783
- # Resolves an IRI or fragment relative to the base_locator of this topic_map or an optional given alternative_base_locator
784
- #
785
- # Absolute IRIs are taken as is.
786
- #
787
- # Relative IRIs:
788
- # If the base_locator is a directory (ends with "/") it is appended like a file, i.e. directly
789
- # If the base_locator is a file it is appended as a fragment (with # in between)
790
- def resolve(obj,alternative_base_locator=nil)
791
- uri = obj.to_s
792
- # TODO uri = URI.decode(obj.to_s) # this InvalidURIError somethimes :(
793
- begin
794
- uri_uri = URI.parse(uri)
795
- rescue URI::InvalidComponentError => ice
796
- warn "Catched an URI::InvalidComponentError for URI: #{uri}, message was \"#{ice.message}\"\n" +
797
- "Will continue using the UNRESOLVED IRI, claiming it is absolute."
798
- return uri
799
- end
800
- if uri_uri.absolute?
801
- return uri_uri.to_s
802
- end
803
-
804
- uri = uri[1..-1] if uri[0] == "#"[0]
805
- bl = alternative_base_locator || base_locator
806
- if bl[-1,1] == "/"
807
- return bl + uri
808
- else
809
- return bl + "#" + uri
810
- end
811
- end
812
-
813
- #private
814
-
815
- def _item_identifier(iid)
816
- __getobj__.locators.find_by_reference(resolve(iid)) # doesn't work :( --> , :include => [ :topic_map_construct ])
817
- end
818
- def _item_identifier!(iid)
819
- __getobj__.locators.find_or_create_by_reference(resolve(iid)) # doesn't work :( --> , :include => [ :topic_map_construct ])
820
- end
821
-
822
- def _subject_identifier(iid)
823
- __getobj__.subject_identifiers.find_by_reference(iid, :include => :topic)
824
- end
825
- def _subject_identifier!(iid)
826
- __getobj__.subject_identifiers.find_or_create_by_reference(iid, :include => :topic)
827
- end
828
-
829
- def _subject_locator(iid)
830
- __getobj__.subject_locators.find_by_reference(iid, :include => :topic)
831
- end
832
- def _subject_locator!(iid)
833
- __getobj__.subject_locators.find_or_create_by_reference(iid, :include => :topic)
834
- end
835
-
836
-
837
- # internal helper for by_item_identifier, doesn't wrap result
838
- def _by_item_identifier(iid)
839
- ii = __getobj__.locators.find_by_reference(resolve(iid)) #, :include => [ :topic_map_construct ])
840
- return ii.topic_map_construct if ii
841
- nil
842
- end
843
- def _topic_by_item_identifier(iid)
844
- t = _by_item_identifier(iid)
845
- return nil unless t
846
- return t if t.class.name =~ /::Topic$/ # only return something if the thing is a topic
847
- nil
848
- end
849
-
850
- # internal helper for topic_by_item_identifier!, doesn't wrap result
851
- def _topic_by_item_identifier!(iid)
852
- ii = __getobj__.locators.find_or_create_by_reference(resolve(iid))#, :include => [ :topic_map_construct ])
853
- return ii.topic_map_construct if ii.topic_map_construct && ii.topic_map_construct_type =~ /::Topic$/
854
- top2 = _topic_by_subject_identifier(resolve(iid))
855
- if top2
856
- ii.topic_map_construct = top2
857
- else
858
- ii.topic_map_construct = create_topic.__getobj__
859
- end
860
- ii.save
861
- ii.topic_map_construct
862
- end
863
- # internal helper for topic_by_subject_identifier, doesn't wrap result
864
- def _topic_by_subject_identifier(sid)
865
- si = __getobj__.subject_identifiers.find_by_reference(sid, :include => [ :topic ])
866
- return si.topic if si
867
- nil
868
- end
869
- # internal helper for topic_by_subject_identifier!, doesn't wrap result
870
- def _topic_by_subject_identifier!(sid)
871
- si = __getobj__.subject_identifiers.find_or_create_by_reference(sid, :include => [ :topic ])
872
- return si.topic if si.topic
873
- begin
874
- top2 = _by_item_identifier(sid)
875
- rescue ActiveRecord::RecordNotFound => rnf
876
- si.topic = create_topic.__getobj__
877
- else
878
- if top2 && top2.respond_to?(:subject_identifiers)
879
- si.topic = top2
880
- else
881
- si.topic = create_topic.__getobj__
882
- end
883
- end
884
- si.save
885
- si.topic
886
- end
887
-
888
- # internal helper for topic_by_subject_locator, doesn't wrap result
889
- def _topic_by_subject_locator(slo)
890
- sl = __getobj__.subject_locators.find_by_reference(RTM::LocatorHelpers.slo2iri(slo)) #, :include => [ :topic ])
891
- return sl.topic if sl
892
- nil
893
- end
894
-
895
- # internal helper for topic_by_subject_locator!, doesn't wrap result
896
- def _topic_by_subject_locator!(slo)
897
- sl = __getobj__.subject_locators.find_or_create_by_reference(RTM::LocatorHelpers.slo2iri(slo), :include => [ :topic ])
898
- return sl.topic if sl.topic
899
- sl.topic = create_topic.__getobj__
900
- sl.save
901
- sl.topic
902
- end
903
- def _topic_by_locator(iri)
904
- raise "Locator may not be nil" unless iri
905
- if RTM::LocatorHelpers.is_a_slo?(iri)
906
- _topic_by_subject_locator(iri)
907
- elsif URI.parse(iri).absolute?
908
- _topic_by_subject_identifier(iri)
909
- else
910
- _topic_by_item_identifier(iri)
911
- end
912
- end
913
-
914
- def _topic_by_locator!(iri)
915
- raise "Locator may not be nil" unless iri
916
- if RTM::LocatorHelpers.is_a_slo?(iri)
917
- _topic_by_subject_locator!(iri)
918
- elsif URI.parse(iri).absolute?
919
- _topic_by_subject_identifier!(iri)
920
- else
921
- _topic_by_item_identifier!(iri)
922
- end
923
- end
924
-
925
- public
926
- # returns an item identifier from the topic_map if it exists
927
- def item_identifier(iid)
928
- ItemIdentifier.wrap(_item_identifier(iid))
929
- end
930
- # returns an item identififier from the topic_map or creates it if it doesn't exist
931
- def item_identifier!(iid)
932
- ItemIdentifier.wrap(_item_identifier!(iid))
933
- end
934
- alias :create_locator :item_identifier!
935
- # Returns a topic map construct by it's item identifier or nil if not found.
936
- # It's the equivalent to TMAPI's TopicMapObjectIndex.getTopicMapObjectBySourceLocator
937
- def by_item_identifier(iid)
938
- TopicMapConstruct.wrap(_by_item_identifier(iid))
939
- end
940
- # Returns a topic by it's item identifier. The topic will be created if not found.
941
- def topic_by_item_identifier!(iid)
942
- Topic.wrap(_topic_by_item_identifier!(iid))
943
- end
944
- # Returns a topic by it's subject identifier or nil if not found.
945
- # It's the equivalent to TMAPI's TopicsIndex.getTopicBySubjectIdentifier.
946
- def topic_by_subject_identifier(sid)
947
- Topic.wrap(_topic_by_subject_identifier(sid))
948
- end
949
- # returns a topic by it's subject identifier. The topic will be created if not found.
950
- def topic_by_subject_identifier!(sid)
951
- Topic.wrap(_topic_by_subject_identifier!(sid))
952
- end
953
- # Returns a topic by it's subject locator or nil if not found.
954
- # It's the equivalent to TMAPI's TopicsIndex.getTopicBySubjectLocator
955
- def topic_by_subject_locator(slo)
956
- Topic.wrap(_topic_by_subject_locator(slo))
957
- end
958
- # returns a topic by it's subject locator. The topic will be created if not found.
959
- def topic_by_subject_locator!(slo)
960
- Topic.wrap(_topic_by_subject_locator!(slo))
961
- end
962
-
963
- # Gets a topic from this topic map using its (relative) item identifier,
964
- # its (absolute) subject identifier or its (absolute and by "=" prepended) subject locator)
965
- #
966
- # Returns nil if the Topic does not exist.
967
- #
968
- def topic_by_locator(iri)
969
- return iri if iri.is_a? Topic
970
- # @tblc ||= {}
971
- # t = @tblc[iri]
972
- # return t if t
973
- t = Topic.wrap(_topic_by_locator(iri))
974
- # @tblc[iri] = t if t
975
- # t
976
- end
977
- alias :get :topic_by_locator
978
-
979
- # Gets a topic from this topic map using its (relative) item identifier,
980
- # its (absolute) subject identifier or its (absolute and by "=" prepended) subject locator)
981
- #
982
- # If there is no topic with this item identifier, subject identifier or subject locator, it is created.
983
- #
984
- def topic_by_locator!(iri)
985
- return iri if iri.is_a? Topic
986
- # @tblc ||= {}
987
- # t = @tblc[iri]
988
- # return t if t
989
- t = Topic.wrap(_topic_by_locator!(iri))
990
- # @tblc[iri] = t
991
- # t
992
- end
993
- alias :get! :topic_by_locator!
994
-
995
- # I am not sure if this is at all correct. TMDM doesn't say a word about it
996
- # and the approach to compare topic maps is CXTM. I chose this because we
997
- # should (at least at the time of writing) have only one topic with a given
998
- # base locator in RTM. If you don't like it, drop me a mail and explain why
999
- # and propose something better.
1000
- equality [:base_locator]
1001
- end
1002
-
1003
- class Topic < TopicMapConstruct
1004
- include RTM::Topic
1005
- wrapper_cache
1006
-
1007
- parent :topic_map
1008
- property_set :subject_identifiers, :aka => [:si,:sid], :type => :SubjectIdentifier, :wrap => true,
1009
- #:create => :subject_identifier, :create_aka => [:csi,:csid],
1010
- #:create_args => [{:name => :reference, :type => :String}]
1011
- :add => true, :remove => true
1012
- property_set :subject_locators, :aka => [:sl,:slo], :type => :SubjectLocator, :wrap => true,
1013
- #:create => :subject_locator, :create_aka => [:csl, :cslo],
1014
- #:create_args => [{:name => :reference, :type => :String}]
1015
- :add => true, :remove => true
1016
-
1017
- property :reified, :computable => true, :type => :Reifiable, :wrap => true
1018
-
1019
- property_set :topic_names, :aka => [:n, :names], :type => :TopicName, :wrap => true,
1020
- :create => :topic_name, :create_aka => [:create_name, :cn],
1021
- :create_args => [ {:name => :value, :type => :String}, {:name => :type, :type => :Topic, :optional => true}, {:name => :scope, :type => :Collection} ]
1022
-
1023
- property_set :occurrences, :aka => :o, :type => :Occurrence, :wrap => true,
1024
- :create => :occurrence, :create_aka => :co,
1025
- :create_args => [ {:name => :value, :type => [:String, :Locator]}, {:name => :type, :type => :Topic}, {:name => :scope, :type => :Collection} ]
1026
-
1027
- def internal_occurrences
1028
- occurrences.select{|o| o.datatype != RTM::PSI[:IRI]}
1029
- end
1030
- def external_occurrences
1031
- occurrences.select{|o| o.datatype == RTM::PSI[:IRI]}
1032
- end
1033
-
1034
- property_set :roles, :aka => [:r, :roles_played, :association_roles], :computable => true, :type => :AssociationRole, :wrap => true
1035
-
1036
- property_set :associations, :aka => [:a, :associations_played], :type => :Association, :wrap => true
1037
-
1038
- property_set :scoped_objects, :type => :TopicMapConstruct, :wrap => true
1039
- property_set :scoped_associations, :type => :Association, :wrap => true
1040
- property_set :scoped_topic_names, :aka => :scoped_names, :type => :TopicName, :wrap => true
1041
- property_set :scoped_variants, :type => :Variant, :wrap => true
1042
- property_set :scoped_occurrences, :type => :Occurrence, :wrap => true
1043
-
1044
- property_set :associations_typed, :aka => :at, :type => :Association, :wrap => true
1045
- property_set :association_roles_typed, :aka => [:roles_typed,:art,:rt], :type => :AssociationRole, :wrap => true
1046
- property_set :topic_names_typed, :aka => [:names_typed,:tnt,:nt], :type => :TopicName, :wrap => true
1047
- property_set :occurrences_typed, :aka => :ot, :type => :Occurrence, :wrap => true
1048
-
1049
- # maybe these pairs could be declared each with a single statement and a reversible option
1050
- index_property_set :types, :type => :Topic, :rule => {
1051
- :transitive => false,
1052
- :role_type => RTM::PSI[:instance],
1053
- :association_type => RTM::PSI[:type_instance],
1054
- :association_arity => 2,
1055
- :other_role_type => RTM::PSI[:type],
1056
- :infer_other => :supertypes,
1057
- :add => :type,
1058
- }
1059
- index_property_set :instances, :type => :Topic, :rule => {
1060
- :transitive => false,
1061
- :role_type => RTM::PSI[:type],
1062
- :association_type => RTM::PSI[:type_instance],
1063
- :association_arity => 2,
1064
- :other_role_type => RTM::PSI[:instance],
1065
- :infer => :subtypes,
1066
- :add => :instance,
1067
- }
1068
- index_property_set :supertypes, :type => :Topic, :rule => {
1069
- :transitive => true,
1070
- :role_type => RTM::PSI[:subtype],
1071
- :association_type => RTM::PSI[:supertype_subtype],
1072
- :association_arity => 2,
1073
- :other_role_type => RTM::PSI[:supertype],
1074
- :add => :supertype,
1075
- }
1076
- index_property_set :subtypes, :type => :Topic, :rule => {
1077
- :transitive => true,
1078
- :role_type => RTM::PSI[:supertype],
1079
- :association_type => RTM::PSI[:supertype_subtype],
1080
- :association_arity => 2,
1081
- :other_role_type => RTM::PSI[:subtype],
1082
- :add => :subtype,
1083
- }
1084
-
1085
- def [](topicref)
1086
- topicref =~ /^(-\s*)?(.+)?$/
1087
- if $1
1088
- nametype = $2 || RTM::PSI[:name_type]
1089
- names.select{|n| n.type == topic_map.get(nametype)}
1090
- else
1091
- raise "No occurrence type given" unless $2 and !$2.empty?
1092
- occurrences.select{|o| o.type == topic_map.get($2)}
1093
- end
1094
- end
1095
-
1096
- def []=(topicref, value)
1097
- topicref =~ /^(-\s*)?(.+)?$/
1098
- if $1
1099
- nametype = $2 || topic_map.get!(RTM::PSI[:name_type])
1100
- n = create_name(value, nametype)
1101
- n
1102
- else
1103
- raise "No occurrence type given" unless $2
1104
- o = create_occurrence(value, $2)
1105
- o
1106
- end
1107
- end
1108
-
1109
- # class:Topic equality, http://www.isotopicmaps.org/sam/sam-model/#d0e1029
1110
- #
1111
- # This method is all crap. These ActiveRecord Arrays can't be intersected,
1112
- # so I map the identifiers to their reference which seems long winded.
1113
- # Still I find it better than using their ID in the long.
1114
- #
1115
- def ==(o)
1116
- return false unless o
1117
- # Two topic items are equal if they have:
1118
- # * at least one equal string in their [subject identifiers] properties,
1119
- # -> test if intersection are > 0
1120
- my_si = self.subject_identifiers.map{|si| si.reference}
1121
- ot_si = o.subject_identifiers.map{|si| si.reference}
1122
- return true if ( my_si & ot_si).size > 0
1123
-
1124
- # * at least one equal string in their [item identifiers] properties,
1125
- my_ii = self.item_identifiers.map{|ii| ii.reference}
1126
- ot_ii = o.item_identifiers.map{|ii| ii.reference}
1127
- return true if (my_ii & ot_ii).size > 0
1128
-
1129
- # * at least one equal string in their [subject locators] properties,
1130
- my_sl = self.subject_locators.map{|sl| sl.reference}
1131
- ot_sl = o.subject_locators.map{|sl| sl.reference}
1132
- return true if (my_sl & ot_sl).size > 0
1133
-
1134
- # * an equal string in the [subject identifiers] property of the one topic item and the [item identifiers] property of the other, or
1135
- return true if (my_si & ot_ii).size > 0
1136
- return true if (my_ii & ot_si).size > 0
1137
-
1138
- # * the same information item in their [reified] properties.
1139
- return true if self.reified != nil && o.reified != nil && (self.reified == o.reified)
1140
- # ... otherwise
1141
- false
1142
- end
1143
- end
1144
-
1145
- class Association < Reifiable
1146
- include RTM::Association
1147
- wrapper_cache
1148
-
1149
- parent :topic_map
1150
- property :type, :aka => [:ty,:t], :rw => true, :type => :Topic, :wrap => true
1151
- property_set :scope, :type => :Topic, :wrap => true
1152
- property_set :roles, :aka => [:r, :association_roles], :type => :AssociationRole, :wrap => true,
1153
- :create => :role, :create_aka => [:cr, :create_association_role],
1154
- :create_args => [ {:name => :player, :type => :Topic}, {:name => :type, :type => :Topic}]
1155
-
1156
- property_set :role_players, :aka => [:players, :rp, :pl], :type => :Topic, :wrap => true
1157
- property_set :role_types, :aka => [:types, :rt], :type => :Topic, :wrap => true
1158
-
1159
- equality [:scope, :type, :roles]
1160
- end
1161
-
1162
- class AssociationRole < Reifiable
1163
- include RTM::AssociationRole
1164
- wrapper_cache
1165
-
1166
- parent :association
1167
- property :player, :aka => [:pl,:topic], :rw => true, :type => :Topic, :wrap => true
1168
- property :type, :aka => [:ty,:t], :rw => true, :type => :Topic, :wrap => true
1169
-
1170
- def counterparts
1171
- self.parent.roles.reject{|r| r.id==self.id}
1172
- end
1173
- def counterplayers
1174
- self.counterparts.map{|r| r.player}
1175
- end
1176
- def counterpart
1177
- n = self.parent.roles.size
1178
- raise "Association must be unary or binary to use counterpart method. Please use counterparts for n-ary associations." if n > 2
1179
- return nil if n == 1
1180
- self.parent.roles.reject{|r| r.id==self.id}.first
1181
- end
1182
- def counterplayer
1183
- n = self.parent.roles.size
1184
- raise "Association must be unary or binary to use counterplayer method. Please use counterplayers for n-ary associations." if n > 2
1185
- return nil if n == 1
1186
- self.parent.roles.reject{|r| r.id==self.id}.first.player
1187
- end
1188
- def peers
1189
- self.counterpart.player.roles.select{|r| r.type == cp.type}.counterpart
1190
- end
1191
- def peerplayers
1192
- self.peers.map{|r| r.player}
1193
- end
1194
-
1195
- equality [:type, :player, :parent]
1196
- end
1197
-
1198
- class TopicName < Reifiable
1199
- include RTM::TopicName
1200
- wrapper_cache
1201
-
1202
- parent :topic
1203
- property :type, :aka => [:ty,:t], :rw => true, :type => :Topic, :wrap => true
1204
- property_set :scope, :type => :Topic, :wrap => true
1205
-
1206
- property_set :variants, :aka => :v, :type => :Variant, :wrap => true,
1207
- :create => :variant, :create_aka => :cv,
1208
- :create_args => [ {:name => :value, :type => [:String, :Locator]}, {:name => :scope, :type => :Collection}]
1209
-
1210
- property :value, :rw => true, :type => :String
1211
-
1212
- equality [:value, :type, :scope, :parent]
1213
- end
1214
-
1215
- class Occurrence < Reifiable
1216
- include RTM::Occurrence
1217
- wrapper_cache
1218
-
1219
- parent :topic
1220
- property :value, :rw => true, :type => :String
1221
- property :datatype, :rw => true, :type => :String
1222
-
1223
- property_set :scope, :type => :Topic, :wrap => true
1224
- property :type, :aka => [:ty,:t], :rw => true, :type => :Topic, :wrap => true
1225
-
1226
- equality [:value, :datatype, :scope, :type, :parent]
1227
- end
1228
-
1229
- class Variant < Reifiable
1230
- include RTM::Variant
1231
- wrapper_cache
1232
-
1233
- parent :topic_name, :aka => :name
1234
- property :value, :rw => true, :type => :String
1235
- property :datatype, :rw => true, :type => :Locator #, :wrap => true
1236
- property_set :scope, :type => :Topic, :wrap => true
1237
-
1238
- equality [:value, :datatype, :scope, :parent]
1239
-
1240
- end
1241
-
1242
- class Locator < TMDelegator
1243
- include RTM::Locator
1244
-
1245
- delegate :+
1246
- delegate :-
1247
- #delegate :==
1248
- delegate :id
1249
-
1250
- delegate :get
1251
- delegate :hash
1252
- delegate :resolve_relative
1253
- delegate :to_s, :to => :reference
1254
- delegate :to_uri
1255
- delegate :uri
1256
- delegate :reference, :rw => true, :save => true
1257
- alias :value :reference
1258
- alias :value= :reference=
1259
-
1260
- equality [:reference]
1261
-
1262
- def self.wrap(obj)
1263
- return nil unless obj
1264
- raise "Double wrapping" if obj.respond_to?(:__getobj__)
1265
- case obj.class.name
1266
- when "RTM::AR::TMDM::ItemIdentifier"
1267
- ItemIdentifier.wrap(obj)
1268
- when "RTM::AR::TMDM::SubjectIdentifier"
1269
- SubjectIdentifier.wrap(obj)
1270
- when "RTM::AR::TMDM::SubjectLocator"
1271
- SubjectLocator.wrap(obj)
1272
- else
1273
- raise "Can't wrap object. Class for wrapping #{obj.class} unknown (object: #{obj})"
1274
- end
1275
- end
1276
-
1277
-
1278
- end
1279
-
1280
-
1281
- class ItemIdentifier < Locator
1282
- include RTM::ItemIdentifier
1283
- wrapper_cache
1284
- property :topic_map_construct, :type => :TopicMapConstruct, :wrap => true
1285
- end
1286
- class SubjectIdentifier < Locator
1287
- include RTM::SubjectIdentifier
1288
- wrapper_cache
1289
- property :topic, :type => :Topic, :wrap => true
1290
- end
1291
- class SubjectLocator < Locator
1292
- include RTM::SubjectLocator
1293
- wrapper_cache
1294
- property :topic, :type => :Topic, :wrap => true
1295
- end
1296
- class Topics < TMSetDelegator
1297
- def wrap(obj)
1298
- Topic.wrap(obj)
1299
- end
1300
- end
1301
- class TopicMapConstructs < TMSetDelegator
1302
- def wrap(obj)
1303
- TopicMapConstruct.wrap(obj)
1304
- end
1305
- end
1306
- class Associations < TMSetDelegator
1307
- def wrap(obj)
1308
- Association.wrap(obj)
1309
- end
1310
- end
1311
- class TopicNames < TMSetDelegator
1312
- def wrap(obj)
1313
- TopicName.wrap(obj)
1314
- end
1315
- end
1316
- class Occurrences < TMSetDelegator
1317
- def wrap(obj)
1318
- Occurrence.wrap(obj)
1319
- end
1320
- end
1321
- class AssociationRoles < TMSetDelegator
1322
- def wrap(obj)
1323
- AssociationRole.wrap(obj)
1324
- end
1325
- end
1326
- class Reifiables < TMSetDelegator
1327
- def wrap(obj)
1328
- TopicMapConstruct.wrap(obj)
1329
- end
1330
- end
1331
- class Variants < TMSetDelegator
1332
- def wrap(obj)
1333
- Variant.wrap(obj)
1334
- end
1335
- end
1336
- class TopicMaps < TMSetDelegator
1337
- def [](obj)
1338
- # support for getting topic_map by base_locator
1339
- if obj.is_a? String
1340
- # return wrap(__getobj__.find { |tm| tm.base_locator == obj })
1341
- return wrap(TMDM::TopicMap.find_by_base_locator(obj))
1342
- end
1343
- # normal index retrieval
1344
- super
1345
- end
1346
-
1347
- def wrap(obj)
1348
- TopicMap.wrap(obj)
1349
- end
1350
- end
1351
- class Locators < TMSetDelegator
1352
- def [](obj)
1353
- # support for getting locators by reference
1354
- if obj.is_a? String
1355
- return wrap(__getobj__.find { |tm| tm.reference == obj })
1356
- end
1357
- # normal index retrieval
1358
- super
1359
- end
1360
- def wrap(obj)
1361
- return nil unless obj
1362
- return obj if obj.respond_to? :__getobj__
1363
- case obj.class.name
1364
- when "RTM::AR::TMDM::ItemIdentifier"
1365
- ItemIdentifier.wrap(obj)
1366
- when "RTM::AR::TMDM::SubjectIdentifier"
1367
- SubjectIdentifier.wrap(obj)
1368
- when "RTM::AR::TMDM::SubjectLocator"
1369
- SubjectLocator.wrap(obj)
1370
- else
1371
- Locator.wrap(obj)
1372
- end
1373
- end
1374
- end
1375
-
1376
- class ItemIdentifiers < Locators
1377
- def wrap(obj)
1378
- ItemIdentifier.wrap(obj)
1379
- end
1380
- end
1381
- class SubjectIdentifiers < Locators
1382
- def wrap(obj)
1383
- SubjectIdentifier.wrap(obj)
1384
- end
1385
-
1386
- end
1387
- class SubjectLocators < Locators
1388
- def wrap(obj)
1389
- SubjectLocator.wrap(obj)
1390
- end
1391
- end
1392
-
44
+ require 'rtm/backend/active_record/tm_delegator'
45
+ require 'rtm/backend/active_record/tm_set_delegator'
46
+ require 'rtm/backend/active_record/tm_construct'
47
+ require 'rtm/backend/active_record/topic_map'
48
+ require 'rtm/backend/active_record/topic'
49
+ require 'rtm/backend/active_record/association_and_role'
50
+ require 'rtm/backend/active_record/name_variant_occurrence'
51
+ require 'rtm/backend/active_record/locators'
52
+ require 'rtm/backend/active_record/set_wrapper'
1393
53
  end
1394
-