Module: Association::Index

Defined in:
lib/rbbt/association/index.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#source_fieldObject

Returns the value of attribute source_field.



109
110
111
# File 'lib/rbbt/association/index.rb', line 109

def source_field
  @source_field
end

#target_fieldObject

Returns the value of attribute target_field.



109
110
111
# File 'lib/rbbt/association/index.rb', line 109

def target_field
  @target_field
end

#undirectedObject

Returns the value of attribute undirected.



109
110
111
# File 'lib/rbbt/association/index.rb', line 109

def undirected
  @undirected
end

Class Method Details

.setup(repo) ⇒ Object



114
115
116
117
118
119
# File 'lib/rbbt/association/index.rb', line 114

def self.setup(repo)
  repo.extend Association::Index
  repo.parse_key_field
  repo.unnamed = true
  repo
end

Instance Method Details

#match(entity) ⇒ Object



169
170
171
172
173
# File 'lib/rbbt/association/index.rb', line 169

def match(entity)
  return entity.inject([]){|acc,e| acc.concat match(e); acc } if Array === entity
  return [] if entity.nil?
  prefix(entity + "~")
end

#matches(entities) ⇒ Object



175
176
177
178
179
180
181
182
183
184
185
# File 'lib/rbbt/association/index.rb', line 175

def matches(entities)
  entities.inject(nil) do |acc,e| 
    m = match(e); 
    if acc.nil? or acc.empty?
      acc = m
    else
      acc.concat m
    end
    acc
  end
end

#parse_key_fieldObject



110
111
112
# File 'lib/rbbt/association/index.rb', line 110

def parse_key_field
  @source_field, @target_field, @undirected = key_field.split("~")
end

#reverseObject



121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/rbbt/association/index.rb', line 121

def reverse
  @reverse ||= begin
                 if self.respond_to? :persistence_path
                   persistence_path = self.persistence_path
                   persistence_path = persistence_path.find if Path === persistence_path
                   reverse_filename = persistence_path + '.reverse'
                 else
                   raise "Can only reverse a TokyoCabinet::BDB dataset at the time"
                 end

                 if File.exists?(reverse_filename)
                   new = Persist.open_tokyocabinet(reverse_filename, false, serializer, TokyoCabinet::BDB)
                   raise "Index has no info: #{reverse_filename}" if new.key_field.nil?
                   Association::Index.setup new
                   new
                 else
                   FileUtils.mkdir_p File.dirname(reverse_filename) unless File.exists?(File.dirname(reverse_filename))

                   new = Persist.open_tokyocabinet(reverse_filename, true, serializer, TokyoCabinet::BDB)
                   
                   self.with_unnamed do
                     self.with_monitor :desc => "Reversing #{ persistence_path }" do
                       self.through do |key, value|
                         new_key = key.split("~").reverse.join("~")
                         new[new_key] = value
                       end
                     end
                   end
                   annotate(new)
                   new.key_field = key_field.split("~").values_at(1,0,2).compact * "~"
                   new.read_and_close do
                     Association::Index.setup new
                   end
                   new.read
                 end

                 new.unnamed = true

                 new.undirected = undirected

                 new
               rescue Exception
                 Log.error "Deleting after error reversing database: #{ reverse_filename }"
                 FileUtils.rm reverse_filename if File.exists? reverse_filename
                 raise $!
               end
end

#subset(source, target) ⇒ Object

{{{ Subset



209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
# File 'lib/rbbt/association/index.rb', line 209

def subset(source, target)
  return [] if source.nil? or target.nil? or source.empty? or target.empty?

  if source == :all or source == "all"
    if target == :all or target == "all"
      return keys
    else
      matches = reverse.subset(target, source)
      return matches.collect{|m| r = m.partition "~"; r.reverse*"" }
    end
  end

  matches = source.uniq.inject([]){|acc,e| 
    if block_given?
      acc.concat(match(e))
    else
      acc.concat(match(e))
    end
  }

  return matches if target == :all or target == "all"

  target_matches = {}

  matches.each{|code| 
    s,sep,t = code.partition "~"
    next if undirected and t > s and source.include? t
    target_matches[t] ||= []
    target_matches[t] << code
  }

  target_matches.values_at(*target.uniq).flatten.compact
end

#to_matrix(value_field = nil, &block) ⇒ Object



187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
# File 'lib/rbbt/association/index.rb', line 187

def to_matrix(value_field = nil, &block)
  value_field = fields.first if value_field.nil? and fields.length == 1
  value_pos = identify_field value_field if value_field and String === value_field
  key_field = source_field

  tsv = if value_pos
          AssociationItem.incidence self.keys, key_field do |key|
            if block_given? 
              yield self[key][value_pos]
            else
              self[key][value_pos]
            end
          end
        elsif block_given?
          AssociationItem.incidence self.keys, key_field, &block
        else
          AssociationItem.incidence self.keys, key_field 
        end
end