redcar 0.9.0 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. data/CHANGES +5 -0
  2. data/Rakefile +1 -2
  3. data/lib/redcar/installer.rb +2 -1
  4. data/lib/redcar.rb +2 -2
  5. data/plugins/project_search/vendor/lucene/CHANGELOG +147 -0
  6. data/plugins/project_search/vendor/lucene/CONTRIBUTORS +17 -0
  7. data/plugins/project_search/vendor/lucene/Gemfile +9 -0
  8. data/plugins/project_search/vendor/lucene/Gemfile.lock +33 -0
  9. data/plugins/project_search/vendor/lucene/LICENSE +19 -0
  10. data/plugins/project_search/vendor/lucene/README.rdoc +283 -0
  11. data/plugins/project_search/vendor/lucene/Rakefile +35 -0
  12. data/plugins/project_search/vendor/lucene/examples/active_model/serializers.rb +25 -0
  13. data/plugins/project_search/vendor/lucene/examples/active_model/validation.rb +26 -0
  14. data/plugins/project_search/vendor/lucene/examples/admin/Rakefile +4 -0
  15. data/plugins/project_search/vendor/lucene/examples/admin/admin.rb +29 -0
  16. data/plugins/project_search/vendor/lucene/examples/admin/public/jquery.js +4376 -0
  17. data/plugins/project_search/vendor/lucene/examples/admin/public/neo4j.css +153 -0
  18. data/plugins/project_search/vendor/lucene/examples/admin/public/neo_admin.js +18 -0
  19. data/plugins/project_search/vendor/lucene/examples/admin/spec/admin_spec.rb +26 -0
  20. data/plugins/project_search/vendor/lucene/examples/admin/views/index.erb +21 -0
  21. data/plugins/project_search/vendor/lucene/examples/filetree/README.rdoc +9 -0
  22. data/plugins/project_search/vendor/lucene/examples/filetree/app.rb +7 -0
  23. data/plugins/project_search/vendor/lucene/examples/filetree/batch.props +5 -0
  24. data/plugins/project_search/vendor/lucene/examples/filetree/features/step_definitions/add_steps.rb +121 -0
  25. data/plugins/project_search/vendor/lucene/examples/filetree/features/support/env.rb +30 -0
  26. data/plugins/project_search/vendor/lucene/examples/filetree/features/support/rspec_helper.rb +50 -0
  27. data/plugins/project_search/vendor/lucene/examples/filetree/features/treesizes.feature +19 -0
  28. data/plugins/project_search/vendor/lucene/examples/imdb/1_create_neo_db.rb +66 -0
  29. data/plugins/project_search/vendor/lucene/examples/imdb/2_index_db.rb +23 -0
  30. data/plugins/project_search/vendor/lucene/examples/imdb/README +12 -0
  31. data/plugins/project_search/vendor/lucene/examples/imdb/find_actors.rb +56 -0
  32. data/plugins/project_search/vendor/lucene/examples/imdb/install.sh +12 -0
  33. data/plugins/project_search/vendor/lucene/examples/imdb/model.rb +37 -0
  34. data/plugins/project_search/vendor/lucene/examples/railway/README +111 -0
  35. data/plugins/project_search/vendor/lucene/examples/railway/railnet-app.rb +31 -0
  36. data/plugins/project_search/vendor/lucene/examples/railway/railnet-data.rb +42 -0
  37. data/plugins/project_search/vendor/lucene/examples/rest/example.rb +41 -0
  38. data/plugins/project_search/vendor/lucene/examples/you_might_know/YouMightKnow.java +60 -0
  39. data/plugins/project_search/vendor/lucene/examples/you_might_know/all_simple_paths.rb +34 -0
  40. data/plugins/project_search/vendor/lucene/examples/you_might_know/nodes.rb +34 -0
  41. data/plugins/project_search/vendor/lucene/examples/you_might_know/you_might_know.rb +50 -0
  42. data/plugins/project_search/vendor/lucene/lib/lucene/config.rb +145 -0
  43. data/plugins/project_search/vendor/lucene/lib/lucene/document.rb +96 -0
  44. data/plugins/project_search/vendor/lucene/lib/lucene/field_info.rb +144 -0
  45. data/plugins/project_search/vendor/lucene/lib/lucene/hits.rb +54 -0
  46. data/plugins/project_search/vendor/lucene/lib/lucene/index.rb +267 -0
  47. data/plugins/project_search/vendor/lucene/lib/lucene/index_info.rb +146 -0
  48. data/plugins/project_search/vendor/lucene/lib/lucene/index_searcher.rb +157 -0
  49. data/plugins/project_search/vendor/lucene/lib/lucene/jars.rb +5 -0
  50. data/plugins/project_search/vendor/lucene/lib/lucene/query_dsl.rb +135 -0
  51. data/plugins/project_search/vendor/lucene/lib/lucene/transaction.rb +117 -0
  52. data/plugins/project_search/vendor/lucene/lib/lucene/version.rb +3 -0
  53. data/plugins/project_search/vendor/lucene/lib/lucene.rb +15 -0
  54. data/plugins/project_search/vendor/lucene/lucene.gemspec +23 -0
  55. data/plugins/project_search/vendor/lucene/spec/lucene/document_spec.rb +32 -0
  56. data/plugins/project_search/vendor/lucene/spec/lucene/field_info_spec.rb +70 -0
  57. data/plugins/project_search/vendor/lucene/spec/lucene/index_info_spec.rb +76 -0
  58. data/plugins/project_search/vendor/lucene/spec/lucene/index_spec.rb +643 -0
  59. data/plugins/project_search/vendor/lucene/spec/lucene/query_dsl_spec.rb +142 -0
  60. data/plugins/project_search/vendor/lucene/spec/lucene/sort_spec.rb +101 -0
  61. data/plugins/project_search/vendor/lucene/spec/lucene/spec_helper.rb +10 -0
  62. data/plugins/project_search/vendor/lucene/spec/lucene/transaction_spec.rb +118 -0
  63. metadata +62 -4
