Class: ODBA::IndexCommon

Inherits:
Object show all
Includes:
Persistable
Defined in:
lib/odba/index.rb

Overview

Indices in ODBA are defined by origin and target (which may be identical) Any time a Persistable of class target_klass or origin_klass is stored, all corresponding indices are updated. To make this possible, we have to tell Index, how to navigate from origin to target and vice versa. This entails the Limitation that these paths must not change without origin and/or target being stored. Further, search_term must be resolved in relation to origin.

Direct Known Subclasses

ConditionIndex, FulltextIndex, Index

Constant Summary collapse

ODBA_EXCLUDE_VARS =
[
  '@proc_origin', '@proc_target', '@proc_resolve_search_term'
]

Constants included from Persistable

Persistable::Exact, Persistable::Find, Persistable::ODBA_INDEXABLE, Persistable::ODBA_PREDEFINE_EXCLUDE_VARS, Persistable::ODBA_PREDEFINE_SERIALIZABLE, Persistable::ODBA_PREFETCH, Persistable::ODBA_SERIALIZABLE

Instance Attribute Summary collapse

Attributes included from Persistable

#odba_id, #odba_name, #odba_persistent, #odba_prefetch

Instance Method Summary collapse

Methods included from Persistable

#==, append_features, #dup, #eql?, #odba_add_observer, #odba_collection, #odba_cut_connection, #odba_delete, #odba_delete_observer, #odba_delete_observers, #odba_dup, #odba_exclude_vars, #odba_indexable?, #odba_isolated_dump, #odba_isolated_store, #odba_isolated_stub, #odba_isolated_twin, #odba_notify_observers, #odba_observers, #odba_potentials, #odba_prefetch?, #odba_replace!, #odba_replace_persistables, #odba_replace_stubs, #odba_restore, #odba_serializables, #odba_snapshot, #odba_store, #odba_store_unsaved, #odba_stubize, #odba_take_snapshot, #odba_target_ids, #odba_unsaved?, #odba_unsaved_neighbors, sanitize

Constructor Details

#initialize(index_definition, origin_module) ⇒ IndexCommon

Returns a new instance of IndexCommon.



27
28
29
30
31
32
33
34
35
36
# File 'lib/odba/index.rb', line 27

def initialize(index_definition, origin_module)
	@origin_klass = origin_module.instance_eval(index_definition.origin_klass.to_s)
	@target_klass = origin_module.instance_eval(index_definition.target_klass.to_s)
	@resolve_origin = index_definition.resolve_origin
	@resolve_target = index_definition.resolve_target
	@index_name = index_definition.index_name
	@resolve_search_term = index_definition.resolve_search_term
	@dictionary = index_definition.dictionary
    @class_filter = index_definition.class_filter
end

Instance Attribute Details

#class_filterObject

Returns the value of attribute class_filter.



25
26
27
# File 'lib/odba/index.rb', line 25

def class_filter
  @class_filter
end

#dictionaryObject

Returns the value of attribute dictionary.



25
26
27
# File 'lib/odba/index.rb', line 25

def dictionary
  @dictionary
end

#index_nameObject

Returns the value of attribute index_name.



25
26
27
# File 'lib/odba/index.rb', line 25

def index_name
  @index_name
end

#origin_klassObject

Returns the value of attribute origin_klass.



25
26
27
# File 'lib/odba/index.rb', line 25

def origin_klass
  @origin_klass
end

#resolve_originObject

Returns the value of attribute resolve_origin.



25
26
27
# File 'lib/odba/index.rb', line 25

def resolve_origin
  @resolve_origin
end

#resolve_search_termObject

Returns the value of attribute resolve_search_term.



25
26
27
# File 'lib/odba/index.rb', line 25

def resolve_search_term
  @resolve_search_term
end

#resolve_targetObject

Returns the value of attribute resolve_target.



25
26
27
# File 'lib/odba/index.rb', line 25

