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
         |