openbel-api 0.5.1-java → 0.6.1-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.
- checksums.yaml +4 -4
- data/.gemspec +14 -6
- data/CHANGELOG.md +32 -0
- data/README.md +2 -2
- data/VERSION +1 -1
- data/app/openbel/api/config.rb +12 -0
- data/app/openbel/api/helpers/base.rb +17 -0
- data/app/openbel/api/helpers/evidence.rb +74 -0
- data/app/openbel/api/helpers/filters.rb +94 -0
- data/app/openbel/api/helpers/translators.rb +73 -0
- data/app/openbel/api/resources/evidence_transform.rb +1 -13
- data/app/openbel/api/routes/authenticate.rb +0 -92
- data/app/openbel/api/routes/base.rb +19 -5
- data/app/openbel/api/routes/datasets.rb +65 -151
- data/app/openbel/api/routes/evidence.rb +10 -95
- data/config/config.yml +4 -6
- data/lib/openbel/api/evidence/api.rb +8 -0
- data/lib/openbel/api/evidence/facet_filter.rb +3 -3
- data/lib/openbel/api/evidence/mongo.rb +304 -44
- data/lib/openbel/api/evidence/mongo_facet.rb +173 -66
- metadata +112 -26
- data/config/async_evidence.rb +0 -12
- data/config/async_jena.rb +0 -14
@@ -1,100 +1,8 @@
|
|
1
|
-
require 'uri'
|
2
|
-
require 'rest-client'
|
3
|
-
|
4
|
-
def current_host(env)
|
5
|
-
scheme = env['rack.url_scheme'] || 'http'
|
6
|
-
host = env['HTTP_HOST']
|
7
|
-
"#{scheme}://#{host}"
|
8
|
-
end
|
9
|
-
|
10
|
-
def current_path(env)
|
11
|
-
scheme = env['rack.url_scheme'] || 'http'
|
12
|
-
host = env['HTTP_HOST']
|
13
|
-
path = env['PATH_INFO']
|
14
|
-
"#{scheme}://#{host}#{path}"
|
15
|
-
end
|
16
|
-
|
17
1
|
module OpenBEL
|
18
2
|
module Routes
|
19
3
|
|
20
4
|
class Authenticate < Base
|
21
5
|
|
22
|
-
get '/api/authenticate' do
|
23
|
-
state = params[:state]
|
24
|
-
code = params[:code]
|
25
|
-
if code.nil?
|
26
|
-
default_connection = OpenBEL::Settings[:auth][:default_connection]
|
27
|
-
default_auth_url = current_path(env) + "/#{default_connection}"
|
28
|
-
if not state.nil?
|
29
|
-
default_auth_url += "?state=#{state}"
|
30
|
-
end
|
31
|
-
redirect to(default_auth_url)
|
32
|
-
end
|
33
|
-
|
34
|
-
domain = OpenBEL::Settings[:auth][:domain]
|
35
|
-
id = OpenBEL::Settings[:auth][:id]
|
36
|
-
secret = OpenBEL::Settings[:auth][:secret]
|
37
|
-
|
38
|
-
callback_url = current_path(env)
|
39
|
-
payload = {
|
40
|
-
client_id: id,
|
41
|
-
client_secret: secret,
|
42
|
-
redirect_uri: callback_url,
|
43
|
-
code: code,
|
44
|
-
grant_type: :authorization_code
|
45
|
-
}
|
46
|
-
|
47
|
-
token_url = "https://#{domain}/oauth/token"
|
48
|
-
body = payload.to_json
|
49
|
-
|
50
|
-
begin
|
51
|
-
token_response = RestClient.post token_url, body,
|
52
|
-
:content_type => :json,
|
53
|
-
:accept => :json
|
54
|
-
rescue => e
|
55
|
-
hdrs = {'Content-Type' => 'application/json'}
|
56
|
-
msg = {error: e.response }
|
57
|
-
return [401, hdrs, [msg.to_json]]
|
58
|
-
end
|
59
|
-
|
60
|
-
token_response = JSON.parse(token_response)
|
61
|
-
access_token = token_response['access_token']
|
62
|
-
jwt = token_response['id_token']
|
63
|
-
|
64
|
-
user_url = "https://#{domain}/userinfo?access_token=#{access_token}"
|
65
|
-
begin
|
66
|
-
user_response = RestClient.get user_url, :accept => :json
|
67
|
-
rescue => e
|
68
|
-
hdrs = {'Content-Type' => 'application/json'}
|
69
|
-
msg = {error: e.response }
|
70
|
-
return [401, hdrs, [msg.to_json]]
|
71
|
-
end
|
72
|
-
|
73
|
-
email = JSON.parse(user_response)['email']
|
74
|
-
hdrs = {'Content-Type' => 'application/json'}
|
75
|
-
msg = {success: email}
|
76
|
-
cookies[:jwt] = jwt
|
77
|
-
if not state.nil?
|
78
|
-
redirect to(state + "?jwt=#{jwt}")
|
79
|
-
else
|
80
|
-
[200, hdrs, [msg.to_json]]
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
get '/api/authenticate/:connection' do
|
85
|
-
state = params[:state]
|
86
|
-
redirect_setting = OpenBEL::Settings[:auth][:redirect]
|
87
|
-
connection = params[:connection]
|
88
|
-
redirect_uri = current_host(env) + '/api/authenticate'
|
89
|
-
auth_url = "#{redirect_setting}"
|
90
|
-
auth_url += "&redirect_uri=#{redirect_uri}"
|
91
|
-
auth_url += "&connection=#{connection}"
|
92
|
-
if not state.nil?
|
93
|
-
auth_url += "&state=#{state}"
|
94
|
-
end
|
95
|
-
redirect to(auth_url)
|
96
|
-
end
|
97
|
-
|
98
6
|
get '/api/authentication-enabled' do
|
99
7
|
enabled = OpenBEL::Settings[:auth][:enabled]
|
100
8
|
hdrs = {'Content-Type' => 'application/json'}
|
@@ -21,14 +21,14 @@ module OpenBEL
|
|
21
21
|
include OpenBEL::Resource::Namespaces
|
22
22
|
include OpenBEL::Schemas
|
23
23
|
|
24
|
-
DEFAULT_CONTENT_TYPE
|
25
|
-
|
24
|
+
DEFAULT_CONTENT_TYPE = 'application/hal+json'
|
25
|
+
DEFAULT_CONTENT_TYPE_ID = :hal
|
26
|
+
SPOKEN_CONTENT_TYPES = %w[application/hal+json application/json]
|
26
27
|
SPOKEN_CONTENT_TYPES.concat(
|
27
28
|
BEL::Translator.plugins.values.flat_map { |p| p.media_types.map(&:to_s) }
|
28
29
|
)
|
29
|
-
|
30
|
-
|
31
|
-
RESOURCE_SERIALIZERS = {
|
30
|
+
SCHEMA_BASE_URL = 'http://next.belframework.org/schemas/'
|
31
|
+
RESOURCE_SERIALIZERS = {
|
32
32
|
:annotation => AnnotationResourceSerializer,
|
33
33
|
:annotation_collection => AnnotationCollectionSerializer,
|
34
34
|
:annotation_value => AnnotationValueResourceSerializer,
|
@@ -80,6 +80,16 @@ module OpenBEL
|
|
80
80
|
SCHEMA_BASE_URL + "#{name}.schema.json"
|
81
81
|
end
|
82
82
|
|
83
|
+
def wants_default?
|
84
|
+
if params[:format]
|
85
|
+
return params[:format] == DEFAULT_CONTENT_TYPE
|
86
|
+
end
|
87
|
+
|
88
|
+
request.accept.any? { |accept_entry|
|
89
|
+
accept_entry.to_s == DEFAULT_CONTENT_TYPE
|
90
|
+
}
|
91
|
+
end
|
92
|
+
|
83
93
|
def validate_media_type!(content_type, options = {})
|
84
94
|
ctype = request.content_type
|
85
95
|
valid = ctype.start_with? content_type
|
@@ -143,6 +153,10 @@ module OpenBEL
|
|
143
153
|
end
|
144
154
|
end
|
145
155
|
|
156
|
+
def write_filter(filter)
|
157
|
+
MultiJson.dump(filter)
|
158
|
+
end
|
159
|
+
|
146
160
|
def render_json(obj, media_type = 'application/hal+json', profile = nil)
|
147
161
|
ctype =
|
148
162
|
if profile
|
@@ -1,10 +1,13 @@
|
|
1
1
|
require 'bel'
|
2
|
+
require 'bel/util'
|
2
3
|
require 'rdf'
|
3
4
|
require 'cgi'
|
4
5
|
require 'multi_json'
|
5
6
|
require 'openbel/api/evidence/mongo'
|
6
7
|
require 'openbel/api/evidence/facet_filter'
|
7
8
|
require_relative '../resources/evidence_transform'
|
9
|
+
require_relative '../helpers/evidence'
|
10
|
+
require_relative '../helpers/filters'
|
8
11
|
require_relative '../helpers/pager'
|
9
12
|
|
10
13
|
module OpenBEL
|
@@ -16,7 +19,6 @@ module OpenBEL
|
|
16
19
|
include OpenBEL::Helpers
|
17
20
|
|
18
21
|
DEFAULT_TYPE = 'application/hal+json'
|
19
|
-
|
20
22
|
ACCEPTED_TYPES = {
|
21
23
|
:bel => 'application/bel',
|
22
24
|
:xml => 'application/xml',
|
@@ -24,9 +26,14 @@ module OpenBEL
|
|
24
26
|
:json => 'application/json',
|
25
27
|
}
|
26
28
|
|
29
|
+
MONGO_BATCH = 500
|
30
|
+
FACET_THRESHOLD = 10000
|
31
|
+
|
27
32
|
def initialize(app)
|
28
33
|
super
|
29
34
|
|
35
|
+
BEL.translator(:rdf)
|
36
|
+
|
30
37
|
# Evidence API using Mongo.
|
31
38
|
mongo = OpenBEL::Settings[:evidence_store][:mongo]
|
32
39
|
@api = OpenBEL::Evidence::Evidence.new(mongo)
|
@@ -36,9 +43,6 @@ module OpenBEL
|
|
36
43
|
:tdb_directory => OpenBEL::Settings[:resource_rdf][:jena][:tdb_directory]
|
37
44
|
)
|
38
45
|
|
39
|
-
# Load RDF monkeypatches.
|
40
|
-
BEL::Translator.plugins[:rdf].create_translator
|
41
|
-
|
42
46
|
# Annotations using RdfRepository
|
43
47
|
annotations = BEL::Resource::Annotations.new(@rr)
|
44
48
|
@annotation_transform = AnnotationTransform.new(annotations)
|
@@ -233,35 +237,66 @@ the "multipart/form-data" content type. Allowed dataset content types are: #{ACC
|
|
233
237
|
# Create dataset in RDF.
|
234
238
|
@rr.insert_statements(void_dataset)
|
235
239
|
|
236
|
-
dataset
|
240
|
+
dataset = retrieve_dataset(void_dataset_uri)
|
241
|
+
dataset_id = dataset[:identifier]
|
242
|
+
|
243
|
+
# Add batches of read evidence objects; save to Mongo and RDF.
|
244
|
+
# TODO Add JRuby note regarding Enumerator threading.
|
245
|
+
evidence_count = 0
|
246
|
+
evidence_batch = []
|
237
247
|
|
238
|
-
#
|
239
|
-
|
240
|
-
slice.map! do |ev|
|
241
|
-
# Standardize annotations from experiment_context.
|
242
|
-
@annotation_transform.transform_evidence!(ev, base_url)
|
248
|
+
# Clear out all facets before loading dataset.
|
249
|
+
@api.delete_facets
|
243
250
|
|
244
|
-
|
245
|
-
|
251
|
+
BEL.evidence(io, type).each do |ev|
|
252
|
+
# Standardize annotations from experiment_context.
|
253
|
+
@annotation_transform.transform_evidence!(ev, base_url)
|
246
254
|
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
255
|
+
ev.metadata[:dataset] = dataset_id
|
256
|
+
facets = map_evidence_facets(ev)
|
257
|
+
ev.bel_statement = ev.bel_statement.to_s
|
258
|
+
hash = BEL.object_convert(String, ev.to_h) { |str|
|
259
|
+
str.gsub(/\n/, "\\n").gsub(/\r/, "\\r")
|
260
|
+
}
|
261
|
+
hash[:facets] = facets
|
262
|
+
# Create dataset field for efficient removal.
|
263
|
+
hash[:_dataset] = dataset_id
|
251
264
|
|
252
|
-
|
253
|
-
|
254
|
-
|
265
|
+
evidence_batch << hash
|
266
|
+
|
267
|
+
if evidence_batch.size == MONGO_BATCH
|
268
|
+
_ids = @api.create_evidence(evidence_batch)
|
269
|
+
|
270
|
+
dataset_parts = _ids.map { |object_id|
|
271
|
+
RDF::Statement.new(void_dataset_uri, RDF::DC.hasPart, object_id.to_s)
|
272
|
+
}
|
273
|
+
@rr.insert_statements(dataset_parts)
|
274
|
+
|
275
|
+
evidence_batch.clear
|
276
|
+
|
277
|
+
# Clear out all facets after FACET_THRESHOLD nanopubs have been seen.
|
278
|
+
evidence_count += MONGO_BATCH
|
279
|
+
if evidence_count >= FACET_THRESHOLD
|
280
|
+
@api.delete_facets
|
281
|
+
evidence_count = 0
|
282
|
+
end
|
255
283
|
end
|
284
|
+
end
|
256
285
|
|
257
|
-
|
286
|
+
unless evidence_batch.empty?
|
287
|
+
_ids = @api.create_evidence(evidence_batch)
|
258
288
|
|
259
289
|
dataset_parts = _ids.map { |object_id|
|
260
290
|
RDF::Statement.new(void_dataset_uri, RDF::DC.hasPart, object_id.to_s)
|
261
291
|
}
|
262
292
|
@rr.insert_statements(dataset_parts)
|
293
|
+
|
294
|
+
evidence_batch.clear
|
263
295
|
end
|
264
296
|
|
297
|
+
# Clear out all facets after the dataset is completely loaded.
|
298
|
+
@api.delete_facets
|
299
|
+
|
265
300
|
status 201
|
266
301
|
headers 'Location' => void_dataset_uri.to_s
|
267
302
|
end
|
@@ -297,142 +332,19 @@ the "multipart/form-data" content type. Allowed dataset content types are: #{ACC
|
|
297
332
|
start = (params[:start] || 0).to_i
|
298
333
|
size = (params[:size] || 0).to_i
|
299
334
|
faceted = as_bool(params[:faceted])
|
300
|
-
max_values_per_facet = (params[:max_values_per_facet] ||
|
301
|
-
|
302
|
-
# check filters
|
303
|
-
filters = []
|
304
|
-
filter_params = CGI::parse(env["QUERY_STRING"])['filter']
|
305
|
-
filter_params.each do |filter|
|
306
|
-
filter = read_filter(filter)
|
307
|
-
halt 400 unless ['category', 'name', 'value'].all? { |f| filter.include? f}
|
308
|
-
|
309
|
-
if filter['category'] == 'fts' && filter['name'] == 'search'
|
310
|
-
unless filter['value'].to_s.length > 1
|
311
|
-
halt(
|
312
|
-
400,
|
313
|
-
{ 'Content-Type' => 'application/json' },
|
314
|
-
render_json({
|
315
|
-
:status => 400,
|
316
|
-
:msg => 'Full-text search filter values must be larger than one.'
|
317
|
-
})
|
318
|
-
)
|
319
|
-
end
|
320
|
-
end
|
321
|
-
|
322
|
-
# Remove dataset filters since we're filtering a specific one already.
|
323
|
-
next if filter.values_at('category', 'name') == ['metadata', 'dataset']
|
335
|
+
max_values_per_facet = (params[:max_values_per_facet] || -1).to_i
|
324
336
|
|
325
|
-
|
326
|
-
end
|
337
|
+
filters = validate_filters!
|
327
338
|
|
328
339
|
collection_total = @api.count_evidence
|
329
340
|
filtered_total = @api.count_evidence(filters)
|
330
|
-
page_results = @api.find_dataset_evidence(dataset, filters, start, size, faceted)
|
331
|
-
|
332
|
-
accept_type = request.accept.find { |accept_entry|
|
333
|
-
ACCEPTED_TYPES.values.include?(accept_entry.to_s)
|
334
|
-
}
|
335
|
-
accept_type ||= DEFAULT_TYPE
|
336
|
-
|
337
|
-
if params[:format]
|
338
|
-
translator = BEL::Translator.plugins[params[:format].to_sym]
|
339
|
-
halt 501 if !translator || translator.id == :rdf
|
340
|
-
accept_type = [translator.media_types].flatten.first
|
341
|
-
end
|
342
|
-
|
343
|
-
if accept_type == DEFAULT_TYPE
|
344
|
-
evidence = page_results[:cursor].map { |item|
|
345
|
-
item.delete('facets')
|
346
|
-
item
|
347
|
-
}.to_a
|
348
|
-
|
349
|
-
facets = page_results[:facets]
|
350
|
-
|
351
|
-
halt 404 if evidence.empty?
|
352
|
-
|
353
|
-
pager = Pager.new(start, size, filtered_total)
|
354
|
-
|
355
|
-
options = {
|
356
|
-
:start => start,
|
357
|
-
:size => size,
|
358
|
-
:filters => filter_params,
|
359
|
-
:metadata => {
|
360
|
-
:collection_paging => {
|
361
|
-
:total => collection_total,
|
362
|
-
:total_filtered => pager.total_size,
|
363
|
-
:total_pages => pager.total_pages,
|
364
|
-
:current_page => pager.current_page,
|
365
|
-
:current_page_size => evidence.size,
|
366
|
-
}
|
367
|
-
}
|
368
|
-
}
|
369
|
-
|
370
|
-
if facets
|
371
|
-
# group by category/name
|
372
|
-
hashed_values = Hash.new { |hash, key| hash[key] = [] }
|
373
|
-
facets.each { |facet|
|
374
|
-
filter = read_filter(facet['_id'])
|
375
|
-
category, name = filter.values_at('category', 'name')
|
376
|
-
next if !category || !name
|
377
|
-
|
378
|
-
key = [category.to_sym, name.to_sym]
|
379
|
-
facet_obj = {
|
380
|
-
:value => filter['value'],
|
381
|
-
:filter => facet['_id'],
|
382
|
-
:count => facet['count']
|
383
|
-
}
|
384
|
-
hashed_values[key] << facet_obj
|
385
|
-
}
|
386
|
-
|
387
|
-
if max_values_per_facet == 0
|
388
|
-
facet_hashes = hashed_values.map { |(category, name), value_objects|
|
389
|
-
{
|
390
|
-
:category => category,
|
391
|
-
:name => name,
|
392
|
-
:values => value_objects
|
393
|
-
}
|
394
|
-
}
|
395
|
-
else
|
396
|
-
facet_hashes = hashed_values.map { |(category, name), value_objects|
|
397
|
-
{
|
398
|
-
:category => category,
|
399
|
-
:name => name,
|
400
|
-
:values => value_objects.take(max_values_per_facet)
|
401
|
-
}
|
402
|
-
}
|
403
|
-
end
|
404
|
-
|
405
|
-
options[:facets] = facet_hashes
|
406
|
-
end
|
407
|
-
|
408
|
-
# pager links
|
409
|
-
options[:previous_page] = pager.previous_page
|
410
|
-
options[:next_page] = pager.next_page
|
411
|
-
|
412
|
-
render_collection(evidence, :evidence, options)
|
413
|
-
else
|
414
|
-
out_translator = BEL.translator(accept_type)
|
415
|
-
extension = ACCEPTED_TYPES.key(accept_type.to_s)
|
416
|
-
|
417
|
-
response.headers['Content-Type'] = accept_type
|
418
|
-
status 200
|
419
|
-
attachment "#{dataset[:identifier].gsub(/[^\w]/, '_')}.#{extension}"
|
420
|
-
stream :keep_open do |response|
|
421
|
-
cursor = page_results[:cursor]
|
422
|
-
json_evidence_enum = cursor.lazy.map { |evidence|
|
423
|
-
evidence.delete('facets')
|
424
|
-
evidence.delete('_id')
|
425
|
-
evidence.keys.each do |key|
|
426
|
-
evidence[key.to_sym] = evidence.delete(key)
|
427
|
-
end
|
428
|
-
BEL::Model::Evidence.create(evidence)
|
429
|
-
}
|
341
|
+
page_results = @api.find_dataset_evidence(dataset, filters, start, size, faceted, max_values_per_facet)
|
342
|
+
name = dataset[:identifier].gsub(/[^\w]/, '_')
|
430
343
|
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
end
|
344
|
+
render_evidence_collection(
|
345
|
+
name, page_results, start, size, filters,
|
346
|
+
filtered_total, collection_total, @api
|
347
|
+
)
|
436
348
|
end
|
437
349
|
|
438
350
|
get '/api/datasets' do
|
@@ -469,6 +381,7 @@ the "multipart/form-data" content type. Allowed dataset content types are: #{ACC
|
|
469
381
|
halt 404 unless dataset_exists?(void_dataset_uri)
|
470
382
|
|
471
383
|
dataset = retrieve_dataset(void_dataset_uri)
|
384
|
+
# XXX Removes all facets due to load of many evidence.
|
472
385
|
@api.delete_dataset(dataset[:identifier])
|
473
386
|
@rr.delete_statement(RDF::Statement.new(void_dataset_uri, nil, nil))
|
474
387
|
|
@@ -485,6 +398,7 @@ the "multipart/form-data" content type. Allowed dataset content types are: #{ACC
|
|
485
398
|
|
486
399
|
datasets.each do |void_dataset_uri|
|
487
400
|
dataset = retrieve_dataset(void_dataset_uri)
|
401
|
+
# XXX Removes all facets due to load of many evidence.
|
488
402
|
@api.delete_dataset(dataset[:identifier])
|
489
403
|
@rr.delete_statement(RDF::Statement.new(void_dataset_uri, nil, nil))
|
490
404
|
end
|
@@ -3,6 +3,8 @@ require 'cgi'
|
|
3
3
|
require 'openbel/api/evidence/mongo'
|
4
4
|
require 'openbel/api/evidence/facet_filter'
|
5
5
|
require_relative '../resources/evidence_transform'
|
6
|
+
require_relative '../helpers/evidence'
|
7
|
+
require_relative '../helpers/filters'
|
6
8
|
require_relative '../helpers/pager'
|
7
9
|
|
8
10
|
module OpenBEL
|
@@ -142,19 +144,7 @@ module OpenBEL
|
|
142
144
|
size = (params[:size] || 0).to_i
|
143
145
|
group_as_array = as_bool(params[:group_as_array])
|
144
146
|
|
145
|
-
|
146
|
-
filters = []
|
147
|
-
filter_params = CGI::parse(env["QUERY_STRING"])['filter']
|
148
|
-
filter_params.each do |filter|
|
149
|
-
filter = read_filter(filter)
|
150
|
-
halt 400 unless ['category', 'name', 'value'].all? { |f| filter.include? f}
|
151
|
-
|
152
|
-
if filter['category'] == 'fts' && filter['name'] == 'search'
|
153
|
-
halt 400 unless filter['value'].to_s.length > 1
|
154
|
-
end
|
155
|
-
|
156
|
-
filters << filter
|
157
|
-
end
|
147
|
+
filters = validate_filters!
|
158
148
|
|
159
149
|
cursor = @api.find_evidence(filters, start, size, false)[:cursor]
|
160
150
|
if group_as_array
|
@@ -168,93 +158,18 @@ module OpenBEL
|
|
168
158
|
start = (params[:start] || 0).to_i
|
169
159
|
size = (params[:size] || 0).to_i
|
170
160
|
faceted = as_bool(params[:faceted])
|
171
|
-
max_values_per_facet = (params[:max_values_per_facet] ||
|
161
|
+
max_values_per_facet = (params[:max_values_per_facet] || -1).to_i
|
172
162
|
|
173
|
-
|
174
|
-
filters = []
|
175
|
-
filter_params = CGI::parse(env["QUERY_STRING"])['filter']
|
176
|
-
filter_params.each do |filter|
|
177
|
-
filter = read_filter(filter)
|
178
|
-
halt 400 unless ['category', 'name', 'value'].all? { |f| filter.include? f}
|
179
|
-
|
180
|
-
if filter['category'] == 'fts' && filter['name'] == 'search'
|
181
|
-
halt 400 unless filter['value'].to_s.length > 1
|
182
|
-
end
|
183
|
-
|
184
|
-
filters << filter
|
185
|
-
end
|
163
|
+
filters = validate_filters!
|
186
164
|
|
187
165
|
collection_total = @api.count_evidence()
|
188
166
|
filtered_total = @api.count_evidence(filters)
|
189
|
-
page_results = @api.find_evidence(filters, start, size, faceted)
|
190
|
-
evidence = page_results[:cursor].map { |item|
|
191
|
-
item.delete('facets')
|
192
|
-
item
|
193
|
-
}.to_a
|
194
|
-
facets = page_results[:facets]
|
195
|
-
|
196
|
-
halt 404 if evidence.empty?
|
197
|
-
|
198
|
-
pager = Pager.new(start, size, filtered_total)
|
199
|
-
|
200
|
-
options = {
|
201
|
-
:start => start,
|
202
|
-
:size => size,
|
203
|
-
:filters => filter_params,
|
204
|
-
:metadata => {
|
205
|
-
:collection_paging => {
|
206
|
-
:total => collection_total,
|
207
|
-
:total_filtered => pager.total_size,
|
208
|
-
:total_pages => pager.total_pages,
|
209
|
-
:current_page => pager.current_page,
|
210
|
-
:current_page_size => evidence.size,
|
211
|
-
}
|
212
|
-
}
|
213
|
-
}
|
214
|
-
|
215
|
-
if facets
|
216
|
-
# group by category/name
|
217
|
-
hashed_values = Hash.new { |hash, key| hash[key] = [] }
|
218
|
-
facets.each { |facet|
|
219
|
-
filter = read_filter(facet['_id'])
|
220
|
-
category, name = filter.values_at('category', 'name')
|
221
|
-
next if !category || !name
|
222
|
-
|
223
|
-
key = [category.to_sym, name.to_sym]
|
224
|
-
facet_obj = {
|
225
|
-
:value => filter['value'],
|
226
|
-
:filter => facet['_id'],
|
227
|
-
:count => facet['count']
|
228
|
-
}
|
229
|
-
hashed_values[key] << facet_obj
|
230
|
-
}
|
231
|
-
|
232
|
-
if max_values_per_facet == 0
|
233
|
-
facet_hashes = hashed_values.map { |(category, name), value_objects|
|
234
|
-
{
|
235
|
-
:category => category,
|
236
|
-
:name => name,
|
237
|
-
:values => value_objects
|
238
|
-
}
|
239
|
-
}
|
240
|
-
else
|
241
|
-
facet_hashes = hashed_values.map { |(category, name), value_objects|
|
242
|
-
{
|
243
|
-
:category => category,
|
244
|
-
:name => name,
|
245
|
-
:values => value_objects.take(max_values_per_facet)
|
246
|
-
}
|
247
|
-
}
|
248
|
-
end
|
249
|
-
|
250
|
-
options[:facets] = facet_hashes
|
251
|
-
end
|
252
|
-
|
253
|
-
# pager links
|
254
|
-
options[:previous_page] = pager.previous_page
|
255
|
-
options[:next_page] = pager.next_page
|
167
|
+
page_results = @api.find_evidence(filters, start, size, faceted, max_values_per_facet)
|
256
168
|
|
257
|
-
|
169
|
+
render_evidence_collection(
|
170
|
+
'evidence-export', page_results, start, size, filters,
|
171
|
+
filtered_total, collection_total, @api
|
172
|
+
)
|
258
173
|
end
|
259
174
|
|
260
175
|
get '/api/evidence/:id' do
|