def resolve_target
  @resolve_target
end

#target_klassObject

Returns the value of attribute target_klass.



25
26
27
# File 'lib/odba/index.rb', line 25

def target_klass
  @target_klass
end

Instance Method Details

#current_origin_ids(target_id) ⇒ Object

:nodoc:



37
38
39
# File 'lib/odba/index.rb', line 37

def current_origin_ids(target_id) # :nodoc:
  ODBA.storage.index_origin_ids(@index_name, target_id)
end

#current_target_ids(origin_id) ⇒ Object

:nodoc:



40
41
42
# File 'lib/odba/index.rb', line 40

def current_target_ids(origin_id) # :nodoc:
  ODBA.storage.index_target_ids(@index_name, origin_id)
end

#delete(object) ⇒ Object

:nodoc:



43
44
45
46
47
48
49
50
51
52
# File 'lib/odba/index.rb', line 43

def delete(object) # :nodoc:
  if(object.is_a?(@origin_klass))
    ODBA.storage.delete_index_element(@index_name, object.odba_id, 
                                      'origin_id')
  end
  if(object.is_a?(@target_klass))
    ODBA.storage.delete_index_element(@index_name, object.odba_id, 
                                      'target_id')
  end
end

#delete_origin(origin_id, term) ⇒ Object

:nodoc:



53
54
55
# File 'lib/odba/index.rb', line 53

def delete_origin(origin_id, term) # :nodoc:
  ODBA.storage.index_delete_origin(@index_name, origin_id, term)
end

#delete_target(origin_id, old_term, target_id) ⇒ Object

:nodoc:



56
57
58
59
# File 'lib/odba/index.rb', line 56

def delete_target(origin_id, old_term, target_id) # :nodoc:
  ODBA.storage.index_delete_target(@index_name, origin_id,
                                   old_term, target_id)
end

#do_update_index(origin_id, term, target_id = nil) ⇒ Object

:nodoc:



60
61
62
# File 'lib/odba/index.rb', line 60

def do_update_index(origin_id, term, target_id=nil) # :nodoc:
    ODBA.storage.update_index(@index_name, origin_id, term, target_id)
end

#fill(targets) ⇒ Object



63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/odba/index.rb', line 63

def fill(targets)
	@proc_origin = nil
	rows = []
	targets.flatten.each { |target|
		target_id = target.odba_id
		origins = proc_instance_origin.call(target)
		origins.each { |origin|
        search_terms(origin).each { |term|
          do_update_index( origin.odba_id, term, target_id)
        }
		}
	}
end

#keys(length = nil) ⇒ Object



76
77
78
79
# File 'lib/odba/index.rb', line 76

def keys(length=nil)
	ODBA.storage.index_fetch_keys(@index_name, length).delete_if { |k|
      k.empty? }
end

#matches(substring, limit = nil, offset = 0) ⇒ Object



80
81
82
# File 'lib/odba/index.rb', line 80

def matches(substring, limit=nil, offset=0)
  ODBA.storage.index_matches @index_name, substring, limit, offset
end

#origin_class?(klass) ⇒ Boolean

Returns:

  • (Boolean)


83
84
85
# File 'lib/odba/index.rb', line 83

def origin_class?(klass)
	(@origin_klass == klass)
end

#proc_instance_originObject

:nodoc:



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/odba/index.rb', line 86

