redcar 0.9.2 → 0.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (234) hide show
  1. data/CHANGES +34 -4
  2. data/Rakefile +2 -1
  3. data/lib/redcar.rb +3 -3
  4. data/lib/redcar/installer.rb +2 -3
  5. data/plugins/application/features/step_definitions/dialog_steps.rb +7 -0
  6. data/plugins/application/features/step_definitions/key_steps.rb +18 -0
  7. data/plugins/application/features/step_definitions/menu_steps.rb +5 -6
  8. data/plugins/application/features/step_definitions/speedbar_steps.rb +29 -9
  9. data/plugins/application/features/step_definitions/tree_steps.rb +13 -0
  10. data/plugins/application/features/support/env.rb +39 -5
  11. data/plugins/application/features/support/fake_event.rb +12 -0
  12. data/plugins/application/lib/application.rb +5 -6
  13. data/plugins/application/lib/application/dialog.rb +53 -10
  14. data/plugins/application/lib/application/dialogs/modeless_list_dialog.rb +85 -0
  15. data/plugins/application/lib/application/keymap.rb +10 -8
  16. data/plugins/application/lib/application/menu.rb +38 -16
  17. data/plugins/application/lib/application/treebook.rb +30 -0
  18. data/plugins/application/lib/application/window.rb +20 -2
  19. data/plugins/application/spec/application/command/executor_spec.rb +1 -0
  20. data/plugins/application/spec/application/menu_spec.rb +26 -26
  21. data/plugins/application/spec/application/treebook_spec.rb +6 -6
  22. data/plugins/application/spec/spec_helper.rb +10 -1
  23. data/plugins/application_swt/lib/application_swt.rb +25 -3
  24. data/plugins/application_swt/lib/application_swt/dialog_adapter.rb +48 -27
  25. data/plugins/application_swt/lib/application_swt/dialogs/filter_list_dialog_controller.rb +22 -11
  26. data/plugins/application_swt/lib/application_swt/dialogs/modeless_dialog.rb +113 -0
  27. data/plugins/application_swt/lib/application_swt/dialogs/modeless_html_dialog.rb +85 -0
  28. data/plugins/application_swt/lib/application_swt/dialogs/modeless_list_dialog_controller.rb +143 -0
  29. data/plugins/application_swt/lib/application_swt/gradient.rb +61 -0
  30. data/plugins/application_swt/lib/application_swt/menu/binding_translator.rb +4 -4
  31. data/plugins/application_swt/lib/application_swt/notebook.rb +5 -8
  32. data/plugins/application_swt/lib/application_swt/speedbar.rb +1 -0
  33. data/plugins/application_swt/lib/application_swt/treebook.rb +6 -8
  34. data/plugins/application_swt/lib/application_swt/window.rb +85 -57
  35. data/plugins/application_swt/lib/swt/graphics_utils.rb +23 -0
  36. data/plugins/application_swt/lib/swt/vtab_folder.rb +7 -0
  37. data/plugins/application_swt/lib/swt/vtab_label.rb +1 -1
  38. data/plugins/application_swt/spec/application_swt/gradient_spec.rb +142 -0
  39. data/plugins/auto_completer/lib/auto_completer.rb +10 -42
  40. data/plugins/auto_completer/lib/auto_completer/list_dialog.rb +21 -0
  41. data/plugins/clojure/lib/clojure.rb +33 -0
  42. data/plugins/{repl/lib/repl/clojure_mirror.rb → clojure/lib/clojure/repl_mirror.rb} +16 -20
  43. data/plugins/clojure/plugin.rb +9 -0
  44. data/plugins/{repl/spec/repl/clojure_mirror_spec.rb → clojure/spec/clojure/repl_mirror_spec.rb} +12 -13
  45. data/plugins/clojure/spec/spec_helper.rb +5 -0
  46. data/plugins/{repl → clojure}/vendor/Wrapper.clj +0 -0
  47. data/plugins/{repl → clojure}/vendor/dummy +0 -0
  48. data/plugins/{repl → clojure}/vendor/enclojure-wrapper.jar +0 -0
  49. data/plugins/connection_manager/lib/connection_manager.rb +13 -13
  50. data/plugins/declarations/lib/declarations.rb +17 -6
  51. data/plugins/document_search/features/find.feature +389 -0
  52. data/plugins/document_search/features/find_and_replace.feature +723 -0
  53. data/plugins/document_search/features/replace.feature +69 -62
  54. data/plugins/document_search/lib/document_search.rb +81 -64
  55. data/plugins/document_search/lib/document_search/commands.rb +258 -0
  56. data/plugins/document_search/lib/document_search/find_and_replace_speedbar.rb +142 -0
  57. data/plugins/document_search/lib/document_search/find_speedbar.rb +102 -0
  58. data/plugins/document_search/lib/document_search/query_options.rb +45 -0
  59. data/plugins/edit_view/features/case_change.feature +9 -5
  60. data/plugins/edit_view/features/step_definitions/editing_steps.rb +19 -0
  61. data/plugins/edit_view/lib/edit_view.rb +15 -12
  62. data/plugins/edit_view/lib/edit_view/actions/arrow_keys.rb +12 -2
  63. data/plugins/edit_view/lib/edit_view/commands/text_conversion_commands.rb +1 -1
  64. data/plugins/edit_view/lib/edit_view/document.rb +129 -99
  65. data/plugins/edit_view_swt/lib/edit_view_swt.rb +33 -15
  66. data/plugins/encryption/encryption.rb +2 -0
  67. data/plugins/find-in-project/lib/find_in_project.rb +3 -5
  68. data/plugins/find-in-project/lib/find_in_project/views/index.html.erb +2 -0
  69. data/plugins/groovy/features/step_definitions/groovy_steps.rb +2 -2
  70. data/plugins/groovy/features/syntax_check_groovy.feature +3 -3
  71. data/plugins/groovy/lib/groovy.rb +38 -0
  72. data/plugins/groovy/lib/groovy/commands.rb +10 -0
  73. data/plugins/{repl/lib/repl/groovy_mirror.rb → groovy/lib/groovy/repl_mirror.rb} +33 -13
  74. data/plugins/groovy/lib/{syntax_check/groovy.rb → groovy/syntax_checker.rb} +13 -8
  75. data/plugins/groovy/plugin.rb +5 -4
  76. data/plugins/{repl/spec/repl/groovy_mirror_spec.rb → groovy/spec/groovy/repl_mirror_spec.rb} +14 -13
  77. data/plugins/groovy/spec/spec_helper.rb +5 -0
  78. data/plugins/html_view/assets/json2.js +476 -0
  79. data/plugins/html_view/lib/html_view.rb +1 -0
  80. data/plugins/java/features/fixtures/test.java +0 -0
  81. data/plugins/java/features/support/env.rb +27 -0
  82. data/plugins/java/features/syntax_check_java.feature +86 -0
  83. data/plugins/java/lib/syntax_check/java.rb +86 -0
  84. data/plugins/java/plugin.rb +7 -0
  85. data/plugins/javascript/features/fixtures/test2.js +5 -0
  86. data/plugins/javascript/features/step_definitions/javascript_steps.rb +16 -0
  87. data/plugins/javascript/features/support/env.rb +14 -0
  88. data/plugins/javascript/features/syntax_check_javascript.feature +46 -3
  89. data/plugins/javascript/lib/syntax_check/javascript.rb +15 -9
  90. data/plugins/line_tools/features/trim_line.feature +49 -0
  91. data/plugins/line_tools/lib/line_tools.rb +5 -1
  92. data/plugins/mirah/README +7 -0
  93. data/plugins/mirah/features/fixtures/test.mirah +2 -0
  94. data/plugins/mirah/features/syntax_check_mirah.feature +46 -0
  95. data/plugins/mirah/lib/mirah.rb +43 -0
  96. data/plugins/mirah/lib/mirah/my_error_handler.rb +22 -0
  97. data/plugins/mirah/lib/mirah/repl_mirror.rb +50 -0
  98. data/plugins/mirah/lib/mirah/syntax_checker.rb +38 -0
  99. data/plugins/mirah/plugin.rb +8 -0
  100. data/plugins/mirah/spec/mirah/repl_mirror_spec.rb +188 -0
  101. data/plugins/mirah/spec/spec_helper.rb +5 -0
  102. data/plugins/mirah/vendor/mirah-parser.jar +0 -0
  103. data/plugins/pair_highlighter/lib/pair_highlighter/document_controller.rb +24 -23
  104. data/plugins/plugin_manager_ui/lib/plugin_manager_ui.rb +10 -1
  105. data/plugins/plugin_manager_ui/views/index.html.erb +2 -0
  106. data/plugins/project/features/find_file.feature +40 -16
  107. data/plugins/project/features/highlight_focussed_tab.feature +16 -10
  108. data/plugins/project/features/step_definitions/find_file_steps.rb +11 -0
  109. data/plugins/project/features/step_definitions/project_tree_steps.rb +5 -1
  110. data/plugins/project/features/support/env.rb +5 -0
  111. data/plugins/project/lib/project/commands.rb +8 -1
  112. data/plugins/project/lib/project/dir_controller.rb +4 -1
  113. data/plugins/project/lib/project/find_file_dialog.rb +16 -12
  114. data/plugins/project/lib/project/manager.rb +30 -1
  115. data/plugins/project_search/vendor/lucene/CHANGELOG +147 -0
  116. data/plugins/project_search/vendor/lucene/CONTRIBUTORS +17 -0
  117. data/plugins/project_search/vendor/lucene/Gemfile +9 -0
  118. data/plugins/project_search/vendor/lucene/Gemfile.lock +33 -0
  119. data/plugins/project_search/vendor/lucene/LICENSE +19 -0
  120. data/plugins/project_search/vendor/lucene/README.rdoc +283 -0
  121. data/plugins/project_search/vendor/lucene/Rakefile +35 -0
  122. data/plugins/project_search/vendor/lucene/examples/active_model/serializers.rb +25 -0
  123. data/plugins/project_search/vendor/lucene/examples/active_model/validation.rb +26 -0
  124. data/plugins/project_search/vendor/lucene/examples/admin/Rakefile +4 -0
  125. data/plugins/project_search/vendor/lucene/examples/admin/admin.rb +29 -0
  126. data/plugins/project_search/vendor/lucene/examples/admin/public/jquery.js +4376 -0
  127. data/plugins/project_search/vendor/lucene/examples/admin/public/neo4j.css +153 -0
  128. data/plugins/project_search/vendor/lucene/examples/admin/public/neo_admin.js +18 -0
  129. data/plugins/project_search/vendor/lucene/examples/admin/spec/admin_spec.rb +26 -0
  130. data/plugins/project_search/vendor/lucene/examples/admin/views/index.erb +21 -0
  131. data/plugins/project_search/vendor/lucene/examples/filetree/README.rdoc +9 -0
  132. data/plugins/project_search/vendor/lucene/examples/filetree/app.rb +7 -0
  133. data/plugins/project_search/vendor/lucene/examples/filetree/batch.props +5 -0
  134. data/plugins/project_search/vendor/lucene/examples/filetree/features/step_definitions/add_steps.rb +121 -0
  135. data/plugins/project_search/vendor/lucene/examples/filetree/features/support/env.rb +30 -0
  136. data/plugins/project_search/vendor/lucene/examples/filetree/features/support/rspec_helper.rb +50 -0
  137. data/plugins/project_search/vendor/lucene/examples/filetree/features/treesizes.feature +19 -0
  138. data/plugins/project_search/vendor/lucene/examples/imdb/1_create_neo_db.rb +66 -0
  139. data/plugins/project_search/vendor/lucene/examples/imdb/2_index_db.rb +23 -0
  140. data/plugins/project_search/vendor/lucene/examples/imdb/README +12 -0
  141. data/plugins/project_search/vendor/lucene/examples/imdb/find_actors.rb +56 -0
  142. data/plugins/project_search/vendor/lucene/examples/imdb/install.sh +12 -0
  143. data/plugins/project_search/vendor/lucene/examples/imdb/model.rb +37 -0
  144. data/plugins/project_search/vendor/lucene/examples/railway/README +111 -0
  145. data/plugins/project_search/vendor/lucene/examples/railway/railnet-app.rb +31 -0
  146. data/plugins/project_search/vendor/lucene/examples/railway/railnet-data.rb +42 -0
  147. data/plugins/project_search/vendor/lucene/examples/rest/example.rb +41 -0
  148. data/plugins/project_search/vendor/lucene/examples/you_might_know/YouMightKnow.java +60 -0
  149. data/plugins/project_search/vendor/lucene/examples/you_might_know/all_simple_paths.rb +34 -0
  150. data/plugins/project_search/vendor/lucene/examples/you_might_know/nodes.rb +34 -0
  151. data/plugins/project_search/vendor/lucene/examples/you_might_know/you_might_know.rb +50 -0
  152. data/plugins/project_search/vendor/lucene/lib/lucene.rb +15 -0
  153. data/plugins/project_search/vendor/lucene/lib/lucene/config.rb +145 -0
  154. data/plugins/project_search/vendor/lucene/lib/lucene/document.rb +96 -0
  155. data/plugins/project_search/vendor/lucene/lib/lucene/field_info.rb +144 -0
  156. data/plugins/project_search/vendor/lucene/lib/lucene/hits.rb +54 -0
  157. data/plugins/project_search/vendor/lucene/lib/lucene/index.rb +267 -0
  158. data/plugins/project_search/vendor/lucene/lib/lucene/index_info.rb +146 -0
  159. data/plugins/project_search/vendor/lucene/lib/lucene/index_searcher.rb +157 -0
  160. data/plugins/project_search/vendor/lucene/lib/lucene/jars.rb +5 -0
  161. data/plugins/project_search/vendor/lucene/lib/lucene/query_dsl.rb +135 -0
  162. data/plugins/project_search/vendor/lucene/lib/lucene/transaction.rb +117 -0
  163. data/plugins/project_search/vendor/lucene/lib/lucene/version.rb +3 -0
  164. data/plugins/project_search/vendor/lucene/lucene.gemspec +23 -0
  165. data/plugins/project_search/vendor/lucene/spec/lucene/document_spec.rb +32 -0
  166. data/plugins/project_search/vendor/lucene/spec/lucene/field_info_spec.rb +70 -0
  167. data/plugins/project_search/vendor/lucene/spec/lucene/index_info_spec.rb +76 -0
  168. data/plugins/project_search/vendor/lucene/spec/lucene/index_spec.rb +643 -0
  169. data/plugins/project_search/vendor/lucene/spec/lucene/query_dsl_spec.rb +142 -0
  170. data/plugins/project_search/vendor/lucene/spec/lucene/sort_spec.rb +101 -0
  171. data/plugins/project_search/vendor/lucene/spec/lucene/spec_helper.rb +10 -0
  172. data/plugins/project_search/vendor/lucene/spec/lucene/transaction_spec.rb +118 -0
  173. data/plugins/redcar/features/alter_font_size.feature +25 -0
  174. data/plugins/redcar/features/step_definitions/font_steps.rb +34 -0
  175. data/plugins/redcar/redcar.rb +256 -43
  176. data/plugins/repl/features/command_editing.feature +55 -0
  177. data/plugins/repl/features/command_history.feature +75 -0
  178. data/plugins/repl/features/step_definitions/repl_steps.rb +17 -1
  179. data/plugins/repl/features/support/env.rb +24 -0
  180. data/plugins/repl/features/support/fake_repl.rb +16 -0
  181. data/plugins/repl/lib/repl.rb +17 -74
  182. data/plugins/repl/lib/repl/repl_command.rb +20 -0
  183. data/plugins/repl/lib/repl/repl_mirror.rb +168 -22
  184. data/plugins/repl/lib/repl/repl_tab.rb +131 -6
  185. data/plugins/repl/plugin.rb +1 -1
  186. data/plugins/repl/spec/repl/repl_mirror_spec.rb +72 -0
  187. data/plugins/repl/spec/spec_helper.rb +1 -1
  188. data/plugins/repl_swt/lib/repl_swt.rb +7 -0
  189. data/plugins/repl_swt/lib/repl_swt/key_listener.rb +43 -0
  190. data/plugins/repl_swt/plugin.rb +8 -0
  191. data/plugins/ruby/lib/ruby.rb +35 -0
  192. data/plugins/{repl/lib/repl/ruby_mirror.rb → ruby/lib/ruby/repl_mirror.rb} +12 -12
  193. data/plugins/ruby/lib/{syntax_check/ruby.rb → ruby/syntax_checker.rb} +3 -3
  194. data/plugins/ruby/plugin.rb +5 -4
  195. data/plugins/{repl/spec/repl/ruby_mirror_spec.rb → ruby/spec/ruby/repl_mirror_spec.rb} +38 -29
  196. data/plugins/ruby/spec/spec_helper.rb +5 -0
  197. data/plugins/runnables/lib/runnables.rb +2 -0
  198. data/plugins/runnables/lib/runnables/command_output_controller.rb +5 -0
  199. data/plugins/runnables/lib/runnables/output_processor.rb +14 -3
  200. data/plugins/runnables/views/command_output.html.erb +3 -2
  201. data/plugins/scm/lib/scm.rb +4 -2
  202. data/plugins/scm/lib/scm/diff_mirror.rb +6 -6
  203. data/plugins/scm_git/lib/scm_git.rb +136 -107
  204. data/plugins/scm_git/lib/scm_git/change.rb +28 -19
  205. data/plugins/snippets/lib/snippets/explorer.rb +2 -2
  206. data/plugins/swt/lib/swt/full_swt.rb +1 -0
  207. data/plugins/syntax_check/features/step_definitions/syntax_check_steps.rb +4 -0
  208. data/plugins/syntax_check/features/support/env.rb +3 -0
  209. data/plugins/syntax_check/lib/syntax_check.rb +71 -5
  210. data/plugins/syntax_check/lib/syntax_check/annotation.rb +61 -0
  211. data/plugins/test_runner/lib/test_runner.rb +39 -0
  212. data/plugins/test_runner/lib/test_runner/rspec_runner.rb +20 -0
  213. data/plugins/test_runner/lib/test_runner/run_test_command.rb +63 -0
  214. data/plugins/test_runner/lib/test_runner/runnable_test_runner.rb +26 -0
  215. data/plugins/test_runner/plugin.rb +8 -0
  216. data/plugins/test_runner/spec/run_test_command_spec.rb +51 -0
  217. data/plugins/test_runner/spec/spec_helper.rb +5 -0
  218. data/plugins/textmate/lib/textmate.rb +12 -2
  219. data/plugins/textmate/vendor/redcar-bundles/Bundles/HTML.tmbundle/Syntaxes/HTML.plist +0 -2
  220. data/plugins/textmate/vendor/redcar-bundles/Bundles/Mirah.tmbundle/Syntaxes/Mirah.plist +22 -0
  221. data/plugins/textmate/vendor/redcar-bundles/Bundles/Mirah.tmbundle/info.plist +12 -0
  222. data/plugins/textmate/vendor/redcar-bundles/Bundles/Ruby.tmbundle/Syntaxes/Ruby.plist +2 -0
  223. data/plugins/todo_list/lib/todo_list.rb +7 -0
  224. data/plugins/todo_list/lib/todo_list/todo_controller.rb +3 -1
  225. data/plugins/tree/lib/tree.rb +4 -0
  226. data/plugins/tree_view_swt/lib/tree_view_swt.rb +5 -0
  227. data/plugins/web_bookmarks/lib/web_bookmarks.rb +10 -0
  228. metadata +137 -22
  229. data/plugins/document_search/features/search.feature +0 -163
  230. data/plugins/document_search/lib/document_search/replace_all_command.rb +0 -27
  231. data/plugins/document_search/lib/document_search/replace_command.rb +0 -38
  232. data/plugins/document_search/lib/document_search/replace_next_command.rb +0 -27
  233. data/plugins/document_search/lib/document_search/search_and_replace.rb +0 -81
  234. data/plugins/ruby/README +0 -6
@@ -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