openbel-api 0.4.0-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. checksums.yaml +7 -0
  2. data/.gemspec +65 -0
  3. data/CHANGELOG.md +22 -0
  4. data/INSTALL.md +19 -0
  5. data/INSTALL_RUBY.md +107 -0
  6. data/LICENSE +191 -0
  7. data/README.md +208 -0
  8. data/app/openbel/api/app.rb +83 -0
  9. data/app/openbel/api/config.rb +45 -0
  10. data/app/openbel/api/config.ru +3 -0
  11. data/app/openbel/api/helpers/pager.rb +109 -0
  12. data/app/openbel/api/middleware/auth.rb +112 -0
  13. data/app/openbel/api/resources/adapters/basic_json.rb +52 -0
  14. data/app/openbel/api/resources/annotation.rb +141 -0
  15. data/app/openbel/api/resources/base.rb +16 -0
  16. data/app/openbel/api/resources/completion.rb +89 -0
  17. data/app/openbel/api/resources/evidence.rb +115 -0
  18. data/app/openbel/api/resources/evidence_transform.rb +143 -0
  19. data/app/openbel/api/resources/function.rb +98 -0
  20. data/app/openbel/api/resources/match_result.rb +79 -0
  21. data/app/openbel/api/resources/namespace.rb +174 -0
  22. data/app/openbel/api/routes/annotations.rb +168 -0
  23. data/app/openbel/api/routes/authenticate.rb +108 -0
  24. data/app/openbel/api/routes/base.rb +326 -0
  25. data/app/openbel/api/routes/datasets.rb +519 -0
  26. data/app/openbel/api/routes/evidence.rb +330 -0
  27. data/app/openbel/api/routes/expressions.rb +560 -0
  28. data/app/openbel/api/routes/functions.rb +41 -0
  29. data/app/openbel/api/routes/namespaces.rb +382 -0
  30. data/app/openbel/api/routes/root.rb +39 -0
  31. data/app/openbel/api/schemas.rb +34 -0
  32. data/app/openbel/api/schemas/annotation_collection.schema.json +20 -0
  33. data/app/openbel/api/schemas/annotation_resource.schema.json +36 -0
  34. data/app/openbel/api/schemas/annotation_value_collection.schema.json +21 -0
  35. data/app/openbel/api/schemas/annotation_value_resource.schema.json +35 -0
  36. data/app/openbel/api/schemas/completion_collection.schema.json +21 -0
  37. data/app/openbel/api/schemas/completion_resource.schema.json +146 -0
  38. data/app/openbel/api/schemas/evidence.schema.json +198 -0
  39. data/app/openbel/api/schemas/evidence_collection.schema.json +98 -0
  40. data/app/openbel/api/schemas/evidence_resource.schema.json +29 -0
  41. data/app/openbel/api/schemas/namespace_value_collection.schema.json +21 -0
  42. data/app/openbel/api/schemas/namespace_value_resource.schema.json +43 -0
  43. data/app/openbel/api/util.rb +11 -0
  44. data/bin/openbel-api +78 -0
  45. data/bin/openbel-config +46 -0
  46. data/config/async_evidence.rb +12 -0
  47. data/config/async_jena.rb +14 -0
  48. data/config/config.yml +31 -0
  49. data/config/server_config.rb +184 -0
  50. data/lib/openbel/api/cache/cache.rb +30 -0
  51. data/lib/openbel/api/config/config.rb +33 -0
  52. data/lib/openbel/api/evidence/api.rb +39 -0
  53. data/lib/openbel/api/evidence/facet_api.rb +18 -0
  54. data/lib/openbel/api/evidence/facet_filter.rb +83 -0
  55. data/lib/openbel/api/evidence/mongo.rb +247 -0
  56. data/lib/openbel/api/evidence/mongo_facet.rb +105 -0
  57. data/lib/openbel/api/helpers/dependency_graph.rb +52 -0
  58. data/lib/openbel/api/model/rdf_resource.rb +74 -0
  59. data/lib/openbel/api/plugin/cache/kyotocabinet.rb +85 -0
  60. data/lib/openbel/api/plugin/configure_plugins.rb +97 -0
  61. data/lib/openbel/api/plugin/evidence/evidence.rb +58 -0
  62. data/lib/openbel/api/plugin/plugin.rb +99 -0
  63. data/lib/openbel/api/plugin/plugin_manager.rb +20 -0
  64. data/lib/openbel/api/plugin/plugin_repository.rb +60 -0
  65. data/lib/openbel/api/storage/cache_proxy.rb +74 -0
  66. data/lib/openbel/api/storage/triple_storage.rb +43 -0
  67. metadata +379 -0
