openbel-api 0.5.1-java → 0.6.1-java
Sign up to get free protection for your applications and to get access to all the features.
- 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
|