@@ -0,0 +1,144 @@
1
+ require 'date'
2
+
3
+ module Lucene
4
+ class ConversionNotSupportedException < StandardError; end
5
+
6
+ class FieldInfo
7
+ DEFAULTS = {:store => false, :type => String, :analyzer => :standard}.freeze
8
+
9
+ def initialize(values = {})
10
+ @info = DEFAULTS.dup
11
+ @info.merge! values
12
+ $LUCENE_LOGGER.debug{"new FieldInfo: #{@info.inspect}"}
13
+ end
14
+
15
+ def dup
16
+ FieldInfo.new(@info)
17
+ end
18
+
19
+ def [](key)
20
+ @info[key]
21
+ end
22
+
23
+ def []=(key,value)
24
+ @info[key] = value
25
+ end
26
+
27
+ def java_field(key, value)
28
+ # convert the ruby value to a string that lucene can handle
29
+ cvalue = convert_to_lucene(value)
30
+
31
+ # check if this field should be indexed
32
+ return nil if cvalue.nil?
33
+
34
+ # decide if the field should be stored in the lucene index or not
35
+ store = store? ? org.apache.lucene.document.Field::Store::YES : org.apache.lucene.document.Field::Store::NO
36
+
37
+ # decide if it should be tokenized/analyzed by lucene
38
+ token_type = tokenized? ? org.apache.lucene.document.Field::Index::ANALYZED : org.apache.lucene.document.Field::Index::NOT_ANALYZED
39
+ $LUCENE_LOGGER.debug{"java_field store=#{store} key='#{key.to_s}' value='#{cvalue}' token_type=#{token_type}"}
40
+
41
+ # create the new Field
42
+ org.apache.lucene.document.Field.new(key.to_s, cvalue, store, token_type ) #org.apache.lucene.document.Field::Index::NO_NORMS)
43
+ end
44
+
45
+
46
+ def convert_to_ruby(value)
47
+ if (value.kind_of?(Array))
48
+ value.collect{|v| convert_to_ruby(v)}
49
+ else case @info[:type].to_s
50
+ when NilClass.to_s then "" # TODO, should we accept nil values in indexes ?
51
+ when String.to_s then value.to_s
52
+ when Fixnum.to_s then value.to_i
53
+ when Float.to_s then value.to_f
54
+ when Date.to_s
55
+ return value if value.kind_of? Date
56
+ return nil if value.nil?
57
+ year = value[0..3].to_i
58
+ month = value[4..5].to_i
59
+ day = value[6..7].to_i
60
+ Date.new year,month,day
61
+ when DateTime.to_s
62
+ return value if value.kind_of? DateTime
63
+ return nil if value.nil?
64
+ year = value[0..3].to_i
65
+ month = value[4..5].to_i
66
+ day = value[6..7].to_i
67
+ hour = value[8..9].to_i
68
+ min = value[10..11].to_i
69
+ sec = value[12..13].to_i
70
+ DateTime.civil(year,month,day,hour,min,sec)
71
+ else
72
+ raise ConversionNotSupportedException.new("Can't convert key '#{value}' of with type '#{@info[:type].class.to_s}'")
73
+ end
74
+ end
75
+ end
76
+
77
+ def convert_to_lucene(value)
78
+ if (value.kind_of?(Array))
79
+ value.collect{|v| convert_to_lucene(v)}
80
+ elsif value.nil?
81
+ value
82
+ else
83
+ case @info[:type].to_s # otherwise it will match Class
84
+ when Fixnum.to_s then sprintf('%011d',value) # TODO: configurable
85
+ when Float.to_s then sprintf('%024.12f', value) # TODO: configurable
86
+ when Bignum.to_s then sprintf('%024d, value')
87
+ when Date.to_s
88
+ t = Time.utc(value.year, value.month, value.day)
89
+ d = t.to_i * 1000
90
+ org.apache.lucene.document.DateTools.timeToString(d,org.apache.lucene.document.DateTools::Resolution::DAY )
91
+ when DateTime.to_s
92
+ # only utc times are supported
93
+ t = Time.utc(value.year, value.month, value.day, value.hour, value.min, value.sec)
94
+ d = t.to_i * 1000
95
+ org.apache.lucene.document.DateTools.timeToString(d,org.apache.lucene.document.DateTools::Resolution::SECOND )
96
+ else value.to_s
97
+ end
98
+ end
99
+ end
100
+
101
+ def convert_to_query(key,value)
102
+ if (value.kind_of? Range)
103
+ first_value = convert_to_lucene(value.first)
104
+ last_value = convert_to_lucene(value.last)
105
+ first = org.apache.lucene.index.Term.new(key.to_s, first_value)
106
+ last = org.apache.lucene.index.Term.new(key.to_s, last_value)
107
+ $LUCENE_LOGGER.debug{"convert_to_query: Range key '#{key.to_s}' #{first_value}' to '#{last_value}'"}
108
+ org.apache.lucene.search.RangeQuery.new(first, last, !value.exclude_end?)
109
+ elsif
110
+ converted_value = convert_to_lucene(value)
111
+ term = org.apache.lucene.index.Term.new(key.to_s, converted_value)
112
+ org.apache.lucene.search.TermQuery.new(term)
113
+ end
114
+ end
115
+
116
+ def tokenized?
117
+ @info[:tokenized]
118
+ end
119
+
120
+ def store?
121
+ @info[:store]
122
+ end
123
+
124
+ def eql?(other)
125
+ return false unless other.kind_of?(FieldInfo)
126
+ @info.each_pair do |key,value|
127
+ return false if other[key] != value
128
+ end
129
+ return true
130
+ end
131
+
132
+ def ==(other)
133
+ eql? other
134
+ end
135
+
136
+ def to_s
137
+ infos = @info.keys.inject(""){|s, key| s << "#{key}=#{@info[key]} "}
138
+ "FieldInfo(#{self.object_id.to_s}) [#{infos}]"
139
+ end
140
+
141
+
142
+ end
143
+ end
144
+
@@ -0,0 +1,54 @@
1
+ module Lucene
2
+
3
+
4
+ #
5
+ # Contains the result as a collection of Documents from a lucene query.
6
+ # Is a wrapper for the Java org.apache.lucene.search.Hits class
7
+ #
8
+ class Hits
9
+ include Enumerable
10
+
11
+ def initialize(field_infos, hits)
12
+ @hits = hits
13
+ @field_infos = field_infos
14
+ end
15
+
16
+
17
+ #
18
+ # Returns the n:th hit document.
19
+ #
20
+ def [](n)
21
+ doc = @hits.doc(n)
22
+ Document.convert(@field_infos, doc)
23
+ end
24
+
25
+
26
+ #
27
+ # Returns true if there are no hits
28
+ #
29
+ def empty?
30
+ @hits.length == 0
31
+ end
32
+
33
+ def each
34
+ iter = @hits.iterator
35
+
36
+ while (iter.hasNext && hit = iter.next)
37
+ yield Document.convert(@field_infos, hit.getDocument)
38
+ end
39
+ end
40
+
41
+
42
+ #
43
+ # The number of documents the query gave.
44
+ #
45
+ def size
46
+ @hits.length
47
+ end
48
+
49
+ def to_s
50
+ "Hits [size=#{size}]"
51
+ end
52
+
53
+ end
54
+ end
@@ -0,0 +1,267 @@
1
+ require 'monitor'
2
+ require 'lucene/jars'
3
+ require 'lucene/transaction'
4
+ require 'lucene/index_searcher'
5
+ require 'lucene/document'
6
+ require 'lucene/field_info'
7
+ require 'lucene/index_info'
8
+
9
+ #
10
+ # A wrapper for the Java lucene search library.
11
+ #
12
+ module Lucene
13
+
14
+ class DocumentDeletedException < StandardError;
15
+ end
16
+ class IdFieldMissingException < StandardError;
17
+ end
18
+
19
+ #
20
+ # Represents a Lucene Index.
21
+ # The index is written/updated only when the commit method is called.
22
+ # This is done since writing to the index file should be done as a batch operation.
23
+ # (Performance will be bad otherwise).
24
+ #
25
+ # For each Thread there is zero or one Index instance. There are at most one Index instance per thread
26
+ # so there is no need for this class to use synchronization for Thread safety.
27
+ #
28
+ class Index
29
+ attr_reader :path, :uncommited
30
+
31
+
32
+ # locks per index path, must not write to the same index from 2 threads
33
+ @@locks = {}
34
+ @@locks.extend MonitorMixin
35
+
36
+ def initialize(path, index_info)
37
+ @path = path # a key (i.e. filepath) where the index is stored on disk/or RAM
38
+ @index_info = index_info # the actual storage of the index
39
+ @uncommited = {} # documents to be commited, a hash of Document
40
+ @deleted_ids = [] # documents to be deleted
41
+ end
42
+
43
+ def field_infos
44
+ IndexInfo.instance(@path)
45
+ end
46
+
47
+
48
+ # Returns an Index instance for the current running transaction.
49
+ #
50
+ # Tries to reuse an Index instance for the current running transaction.
51
+ # If a Lucene::Transaction is running it will register this index in that transaction if
52
+ # this has not already been done.
53
+ # When it has been registered in the transaction the transaction will commit the index
54
+ # when the transaction is finished.
55
+ # The configuration (kept in the #field_infos) for this index will be the same for all indexes with the same path/key.
56
+ #
57
+ # ==== Parameters
58
+ # path<String>:: The key or location where the index should be stored (relative Lucene::Config[:storage_path]
59
+ #
60
+ # ==== Examples
61
+ # Index.new 'foo/lucene-db'
62
+ #
63
+ # ==== Returns
64
+ # Returns a new or an already existing Index
65
+ #
66
+ def self.new(path)
67
+ # make sure no one modifies the index specified at given path
68
+ lock(path).synchronize do
69
+ # create a new transaction if needed
70
+ Transaction.new unless Transaction.running?
71
+
72
+ # create a new instance only if it does not already exist in the current transaction
73
+ unless Transaction.current.index?(path)
74
+ info = IndexInfo.instance(path)
75
+ index = super(path, info)
76
+ Transaction.current.register_index(path, index)
77
+ end
78
+ end
79
+ # return the index for the current transaction
80
+ Transaction.current.index(path)
81
+ end
82
+
83
+
84
+ #
85
+ # Delete all uncommited documents. Also deregister this index
86
+ # from the current transaction (if there is one transaction)
87
+ #
88
+ def clear
89
+ @uncommited.clear
90
+ Transaction.current.deregister_index self if Transaction.running?
91
+ end
92
+
93
+ #
94
+ # See instance method Index.clear
95
+ #
96
+ def self.clear(path)
97
+ return unless Transaction.running?
98
+ return unless Transaction.current.index?(path)
99
+ Transaction.current.index(path).clear
100
+ end
101
+
102
+ # Creates a new document from the given hash of values.
103
+ # This document will be stored in this instance till it is commited.
104
+ #
105
+ # ==== Parameters
106
+ # path<String>:: The key or location where the index should be stored (relative Lucene::Config[:storage_path]
107
+ #
108
+ # ==== Examples
109
+ # index = Index.new('name_or_path_to_index')
110
+ # index << {:id=>'1', :name=>'foo'}
111
+ #
112
+ # ==== Returns
113
+ # Returns the index instance so that this method can be chained
114
+ #
115
+ def <<(key_values)
116
+ doc = Document.new(field_infos, key_values)
117
+ @uncommited[doc.id] = doc
118
+ self
119
+ end
120
+
121
+ def id_field
122
+ @index_info.id_field
123
+ end
124
+
125
+ #
126
+ # Updates the specified document.
127
+ # The index file will not be updated until the transaction commits.
128
+ # The doc is stored in memory till the transaction commits.
129
+ #
130
+ def update(doc)
131
+ @uncommited[doc.id] = doc
132
+ end
133
+
134
+ #
135
+ # Delete the specified document.
136
+ # The index file not be updated until the transaction commits.
137
+ # The id of the deleted document is stored in memory till the transaction commits.
138
+ #
139
+ def delete(id)
140
+ @deleted_ids << id.to_s
141
+ end
142
+
143
+
144
+ def deleted?(id)
145
+ @deleted_ids.include?(id.to_s)
146
+ end
147
+
148
+ def updated?(id)
149
+ @uncommited[id.to_s]
150
+ end
151
+
152
+ # Writes to the index files.
153
+ # Open and closes an lucene IndexWriter
154
+ # Close the IndexSearcher so that it will read the updated index next time.
155
+ # This method will automatically be called from a Lucene::Transaction if it was running when the index was created.
156
+ #
157
+ # This method is synchronized since it is not allowed to update a lucene index from several threads at the same time.
158
+ #
159
+ def commit
160
+ lock.synchronize do
161
+ delete_documents # deletes all documents given @deleted_ids
162
+
163
+ # are any updated document deleted ?
164
+ deleted_ids = @uncommited.keys & @deleted_ids
165
+ # make sure we don't index deleted document
166
+ deleted_ids.each {|id| @uncommited.delete(id)}
167
+
168
+ # update the remaining documents that has not been deleted
169
+
170
+ begin
171
+ index_writer = org.apache.lucene.index.IndexWriter.new(@index_info.storage, @index_info.analyzer, ! exist?)
172
+ # removes the document and adds it again
173
+ @uncommited.each_value { |doc| doc.update(index_writer) }
174
+ ensure
175
+ # TODO exception handling, what if ...
176
+ index_writer.close
177
+
178
+ @uncommited.clear
179
+ @deleted_ids.clear
180
+
181
+ # if we are running in a transaction remove this so it will not be committed twice
182
+ Transaction.current.deregister_index(self) if Transaction.running?
183
+ end
184
+ end
185
+ end
186
+
187
+
188
+ #
189
+ # Delegates to the IndexSearcher.find method
190
+ #
191
+ def find(*query, &block)
192
+ # new method is a factory method, does not create if it already exists
193
+ searcher = IndexSearcher.new(@index_info.storage)
194
+
195
+ if block.nil?
196
+ case query.first
197
+ when String
198
+ return searcher.find(@index_info, query)
199
+ when Hash, Array
200
+ return searcher.find(@index_info, query.first)
201
+ end
202
+ else
203
+ return searcher.find_dsl(@index_info, &block)
204
+ end
205
+ end
206
+
207
+
208
+ def to_s
209
+ "Index [path: '#@path', #{@uncommited.size} documents]"
210
+ end
211
+
212
+ #
213
+ # -------------------------------------------------------------------------
214
+ # Private methods
215
+ #
216
+
217
+ private
218
+
219
+ #
220
+ # There is one lock per index path.
221
+ #
222
+ def lock
223
+ @@locks.synchronize do
224
+ @@locks[@path] ||= Monitor.new
225
+ @@locks[@path]
226
+ end
227
+ end
228
+
229
+ def self.lock(path)
230
+ @@locks.synchronize do
231
+ @@locks[path] ||= Monitor.new
232
+ @@locks[path]
233
+ end
234
+ end
235
+
236
+ #
237
+ # Returns true if the index already exists.
238
+ #
239
+ def exist?
240
+ @index_info.index_exists?
241
+ end
242
+
243
+ #
244
+ # --------------------------------------------------------------------------
245
+ #
246
+ private
247
+
248
+ def delete_documents # :nodoc:
249
+ return unless exist? # if no index exists then there is nothing to do
250
+
251
+ writer = org.apache.lucene.index.IndexWriter.new(@index_info.storage, @index_info.analyzer, false)
252
+ id_field = @index_info.infos[@index_info.id_field]
253
+
254
+ @deleted_ids.each do |id|
255
+ converted_value = id_field.convert_to_lucene(id)
256
+ writer.deleteDocuments(org.apache.lucene.index.Term.new(@index_info.id_field.to_s, converted_value))
257
+ end
258
+ ensure
259
+ # TODO exception handling, what if ...
260
+ writer.close unless writer.nil?
261
+ end
262
+
263
+
264
+ end
265
+ end
266
+
267
+
@@ -0,0 +1,146 @@
1
+ module Lucene
2
+
3
+ #
4
+ # Contains info for a specific Index identified by a path
5
+ # Contains a
6
+ # * collection of FieldInfo objects.
7
+ # * the name of the id field.
8
+ # * the index storage, either file based or RAM based.
9
+ #
10
+ # Fields has default value IndexInfo::DEFAULTS.
11
+ #
12
+ class IndexInfo #:nodoc:
13
+ DEFAULTS = FieldInfo.new({}).freeze
14
+
15
+ attr_reader :infos, :path
16
+ attr_accessor :id_field
17
+ attr_writer :store_on_file
18
+
19
+ # Initializes this object by setting values to default values specified in the Lucene::Config.
20
+ # The path/id to the index is specified by the the path parameter.
21
+ # If the index is Lucene::Config[:storage_path]
22
+ # ==== Block parameters
23
+ # path<String>:: The id or the (incomplete) path on the filesystem of the index
24
+ #
25
+ # :api: private
26
+ def initialize(path)
27
+ $LUCENE_LOGGER.debug{"IndexInfo#initialize(#{path})"}
28
+ @id_field = Lucene::Config[:id_field].to_sym
29
+ @path = path
30
+ @store_on_file = Lucene::Config[:store_on_file]
31
+ @infos = {}
32
+ # always store the id field
33
+ @infos[@id_field] = FieldInfo.new(:store => true)
34
+ end
35
+
36
+ def to_s
37
+ "IndexInfo [#{@id_field}, #{@infos.inspect}]"
38
+ end
39
+
40
+ def store_on_file?
41
+ @store_on_file
42
+ end
43
+
44
+ def storage
45
+ @storage ||= create_storage
46
+ end
47
+
48
+ def create_storage
49
+ if store_on_file?
50
+ raise StandardError.new("Lucene::Config[:storage_path] is nil but index configured to be stored on filesystem") if Lucene::Config[:storage_path].nil?
51
+ Lucene::Config[:storage_path] + @path
52
+ else
53
+ org.apache.lucene.store.RAMDirectory.new
54
+ end
55
+ end
56
+
57
+
58
+ def self.instance?(path)
59
+ return false if @instances.nil?
60
+ ! @instances[path].nil?
61
+ end
62
+
63
+ # Creates and initializes an IndexInfo object by setting values to default
64
+ # values specified in the Lucene::Config. Does not create new object if it has
65
+ # already been created before with the given path.
66
+ #
67
+ # If the index is stored on the filesystem the complete path will be
68
+ # Lucene::Config[:storage_path] + /path
69
+ #
70
+ # ==== Block parameters
71
+ # path<String>:: The id or the (incomplete) path on the filesystem of the index
72
+ #
73
+ # :api: public
74
+ def self.instance(path)
75
+ @instances ||= {}
76
+ $LUCENE_LOGGER.debug{"IndexInfos#instance(#{path}) : @instances[path]: #{@instances[path]}"}
77
+ @instances[path] ||= IndexInfo.new(path)
78
+ end
79
+
80
+ def self.delete_all
81
+ $LUCENE_LOGGER.debug{"IndexInfos#delete_all"}
82
+ @instances = nil
83
+ end
84
+
85
+ def self.index_exists(path)
86
+ return false if @instances[path].nil?
87
+ instance(path).index_exists?
88
+ end
89
+
90
+ def index_exists?
91
+ org.apache.lucene.index.IndexReader.index_exists(storage)
92
+ end
93
+
94
+ def each_pair
95
+ @infos.each_pair{|key,value| yield key,value}
96
+ end
97
+
98
+ def analyzer
99
+ # do all fields have the default value :standard analyzer ?
100
+ if @infos.values.find {|info| info[:analyzer] != :standard}
101
+ # no, one or more has set
102
+ wrapper = org.apache.lucene.analysis.PerFieldAnalyzerWrapper.new(org.apache.lucene.analysis.standard.StandardAnalyzer.new)
103
+ @infos.each_pair do |key,value|
104
+ case value[:analyzer]
105
+ when :keyword
106
+ wrapper.addAnalyzer(key.to_s, org.apache.lucene.analysis.KeywordAnalyzer.new)
107
+ when :standard
108
+ # default
109
+ when :simple
110
+ wrapper.addAnalyzer(key.to_s, org.apache.lucene.analysis.SimpleAnalyzer.new)
111
+ when :whitespace
112
+ wrapper.addAnalyzer(key.to_s, org.apache.lucene.analysis.WhitespaceAnalyzer.new)
113
+ when :stop
114
+ wrapper.addAnalyzer(key.to_s, org.apache.lucene.analysis.StopAnalyzer.new)
115
+ else
116
+ raise "Unknown analyzer, supports :keyword, :standard, :simple, :stop, :whitspace, got '#{value}' for field '#{key}'"
117
+ end
118
+ end
119
+ wrapper
120
+ else
121
+ # yes, all fields has standard analyzer
122
+ org.apache.lucene.analysis.standard.StandardAnalyzer.new
123
+ end
124
+ end
125
+
126
+ # Returns true if it has one or more tokenized fields
127
+ def tokenized?
128
+ @infos.values.find{|field_info| field_info.tokenized?}
129
+ end
130
+
131
+ def [](key)
132
+ k = key.to_sym
133
+ $LUCENE_LOGGER.debug{"FieldInfos create new FieldInfo key '#{k}'"} if @infos[k].nil?
134
+ @infos[k] ||= DEFAULTS.dup
135
+ @infos[k]
136
+ end
137
+
138
+ def []=(key,value)
139
+ case value
140
+ when Hash then @infos[key] = FieldInfo.new(value)
141
+ when FieldInfo then @infos[key] = value
142
+ else raise ArgumentError.new("only accept Hash and FieldInfo, got #{value.class.to_s}")
143
+ end
144
+ end
145
+ end
146
+ end