@@ -0,0 +1,41 @@
1
+ require 'bel'
2
+
3
+ module OpenBEL
4
+ module Routes
5
+
6
+ class Functions < Base
7
+ include BEL::Language
8
+
9
+ SORTED_FUNCTIONS = FUNCTIONS.values.uniq.sort_by { |fx|
10
+ fx[:short_form]
11
+ }
12
+
13
+ options '/api/functions' do
14
+ response.headers['Allow'] = 'OPTIONS,GET'
15
+ status 200
16
+ end
17
+
18
+ options '/api/functions/:fx' do
19
+ response.headers['Allow'] = 'OPTIONS,GET'
20
+ status 200
21
+ end
22
+
23
+ get '/api/functions' do
24
+ render(SORTED_FUNCTIONS, :function_collection)
25
+ end
26
+
27
+ # BEL Completion
28
+ get '/api/functions/:fx' do
29
+ fx_match = FUNCTIONS[params[:fx].to_sym]
30
+ halt 404 unless fx_match
31
+
32
+ render(
33
+ [fx_match],
34
+ :function_collection
35
+ )
36
+ end
37
+ end
38
+ end
39
+ end
40
+ # vim: ts=2 sw=2:
41
+ # encoding: utf-8
@@ -0,0 +1,382 @@
1
+ require 'bel'
2
+ require 'cgi'
3
+ require 'multi_json'
4
+ require 'uri'
5
+
6
+ module OpenBEL
7
+ module Routes
8
+
9
+ # REST API for retrieving namespaces and values. Provides the following capabilities:
10
+ #
11
+ # * Retrieve namespaces.
12
+ # * Retrieve values for a namespace using the identifier, preferred name, or title.
13
+ # * Retrieve equivalences for one or more values.
14
+ # * Retrieve equivalences in a target namespace for one or more values.
15
+ # * Retrieve orthologs for one or more values.
16
+ # * Retrieve orthologs in a target namespace for one or more values.
17
+ class Namespaces < Base
18
+
19
+ RESULT_TYPES = {
20
+ :resource => :all,
21
+ :name => :prefLabel,
22
+ :identifier => :identifier,
23
+ :title => :title
24
+ }
25
+
26
+ def initialize(app)
27
+ super
28
+
29
+ # RdfRepository using Jena.
30
+ @rr = BEL::RdfRepository.plugins[:jena].create_repository(
31
+ :tdb_directory => OpenBEL::Settings[:resource_rdf][:jena][:tdb_directory]
32
+ )
33
+
34
+ # Namespaces using RdfRepository
35
+ @namespaces = BEL::Resource::Namespaces.new(@rr)
36
+
37
+ # Resource Search using SQLite.
38
+ @search = BEL::Resource::Search.plugins[:sqlite].create_search(
39
+ :database_file => OpenBEL::Settings[:resource_search][:sqlite][:database_file]
40
+ )
41
+ end
42
+
43
+ options '/api/namespaces' do
44
+ response.headers['Allow'] = 'OPTIONS,GET'
45
+ status 200
46
+ end
47
+
48
+ options '/api/namespaces/:namespace' do
49
+ response.headers['Allow'] = 'OPTIONS,GET'
50
+ status 200
51
+ end
52
+
53
+ options '/api/namespaces/:namespace/equivalents' do
54
+ response.headers['Allow'] = 'OPTIONS,POST,GET'
55
+ status 200
56
+ end
57
+
58
+ options '/api/namespaces/:namespace/orthologs' do
59
+ response.headers['Allow'] = 'OPTIONS,POST,GET'
60
+ status 200
61
+ end
62
+
63
+ options '/api/namespaces/:namespace/values/:value' do
64
+ response.headers['Allow'] = 'OPTIONS,GET'
65
+ status 200
66
+ end
67
+
68
+ options '/api/namespaces/:namespace/values/:value/equivalents' do
69
+ response.headers['Allow'] = 'OPTIONS,GET'
70
+ status 200
71
+ end
72
+
73
+ options '/api/namespaces/:namespace/values/:value/equivalents/:target' do
74
+ response.headers['Allow'] = 'OPTIONS,GET'
75
+ status 200
76
+ end
77
+
78
+ options '/api/namespaces/:namespace/values/:value/orthologs' do
79
+ response.headers['Allow'] = 'OPTIONS,GET'
80
+ status 200
81
+ end
82
+
83
+ options '/api/namespaces/:namespace/values/:value/orthologs/:target' do
84
+ response.headers['Allow'] = 'OPTIONS,GET'
85
+ status 200
86
+ end
87
+
88
+ get '/api/namespaces' do
89
+ namespaces = @namespaces.each.to_a
90
+
91
+ halt 404 if not namespaces or namespaces.empty?
92
+
93
+ render_collection(
94
+ namespaces.sort { |x,y|
95
+ x.prefLabel.to_s <=> y.prefLabel.to_s
96
+ },
97
+ :namespace
98
+ )
99
+ end
100
+
101
+ get '/api/namespaces/values' do
102
+ start = (params[:start] || 0).to_i
103
+ size = (params[:size] || -1).to_i
104
+ size = -1 if size <= 0
105
+ faceted = as_bool(params[:faceted])
106
+ halt 501 if faceted
107
+
108
+ filter_hash = Hash.new{ |h,k| h[k] = Hash.new(&h.default_proc) }
109
+ filter_params = CGI::parse(env["QUERY_STRING"])['filter']
110
+ filter_params.each do |filter|
111
+ filter = read_filter(filter)
112
+ halt 400 unless ['category', 'name', 'value'].all? { |f| filter.include? f}
113
+ filter_hash[filter['category']][filter['name']] = filter['value']
114
+ end
115
+
116
+ halt 404 unless filter_hash['fts']['search'].is_a?(String)
117
+ match = filter_hash['fts']['search']
118
+ halt 404 unless match.length > 1
119
+
120
+ match_results = @search.search(wildcard_match(match), :namespace_concept, nil, nil,
121
+ :start => start,
122
+ :size => size
123
+ ).map { |result|
124
+ value = OpenBEL::Resource::Namespaces::NamespaceValueSearchResult.new(@rr, result.uri)
125
+ value.match_text = result.snippet
126
+ value
127
+ }.to_a
128
+
129
+ halt 404 if not match_results or match_results.empty?
130
+ render_collection(
131
+ match_results,
132
+ :namespace_value,
133
+ :adapter => Oat::Adapters::BasicJson
134
+ )
135
+ end
136
+
137
+ get '/api/namespaces/:namespace' do |namespace|
138
+ namespace = @namespaces.find(namespace).first
139
+
140
+ halt 404 unless namespace
141
+
142
+ status 200
143
+ render_resource(
144
+ namespace,
145
+ :namespace
146
+ )
147
+ end
148
+
149
+ get '/api/namespaces/:namespace/values' do |namespace|
150
+ namespace = @namespaces.find(namespace).first
151
+ halt 404 unless namespace
152
+
153
+ start = (params[:start] || 0).to_i
154
+ size = (params[:size] || -1).to_i
155
+ size = -1 if size <= 0
156
+ faceted = as_bool(params[:faceted])
157
+ halt 501 if faceted
158
+
159
+ filter_hash = Hash.new{ |h,k| h[k] = Hash.new(&h.default_proc) }
160
+ filter_params = CGI::parse(env["QUERY_STRING"])['filter']
161
+ filter_params.each do |filter|
162
+ filter = read_filter(filter)
163
+ halt 400 unless ['category', 'name', 'value'].all? { |f| filter.include? f}
164
+ filter_hash[filter['category']][filter['name']] = filter['value']
165
+ end
166
+
167
+ halt 404 unless filter_hash['fts']['search'].is_a?(String)
168
+ match = filter_hash['fts']['search']
169
+ halt 404 unless match.length > 1
170
+
171
+ match_results = @search.search(wildcard_match(match), :namespace_concept, namespace.uri.to_s, nil,
172
+ :start => start,
173
+ :size => size
174
+ ).map { |result|
175
+ value = OpenBEL::Resource::Namespaces::NamespaceValueSearchResult.new(@rr, result.uri)
176
+ value.match_text = result.snippet
177
+ value
178
+ }.to_a
179
+
180
+ halt 404 if not match_results or match_results.empty?
181
+ render_collection(
182
+ match_results,
183
+ :namespace_value,
184
+ :adapter => Oat::Adapters::BasicJson
185
+ )
186
+ end
187
+
188
+ # TODO Requires a Namespace API to retrieve equivalents for matched values.
189
+ # get '/api/namespaces/:namespace/equivalents' do |namespace|
190
+ # halt 400 unless request.params['value']
191
+
192
+ # values = CGI::parse(env["QUERY_STRING"])['value']
193
+ # options = {}
194
+ # if request.params['namespace']
195
+ # options[:target] = request.params['namespace']
196
+ # end
197
+
198
+ # if request.params['result']
199
+ # result = request.params['result'].to_sym
200
+ # halt 400 unless RESULT_TYPES.include? result
201
+ # options[:result] = RESULT_TYPES[result]
202
+ # end
203
+
204
+ # eq_mapping = @api.find_equivalents(namespace, values, options)
205
+ # halt 404 if eq_mapping.values.all? { |v| v == nil }
206
+ # response.headers['Content-Type'] = 'application/json'
207
+ # MultiJson.dump eq_mapping
208
+ # end
209
+
210
+ # TODO Requires a Namespace API to retrieve equivalents for matched values.
211
+ # post '/api/namespaces/:namespace/equivalents' do |namespace|
212
+ # halt 400 unless request.media_type == 'application/x-www-form-urlencoded'
213
+
214
+ # content = request.body.read
215
+ # halt 400 if content.empty?
216
+
217
+ # params = Hash[
218
+ # URI.decode_www_form(content).group_by(&:first).map{
219
+ # |k,a| [k,a.map(&:last)]
220
+ # }
221
+ # ]
222
+
223
+ # halt 400 unless params['value']
224
+
225
+ # options = {}
226
+ # if params['namespace']
227
+ # options[:target] = params['namespace'].first
228
+ # end
229
+
230
+ # if params['result']
231
+ # result = params['result'].first.to_sym
232
+ # halt 400 unless RESULT_TYPES.include? result
233
+ # options[:result] = RESULT_TYPES[result]
234
+ # end
235
+
236
+ # eq_mapping = @api.find_equivalents(namespace, params['value'], options)
237
+ # response.headers['Content-Type'] = 'application/json'
238
+ # MultiJson.dump eq_mapping
239
+ # end
240
+
241
+ # TODO Requires a Namespace API to retrieve orthologs for matched values.
242
+ # get '/api/namespaces/:namespace/orthologs' do |namespace|
243
+ # halt 400 unless request.params['value']
244
+
245
+ # values = CGI::parse(env["QUERY_STRING"])['value']
246
+ # options = {}
247
+ # if request.params['namespace']
248
+ # options[:target] = request.params['namespace']
249
+ # end
250
+
251
+ # if request.params['result']
252
+ # result = request.params['result'].to_sym
253
+ # halt 400 unless RESULT_TYPES.include? result
254
+ # options[:result] = RESULT_TYPES[result]
255
+ # end
256
+
257
+ # orth_mapping = @api.find_orthologs(namespace, values, options)
258
+ # halt 404 if orth_mapping.values.all? { |v| v == nil }
259
+ # response.headers['Content-Type'] = 'application/json'
260
+ # MultiJson.dump orth_mapping
261
+ # end
262
+
263
+ # TODO Requires a Namespace API to retrieve orthologs for matched values.
264
+ # post '/api/namespaces/:namespace/orthologs' do |namespace|
265
+ # halt 400 unless request.media_type == 'application/x-www-form-urlencoded'
266
+
267
+ # content = request.body.read
268
+ # halt 400 if content.empty?
269
+
270
+ # params = Hash[
271
+ # URI.decode_www_form(content).group_by(&:first).map{
272
+ # |k,a| [k,a.map(&:last)]
273
+ # }
274
+ # ]
275
+
276
+ # halt 400 unless params['value']
277
+
278
+ # options = {}
279
+ # if params['namespace']
280
+ # options[:target] = params['namespace'].first
281
+ # end
282
+
283
+ # if params['result']
284
+ # result = params['result'].first.to_sym
285
+ # halt 400 unless RESULT_TYPES.include? result
286
+ # options[:result] = RESULT_TYPES[result]
287
+ # end
288
+
289
+ # orth_mapping = @api.find_orthologs(namespace, params['value'], options)
290
+ # response.headers['Content-Type'] = 'application/json'
291
+ # MultiJson.dump orth_mapping
292
+ # end
293
+
294
+ get '/api/namespaces/:namespace/values/:value' do |namespace, value|
295
+ namespace = @namespaces.find(namespace).first
296
+ halt 404 unless namespace
297
+
298
+ value = namespace.find(value).first
299
+ halt 404 unless value
300
+
301
+ status 200
302
+ render_resource(
303
+ value,
304
+ :namespace_value,
305
+ :adapter => Oat::Adapters::BasicJson
306
+ )
307
+ end
308
+
309
+ get '/api/namespaces/:namespace/values/:value/equivalents' do |namespace, value|
310
+ namespace = @namespaces.find(namespace).first
311
+ halt 404 unless namespace
312
+
313
+ value = namespace.find(value).first
314
+ halt 404 unless value
315
+
316
+ equivalents = value.equivalents.to_a
317
+ halt 404 if not equivalents or equivalents.empty?
318
+
319
+ render_collection(
320
+ equivalents,
321
+ :namespace_value,
322
+ :adapter => Oat::Adapters::BasicJson
323
+ )
324
+ end
325
+
326
+ get '/api/namespaces/:namespace/values/:value/equivalents/:target' do |namespace, value, target|
327
+ namespace = @namespaces.find(namespace).first
328
+ halt 404 unless namespace
329
+ halt 404 unless @namespaces.find(target).first
330
+
331
+ value = namespace.find(value).first
332
+ halt 404 unless value
333
+
334
+ target_equivalents = value.equivalents(target).to_a
335
+ halt 404 if not target_equivalents or target_equivalents.empty?
336
+
337
+ render_collection(
338
+ target_equivalents,
339
+ :namespace_value,
340
+ :adapter => Oat::Adapters::BasicJson
341
+ )
342
+ end
343
+
344
+ get '/api/namespaces/:namespace/values/:value/orthologs' do |namespace, value|
345
+ namespace = @namespaces.find(namespace).first
346
+ halt 404 unless namespace
347
+
348
+ value = namespace.find(value).first
349
+ halt 404 unless value
350
+
351
+ orthologs = value.orthologs.to_a
352
+ halt 404 if not orthologs or orthologs.empty?
353
+
354
+ render_collection(
355
+ orthologs,
356
+ :namespace_value,
357
+ :adapter => Oat::Adapters::BasicJson
358
+ )
359
+ end
360
+
361
+ get '/api/namespaces/:namespace/values/:value/orthologs/:target' do |namespace, value, target|
362
+ namespace = @namespaces.find(namespace).first
363
+ halt 404 unless namespace
364
+ halt 404 unless @namespaces.find(target).first
365
+
366
+ value = namespace.find(value).first
367
+ halt 404 unless value
368
+
369
+ target_orthologs = value.orthologs(target).to_a
370
+ halt 404 if not target_orthologs or target_orthologs.empty?
371
+
372
+ render_collection(
373
+ target_orthologs,
374
+ :namespace_value,
375
+ :adapter => Oat::Adapters::BasicJson
376
+ )
377
+ end
378
+ end
379
+ end
380
+ end
381
+ # vim: ts=2 sw=2:
382
+ # encoding: utf-8
@@ -0,0 +1,39 @@
1
+ module OpenBEL
2
+ module Routes
3
+
4
+ class Root < Base
5
+
6
+ options '/api' do
7
+ response.headers['Allow'] = 'OPTIONS,GET'
8
+ status 200
9
+ end
10
+
11
+ get '/api' do
12
+ response.headers['Content-Type'] = 'application/hal+json'
13
+ MultiJson.dump({
14
+ :_links => {
15
+ :item => [
16
+ {
17
+ :href => "#{base_url}/api/annotations"
18
+ },
19
+ {
20
+ :href => "#{base_url}/api/evidence"
21
+ },
22
+ {
23
+ :href => "#{base_url}/api/expressions"
24
+ },
25
+ {
26
+ :href => "#{base_url}/api/functions"
27
+ },
28
+ {
29
+ :href => "#{base_url}/api/namespaces"
30
+ }
31
+ ]
32
+ }
33
+ })
34
+ end
35
+ end
36
+ end
37
+ end
38
+ # vim: ts=2 sw=2:
39
+ # encoding: utf-8