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
# 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
    @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

#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:



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

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

#current_target_ids(origin_id) ⇒ Object

:nodoc:



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

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

#delete(object) ⇒ Object

:nodoc:



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

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:



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

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:



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

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:



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

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



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

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



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

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



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

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

#origin_class?(klass) ⇒ Boolean

Returns:

  • (Boolean)


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

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

#proc_instance_originObject

:nodoc:



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

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:



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

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:



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

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:



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

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

#search_terms(origin) ⇒ Object



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

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

#set_relevance(meta, rows) ⇒ Object

:nodoc:



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

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



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

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:



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

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:



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

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