def proc_instance_origin # :nodoc:
	if(@proc_origin.nil?)
		if(@resolve_origin.to_s.empty?)
			@proc_origin = Proc.new { |odba_item|  [odba_item] }
		else
			src = <<-EOS
				Proc.new { |odba_item| 
					res = [odba_item.#{@resolve_origin}]
					res.flatten!
					res.compact!
					res
				}
			EOS
			@proc_origin = eval(src)
		end
	end
	@proc_origin
end

#proc_instance_targetObject

:nodoc:



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/odba/index.rb', line 104

def proc_instance_target # :nodoc:
  if(@proc_target.nil?)
    if(@resolve_target.to_s.empty?)
      @proc_target = Proc.new { |odba_item|  [odba_item] }
    #elsif(@resolve_target == :odba_skip)
    #  @proc_target = Proc.new { [] }
    else
      src = <<-EOS
        Proc.new { |odba_item| 
          res = [odba_item.#{@resolve_target}]
          res.flatten!
          res.compact!
          res
        }
      EOS
      @proc_target = eval(src)
    end
  end
  @proc_target
end

#proc_resolve_search_termObject

:nodoc:



124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/odba/index.rb', line 124

def proc_resolve_search_term # :nodoc:
	if(@proc_resolve_search_term.nil?)
		if(@resolve_search_term.to_s.empty?)
			@proc_resolve_search_term = Proc.new { |origin| 
          origin.to_s.downcase
        }
		else
			src = <<-EOS
				Proc.new { |origin| 
					begin
						origin.#{@resolve_search_term}
					rescue NameError => e
						nil
					end
				}
			EOS
			@proc_resolve_search_term = eval(src)
		end
	end
	@proc_resolve_search_term
end

#search_term(origin) ⇒ Object

:nodoc:



145
146
147
# File 'lib/odba/index.rb', line 145

def search_term(origin) # :nodoc:
	proc_resolve_search_term.call(origin)
end

#search_terms(origin) ⇒ Object



148
149
150
# File 'lib/odba/index.rb', line 148

def search_terms(origin)
  [search_term(origin)].flatten.compact.uniq
end

#set_relevance(meta, rows) ⇒ Object

:nodoc:



151
152
153
154
155
156
157
# File 'lib/odba/index.rb', line 151

def set_relevance(meta, rows) # :nodoc:
	if(meta.respond_to?(:set_relevance))
		rows.each { |row|
			meta.set_relevance(row.at(0), row.at(1))
		}
	end
end

#update(object) ⇒ Object



158
159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/odba/index.rb', line 158

def update(object)
    @class_filter ||= :is_a?
	if(object.send(@class_filter, @target_klass))
		update_target(object)
	elsif(object.send(@class_filter, @origin_klass))
		update_origin(object)
	end
  rescue StandardError => err
    warn <<-EOS
#{err.class}: #{err.message} when updating index '#{@index_name}' with a #{object.class}
#{err.backtrace[0,4]}
[...]
    EOS
end

#update_origin(object) ⇒ Object

:nodoc:



172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/odba/index.rb', line 172

def update_origin(object) # :nodoc:
	origin_id = object.odba_id
	search_terms = search_terms(object)
    current = current_target_ids(origin_id)
    target_ids = []
    current_terms = []
    current.each { |row|
      target_ids.push(row[0])
      current_terms.push(row[1])
    }
    current_terms.uniq!
    target_ids.uniq!
    (current_terms - search_terms).each { |term|
      delete_origin(origin_id, term)
    }
    new_terms = search_terms - current_terms
    unless(new_terms.empty?)
      target_ids.each { |target_id|
        new_terms.each { |term|
          do_update_index(origin_id, term, target_id)
        }
      }
    end
end

#update_target(target) ⇒ Object

:nodoc:



196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
# File 'lib/odba/index.rb', line 196

def update_target(target) # :nodoc:
    target_id = target.odba_id
    current = current_origin_ids(target_id)
    old_terms = current.collect { |row|
      [row[0], row[1]]
    }
    origins = proc_instance_origin.call(target)
    new_terms = []
    origins.each { |origin|
      origin_id = origin.odba_id
      search_terms(origin).each { |term|
        new_terms.push([origin_id, term])
      }
    }
    (old_terms - new_terms).each { |origin_id, terms|
      delete_target(origin_id, terms, target_id)
    }
    (new_terms - old_terms).each { |origin_id, terms|
      do_update_index(origin_id, terms, target_id)
    }
end