colrapi 0.1.0

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.
data/lib/colrapi.rb ADDED
@@ -0,0 +1,1026 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "erb"
4
+ require_relative "colrapi/version"
5
+ require_relative "colrapi/request"
6
+ require "colrapi/helpers/configuration"
7
+
8
+ module Colrapi
9
+ extend Configuration
10
+
11
+ define_setting :base_url, "https://api.checklistbank.org/"
12
+ define_setting :mailto, ENV["COL_API_EMAIL"]
13
+
14
+ # Get assembly status
15
+ #
16
+ # @param dataset_id [String] The dataset id
17
+ #
18
+ # @return [Hash] A result hash of the assembly queue
19
+ def self.assembly(dataset_id, verbose: false)
20
+ endpoint = "dataset/#{dataset_id}/assembly"
21
+ Request.new(endpoint: endpoint, verbose: verbose).perform
22
+ end
23
+
24
+ # Get a dataset's original archive
25
+ #
26
+ # @param dataset_id [String] The dataset id
27
+ #
28
+ # @return [Binary] An archive of the original dataset
29
+ def self.archive(dataset_id, verbose: false)
30
+ endpoint = "dataset/#{dataset_id}/archive"
31
+ Request.new(endpoint: endpoint, verbose: verbose).perform
32
+ end
33
+
34
+ # Get dataset metadata
35
+ #
36
+ # For a specific dataset:
37
+ # @param dataset_id [String] The dataset id
38
+ # @param attempt [Integer] Returns archived metadata for a past import attempt number
39
+ #
40
+ # Search datasets:
41
+ # @param q [String] A search query for datasets
42
+ # @param short_title [String] A dataset alias
43
+ # @param code [String] The nomenclatural code (bacterial, botanical, cultivars, phytosociological, virus, zoological)
44
+ # @param private [Boolean] Whether the dataset is private or not
45
+ # @param released_from [Integer] Filter by a project id that a dataset was released from
46
+ # @param contributes_to [Integer] Filter by a project id that a dataset contributes to
47
+ # @param has_source_dataset [Boolean] Filter by if source datasets contribute to the project dataset
48
+ # @param has_gbif_id [Boolean] Whether the dataset has a GBIF registry id
49
+ # @param gbif_id [String] The GBIF registry id
50
+ # @param gbif_publisher_id [String] Filter by a GBIF publisher's id
51
+ # @param editor [Integer] Filter by an editor's user id
52
+ # @param reviewer [Integer] Filter by a reviewer's user id
53
+ # @param modified_by [Integer] Filter by a user id on last modified by
54
+ # @param origin [Array, String] Filter by the origin of a dataset (external, project, release, xrelease)
55
+ # @param type [Array, String] Filter by the dataset type (nomenclatural, taxonomic, phylogenetic, article, legal, thematic, other)
56
+ # @param license [Array, String] Filter by the license type (cc0, cc_by, cc_by_sa, cc_by_nc, cc_by_nd, cc_by_nc_sa, cc_by_nc_nd, unspecified, other)
57
+ # @param row_type [Array, String] Filter by datasets that include a row type (e.g., acef:AcceptedSpecies, col:Taxon, dwc:Taxon)
58
+ # @param created_after [Date] Filter by created after date
59
+ # @param created_before [Date] Filter by created before date
60
+ # @param issued_after [Date] Filter by issued after date
61
+ # @param issued_before [Date] Filter by issued before date
62
+ # @param modified_after [Date] Filter by modified after date
63
+ # @param modified_before [Date] Filter by modified before date
64
+ # @param min_size [Integer] Filter by minimum record size
65
+ #
66
+ # @param sort_by [String] Sort by (key, alias, title, creator, relevance, created, modified, imported, size)
67
+ # @param reverse [Boolean] Sort in reverse
68
+ # @param offset [Integer] Offset for pagination
69
+ # @param limit [Integer] Limit for pagination
70
+ # @param verbose [Boolean] Print headers to STDOUT
71
+ #
72
+ # @return [Array, Boolean] An array of hashes
73
+ def self.dataset(dataset_id: nil, attempt: nil, q: nil, short_title: nil, code: nil, private: nil, released_from: nil,
74
+ contributes_to: nil, has_source_dataset: nil, has_gbif_id: nil, gbif_id: nil, gbif_publisher_id: nil,
75
+ editor: nil, reviewer: nil, modified_by: nil, origin: nil, type: nil, license: nil, row_type: nil,
76
+ created_after: nil, created_before: nil, issued_after: nil, issued_before: nil, modified_after: nil,
77
+ modified_before: nil, min_size: nil, sort_by: nil, reverse: nil, offset: nil, limit: nil,
78
+ verbose: false)
79
+ endpoint = "dataset"
80
+ unless dataset_id.nil?
81
+ endpoint = "#{endpoint}/#{dataset_id}"
82
+ unless attempt.nil?
83
+ endpoint = "#{endpoint}/#{attempt}"
84
+ end
85
+ endpoint = "#{endpoint}.json"
86
+ Request.new(endpoint: endpoint, verbose: verbose).perform
87
+ else
88
+ Request.new(endpoint: endpoint, q: q, short_title: short_title, code: code, private: private,
89
+ released_from: released_from, contributes_to: contributes_to, has_source_dataset: has_source_dataset,
90
+ has_gbif_id: has_gbif_id, gbif_id: gbif_id, gbif_publisher_id: gbif_publisher_id, editor: editor,
91
+ reviewer: reviewer, modified_by: modified_by, origin: origin, type: type, license: license,
92
+ row_type: row_type, created_after: created_after, created_before: created_before,
93
+ issued_after: issued_after, issued_before: issued_before, modified_after: modified_after,
94
+ modified_before: modified_before, min_size: min_size, sort_by: sort_by, reverse: reverse,
95
+ offset: offset, limit: limit, verbose: verbose).perform
96
+ end
97
+ end
98
+
99
+ # Get project decisions
100
+ #
101
+ # @param dataset_id [String] The dataset id
102
+ # @param decision_id [Integer, nil] The decision id
103
+ # @param name [String, nil] The scientific name to match
104
+ # @param rank [String, nil] The rank of the scientific name
105
+ # @param modified_by [Integer, nil] Filter by a user id on last modified by
106
+ # @param broken [Boolean, nil] Whether the decision is broken or not
107
+ # @param subject_dataset_id [String, nil] The source dataset id
108
+ # @param mode [String, nil] The type of decision (block, reviewed, update, update_recursive, ignore)
109
+ # @param subject [Boolean, nil] TODO: what does this do? All decisions with subject=true are bare names, so maybe it checks if the subject taxon exists?
110
+ #
111
+ # @param offset [Integer] Offset for pagination
112
+ # @param limit [Integer] Limit for pagination
113
+ # @param verbose [Boolean] Print headers to STDOUT
114
+ #
115
+ # @return [Hash, Boolean] A result hash
116
+ def self.decision(dataset_id, decision_id: nil, name: nil, rank: nil, modified_by: nil, broken: nil,
117
+ subject_dataset_id: nil, mode: nil, subject: nil, offset: nil, limit: nil, verbose: false)
118
+ if decision_id.nil?
119
+ endpoint = "dataset/#{dataset_id}/decision"
120
+ Request.new(endpoint: endpoint, name: name, rank: rank, modified_by: modified_by, broken: broken,
121
+ subject_dataset_id: subject_dataset_id, mode: mode, subject: subject, offset: offset,
122
+ limit: limit, verbose: verbose).perform
123
+ else
124
+ endpoint = "dataset/#{dataset_id}/decision/#{decision_id}"
125
+ Request.new(endpoint: endpoint, verbose: verbose).perform
126
+ end
127
+ end
128
+
129
+ # Get duplicate names
130
+ #
131
+ # @param dataset_id [String] The dataset id
132
+ #
133
+ # @param offset [Integer] Offset for pagination
134
+ # @param limit [Integer] Limit for pagination
135
+ # @param verbose [Boolean] Print headers to STDOUT
136
+ def self.duplicate(dataset_id, offset: nil, limit: nil, verbose: false)
137
+ endpoint = "dataset/#{dataset_id}/duplicate"
138
+ Request.new(endpoint: endpoint, offset: offset, limit: limit, verbose: verbose).perform
139
+ end
140
+
141
+ # Get names diff between 2 datasets
142
+ #
143
+ # @param dataset_id [String] The first dataset id
144
+ # @param dataset2_id [String] The second dataset id
145
+ # @param root_id [Array, String, nil] The root taxon for the first dataset
146
+ # @param root2_id [Array, String, nil] The root taxon for the second dataset
147
+ # @param min_rank [String, nil] The minimum taxonomic rank
148
+ # @param authorship [Boolean, nil] Include authorship
149
+ # @param include_synonyms [Boolean, nil] Include synonyms
150
+ # @param include_parent [Boolean, nil] Include parent
151
+ # @param parent_rank [String, nil] Filter by parent rank
152
+ # @param token [String, nil] An authentication token from Colrapi.user_login()
153
+ #
154
+ # @param offset [Integer] Offset for pagination
155
+ # @param limit [Integer] Limit for pagination
156
+ # @param verbose [Boolean] Print headers to STDOUT
157
+ #
158
+ # @return [String, Boolean] A text diff of names
159
+ def self.diff(dataset_id, dataset2_id, root_id: nil, root2_id: nil, min_rank: nil,
160
+ authorship: nil, include_synonyms: nil, include_parent: nil, parent_rank: nil,
161
+ offset: nil, limit: nil, token: nil, verbose: false)
162
+ endpoint = "dataset/#{dataset_id}/diff/#{dataset2_id}"
163
+ Request.new(endpoint: endpoint, root_id: root_id, root2_id: root2_id, min_rank: min_rank,
164
+ authorship: authorship, include_synonyms: include_synonyms,
165
+ include_parent: include_parent, parent_rank: parent_rank,
166
+ offset: offset, limit: limit, token: token, verbose: verbose).perform
167
+ end
168
+
169
+ # Get editor info
170
+ #
171
+ # @param dataset_id [String] The dataset id
172
+ # @param token [String, nil] The authentication token from retrieved with Colrapi.user_login(user, password)
173
+ #
174
+ # # @return [Array, Hash, Boolean] An array of hashes
175
+ def self.editor(dataset_id, token, verbose: false)
176
+ endpoint = "dataset/#{dataset_id}/editor"
177
+ Request.new(endpoint: endpoint, token: token, verbose: verbose).perform
178
+ end
179
+
180
+ # Get estimates
181
+ # @param dataset_id [String] The dataset id
182
+ # @param estimate_id [Integer, nil] The estimate ID
183
+ # @param name [String] The scientific name
184
+ # @param rank [String, nil] taxonomic rank
185
+ # @param modified_by [Integer, nil] Filter by a user id on last modified by
186
+ # @param broken [Boolean, nil] Whether the estimate is broken or not
187
+ # @param min [Integer, nil] Filter by the minimum estimate
188
+ # @param max [Integer, nil] Filter by the maximum estimate
189
+ #
190
+ # @param offset [Integer] Offset for pagination
191
+ # @param limit [Integer] Limit for pagination
192
+ # @param verbose [Boolean] Print headers to STDOUT
193
+ #
194
+ # @return [Hash, Boolean] A results hash
195
+ def self.estimate(dataset_id, estimate_id: nil, name: nil, rank: nil, modified_by: nil, broken: nil, min: nil,
196
+ max: nil, offset: nil, limit: nil, verbose: false)
197
+ endpoint = "dataset/#{dataset_id}/estimate"
198
+ if estimate_id.nil?
199
+ Request.new(endpoint: endpoint, name: name, rank: rank, modified_by: modified_by, broken: broken,
200
+ min: min, max: max, offset: offset, limit: limit, verbose: verbose).perform
201
+ else
202
+ endpoint = "dataset/#{dataset_id}/estimate/#{estimate_id}"
203
+ Request.new(endpoint: endpoint, verbose: verbose).perform
204
+ end
205
+ end
206
+
207
+ # TODO: /dataset/{key}/export is covered, but /export and /export/{id} are not
208
+ # Get a dataset export
209
+ #
210
+ # @param dataset_id [String] The dataset id
211
+ # @param show_id [Boolean, nil] TODO: not implemented because it doesn't seem to do anything?
212
+ # @param verbose [Boolean] Print headers to STDOUT
213
+ #
214
+ # @return [Hash, Boolean] An export hash
215
+ def self.export(dataset_id, show_id: nil, verbose: false)
216
+ endpoint = "dataset/#{dataset_id}/export"
217
+ Request.new(endpoint: endpoint, verbose: verbose).perform
218
+ end
219
+
220
+ # Get data quality issues
221
+ #
222
+ # @param dataset_id [String] The dataset id
223
+ # @param issue [String] Filter by data quality issue (e.g., ACCEPTED_NAME_MISSING, DUPLICATE_NAME, URL_INVALID)
224
+ # @param mode [String] Verbatim (default) or interpreted
225
+ #
226
+ # @param offset [Integer] Offset for pagination
227
+ # @param limit [Integer] Limit for pagination
228
+ # @param verbose [Boolean] Print headers to STDOUT
229
+ #
230
+ # @return [Array, Hash, Boolean] An array of hashes
231
+ def self.issues(dataset_id, issue: nil, mode: 'verbatim', offset: nil, limit: nil, verbose: false)
232
+ if issue.nil?
233
+ metrics = Request.new(endpoint: "/dataset/#{dataset_id}/import?state=finished").perform
234
+ return {"issuesCount" => metrics[0]['issuesCount']}
235
+ else
236
+ if mode == 'interpreted'
237
+ issues = self.vocab(term: 'issue')
238
+ record_type = 'any'
239
+ issues.each do |i|
240
+ if i['name'] == issue.downcase
241
+ record_type = i['group']
242
+ end
243
+ end
244
+
245
+ # TODO: so far issues are only filterable on nameusage/search and /reference
246
+ # for other record_types, may need to add other endpoints in the future
247
+ if record_type == 'reference'
248
+ self.reference(dataset_id, issue: issue, offset: offset, limit: limit, verbose: verbose)
249
+ else
250
+ self.nameusage_search(dataset_id: dataset_id, issue: issue, facet: 'issue', offset: offset, limit: limit,
251
+ verbose: verbose)
252
+ end
253
+ else
254
+ self.verbatim(dataset_id, issue: issue, offset: offset, limit: limit, verbose: verbose)
255
+ end
256
+ end
257
+ end
258
+
259
+ # Get importer status
260
+ #
261
+ # @param dataset_id [String] Calls the dataset_id endpoint /importer/{dataset_id}
262
+ # @param dataset_id_filter [String] Filters the importer queue by dataset_id
263
+ # @param state [Array, String] The import status (e.g., waiting, preparing, downloading, processing, inserting, ...)
264
+ # @param running [Boolean] Filter by actively importing datasets
265
+ #
266
+ # @param offset [Integer] Offset for pagination
267
+ # @param limit [Integer] Limit for pagination
268
+ # @param verbose [Boolean] Print headers to STDOUT
269
+ #
270
+ # @return [Array, Boolean] An array of hashes
271
+ def self.importer(dataset_id: nil, dataset_id_filter: nil, state: nil, running: nil, offset: nil, limit: nil,
272
+ verbose: false)
273
+ endpoint = "importer"
274
+ if dataset_id.nil?
275
+ Request.new(endpoint: endpoint, dataset_id_filter: dataset_id_filter, state: state, running: running,
276
+ offset: offset, limit: limit, verbose: verbose).perform
277
+ else
278
+ endpoint = "#{endpoint}/#{dataset_id}"
279
+ Request.new(endpoint: endpoint, verbose: verbose).perform
280
+ end
281
+ end
282
+
283
+ # Get a dataset's logo
284
+ #
285
+ # @param dataset_id [String] The dataset id
286
+ # @param size [String] The size of the logo (original, large, medium, small)
287
+ #
288
+ # @return [Binary] The dataset logo
289
+ def self.logo(dataset_id, size: nil, verbose: false)
290
+ endpoint = "dataset/#{dataset_id}/logo"
291
+ Request.new(endpoint: endpoint, size: size, verbose: verbose).perform
292
+ end
293
+
294
+ # Get names or a name from a dataset
295
+ #
296
+ # @param dataset_id [String] The dataset id
297
+ # @param name [String] The scientific name to match
298
+ # @param authorship [String] The authorship string for the scientific name
299
+ # @param code [String] The nomenclatural code (bacterial, botanical, cultivars, phytosociological, virus, zoological)
300
+ # @param rank [String] The rank of the scientific name
301
+ # @param within_superkingdom [String] Restricts query to within a superkingdom
302
+ # @param within_kingdom [String] Restricts query to within a kingdom
303
+ # @param within_subkingdom [String] Restricts query to within a subkingdom
304
+ # @param within_superphylum [String] Restricts query to within a superphylum
305
+ # @param within_phylum [String] Restricts query to within a phylum
306
+ # @param within_subphylum [String] Restricts query to within a subphylum
307
+ # @param within_superclass [String] Restricts query to within a superclass
308
+ # @param within_class [String] Restricts query to within a class
309
+ # @param within_subclass [String] Restricts query to within a subclass
310
+ # @param within_superorder [String] Restricts query to within a superorder
311
+ # @param within_order [String] Restricts query to within a order
312
+ # @param within_suborder [String] Restricts query to within a suborder
313
+ # @param within_superfamily [String] Restricts query to within a superfamily
314
+ # @param within_family [String] Restricts query to within a family
315
+ # @param within_subfamily [String] Restricts query to within a subfamily
316
+ # @param within_tribe [String] Restricts query to within a tribe
317
+ # @param within_subtribe [String] Restricts query to within a subtribe
318
+ # @param within_genus [String] Restricts query to within a genus
319
+ # @param within_subgenus [String] Restricts query to within a subgenus
320
+ # @param within_section [String] Restricts query to within a section
321
+ # @param within_species [String] Restricts query to within a species
322
+ #
323
+ # @param verbose [Boolean] Print headers to STDOUT
324
+ #
325
+ # @return [Array, Boolean] An array of hashes
326
+ # def self.matching(dataset_id, name: nil, authorship: nil, code: nil, rank: nil, within_superkingdom: nil,
327
+ # within_kingdom: nil, within_subkingdom: nil, within_superphylum: nil, within_phylum: nil,
328
+ # within_subphylum: nil, within_superclass: nil, within_class: nil, within_subclass: nil,
329
+ # within_superorder: nil, within_order: nil, within_suborder: nil, within_superfamily: nil,
330
+ # within_family: nil, within_subfamily: nil, within_tribe: nil, within_subtribe: nil,
331
+ # within_genus: nil, within_subgenus: nil, within_section: nil, within_species: nil,
332
+ # verbose: false)
333
+ # endpoint = "dataset/#{dataset_id}/matching"
334
+ # Request.new(endpoint: endpoint, name: name, authorship: authorship, code: code, rank: rank,
335
+ # within_superkingdom: within_superkingdom, within_kingdom: within_kingdom,
336
+ # within_subkingdom: within_subkingdom, within_superphylum: within_superphylum,
337
+ # within_phylum: within_phylum, within_subphylum: within_subphylum, within_superclass: within_superclass,
338
+ # within_class: within_class, within_subclass: within_subclass, within_superorder: within_superorder,
339
+ # within_order: within_order, within_suborder: within_suborder, within_superfamily: within_superfamily,
340
+ # within_family: within_family, within_subfamily: within_subfamily, within_tribe: within_tribe,
341
+ # within_subtribe: within_subtribe, within_genus: within_genus, within_subgenus: within_subgenus,
342
+ # within_section: within_section, within_species: within_species, verbose: verbose).perform
343
+ # end
344
+
345
+ # Get metrics for the *last successful* import of a dataset or a specific import_attempt
346
+ #
347
+ # @param dataset_id [String] The dataset id
348
+ # @param import_attempt [Integer] The import attempt
349
+ #
350
+ # @return [Array, Hash, Boolean] An array of hashes
351
+ def self.metrics(dataset_id, import_attempt: nil, verbose: false)
352
+
353
+ import = self.importer(dataset_id: dataset_id)
354
+ unless %w[unchanged finished].include? import['state']
355
+ return {"code" => 400, 'message' => 'Dataset has not finished importing or failed to import'}
356
+ end
357
+
358
+ # it's necessary to get the last finished import attempt because status=unchanged import results don't have metrics
359
+ # project release datasets do not seem to have import_attempts or should be taken from the project dataset, e.g.:
360
+ # https://api.checklistbank.org/dataset/3/import/107 == https://api.checklistbank.org/dataset/9837/import
361
+ if import_attempt.nil?
362
+ import = self.importer(dataset_id_filter: dataset_id, state: 'finished')
363
+ if import['total'] > 0
364
+ import_attempt = import['result'][0]['attempt']
365
+ end
366
+ end
367
+
368
+ endpoint = "dataset/#{dataset_id}/import"
369
+ if !import_attempt.nil?
370
+ endpoint = "#{endpoint}/#{import_attempt}"
371
+ Request.new(endpoint: endpoint, verbose: verbose).perform
372
+ else
373
+ # /dataset/{id}/import returns an array of 1 item while /dataset/{id}/import/{attempt} doesn't
374
+ res = Request.new(endpoint: endpoint, verbose: verbose).perform
375
+ res[0]
376
+ end
377
+ end
378
+
379
+ # Get names or a name from a dataset
380
+ #
381
+ # @param dataset_id [String] The dataset id
382
+ # @param name_id [String] The name id
383
+ # @param subresource [String] The name subresource endpoint (relations, synonyms, types, or orphans)
384
+ #
385
+ # @param offset [Integer] Offset for pagination
386
+ # @param limit [Integer] Limit for pagination
387
+ # @param verbose [Boolean] Print headers to STDOUT
388
+ #
389
+ # @return [Array, Boolean] An array of hashes
390
+ def self.name(dataset_id, name_id: nil, subresource: nil, offset: nil, limit: nil, verbose: false)
391
+ endpoint = "dataset/#{dataset_id}/name"
392
+ unless name_id.nil?
393
+ endpoint = "#{endpoint}/#{name_id}"
394
+ offset = nil
395
+ limit = nil
396
+ end
397
+ if !subresource.nil? and %w[relations synonyms types orphans].include? subresource
398
+ endpoint = "#{endpoint}/#{subresource}"
399
+ end
400
+ Request.new(endpoint: endpoint, offset: offset, limit: limit, verbose: verbose).perform
401
+ end
402
+
403
+ # Get a text list of names for a dataset
404
+ #
405
+ # @param dataset_id [String] The dataset id
406
+ # @param import_attempt [Integer] The import attempt number
407
+ #
408
+ def self.name_list(dataset_id, import_attempt: nil, verbose: nil)
409
+
410
+ # get last import attempt number if none given
411
+ if import_attempt.nil?
412
+ import = self.importer(dataset_id: dataset_id)
413
+ import_attempt = import['attempt']
414
+ end
415
+
416
+ endpoint = "dataset/#{dataset_id}/import/#{import_attempt}/names"
417
+ Request.new(endpoint: endpoint, verbose: verbose).perform
418
+ end
419
+
420
+ # Get a text tree of names for a dataset
421
+ #
422
+ # @param dataset_id [String] The dataset id
423
+ # @param import_attempt [Integer] The import attempt number
424
+ #
425
+ def self.name_tree(dataset_id, import_attempt: nil, verbose: nil)
426
+
427
+ # get last import attempt number if none given
428
+ if import_attempt.nil?
429
+ import = self.importer(dataset_id: dataset_id)
430
+ import_attempt = import['attempt']
431
+ end
432
+
433
+ endpoint = "dataset/#{dataset_id}/import/#{import_attempt}/tree"
434
+ Request.new(endpoint: endpoint, verbose: verbose).perform
435
+ end
436
+
437
+ # Get name usages or a nameusage from a dataset
438
+ # Note: Queries the PSQL database, whereas nameusage_search uses Elastic Search
439
+ #
440
+ # @param dataset_id [String] The dataset id
441
+ # @param nameusage_id [String] The nameusage id
442
+ # @param q [String] The scientific name or authorship search query
443
+ # @param rank [Array, String] The rank of the taxon in the search query q
444
+ # @param nidx_id [String] The name index id
445
+ # @param subresource [String] The name subresource endpoint (relations, synonyms, types, or orphans)
446
+ #
447
+ # @param offset [Integer] Offset for pagination
448
+ # @param limit [Integer] Limit for pagination
449
+ # @param verbose [Boolean] Print headers to STDOUT
450
+ #
451
+ # @return [Array, Boolean] An array of hashes
452
+ def self.nameusage(dataset_id, nameusage_id: nil, q: nil, rank: nil, nidx_id: nil, subresource: nil,
453
+ offset: nil, limit: nil, verbose: false)
454
+ endpoint = "dataset/#{dataset_id}/nameusage"
455
+ unless nameusage_id.nil?
456
+ endpoint = "#{endpoint}/#{nameusage_id}"
457
+ offset = nil
458
+ limit = nil
459
+ end
460
+ unless subresource.nil?
461
+ endpoint = "#{endpoint}/#{subresource}"
462
+ end
463
+ Request.new(endpoint: endpoint, q: q, rank: rank, nidx_id: nidx_id, offset: offset, limit: limit,
464
+ verbose: verbose).perform
465
+ end
466
+
467
+ # TODO: /dataset/{key}/nameusage/{id}/related not covered
468
+ # TODO: /dataset/{key}/nameusage/{id}/source not covered
469
+
470
+ # Get names or a name from a dataset
471
+ #
472
+ # @param dataset_id [String] The dataset id
473
+ # @param name [String] The scientific name to match
474
+ # @param authorship [String] The authorship string for the scientific name
475
+ # @param code [String] The nomenclatural code (bacterial, botanical, cultivars, phytosociological, virus, zoological)
476
+ # @param rank [String] The rank of the scientific name
477
+ # @param within_superkingdom [String] Restricts query to within a superkingdom
478
+ # @param within_kingdom [String] Restricts query to within a kingdom
479
+ # @param within_subkingdom [String] Restricts query to within a subkingdom
480
+ # @param within_superphylum [String] Restricts query to within a superphylum
481
+ # @param within_phylum [String] Restricts query to within a phylum
482
+ # @param within_subphylum [String] Restricts query to within a subphylum
483
+ # @param within_superclass [String] Restricts query to within a superclass
484
+ # @param within_class [String] Restricts query to within a class
485
+ # @param within_subclass [String] Restricts query to within a subclass
486
+ # @param within_superorder [String] Restricts query to within a superorder
487
+ # @param within_order [String] Restricts query to within a order
488
+ # @param within_suborder [String] Restricts query to within a suborder
489
+ # @param within_superfamily [String] Restricts query to within a superfamily
490
+ # @param within_family [String] Restricts query to within a family
491
+ # @param within_subfamily [String] Restricts query to within a subfamily
492
+ # @param within_tribe [String] Restricts query to within a tribe
493
+ # @param within_subtribe [String] Restricts query to within a subtribe
494
+ # @param within_genus [String] Restricts query to within a genus
495
+ # @param within_subgenus [String] Restricts query to within a subgenus
496
+ # @param within_section [String] Restricts query to within a section
497
+ # @param within_species [String] Restricts query to within a species
498
+ #
499
+ # @param verbose [Boolean] Print headers to STDOUT
500
+ #
501
+ # @return [Array, Boolean] An array of hashes
502
+ def self.matching(dataset_id, name: nil, authorship: nil, code: nil, rank: nil, within_superkingdom: nil,
503
+ within_kingdom: nil, within_subkingdom: nil, within_superphylum: nil, within_phylum: nil,
504
+ within_subphylum: nil, within_superclass: nil, within_class: nil, within_subclass: nil,
505
+ within_superorder: nil, within_order: nil, within_suborder: nil, within_superfamily: nil,
506
+ within_family: nil, within_subfamily: nil, within_tribe: nil, within_subtribe: nil,
507
+ within_genus: nil, within_subgenus: nil, within_section: nil, within_species: nil,
508
+ verbose: false)
509
+ endpoint = "dataset/#{dataset_id}/nameusage/match"
510
+ Request.new(endpoint: endpoint, name: name, authorship: authorship, code: code, rank: rank,
511
+ within_superkingdom: within_superkingdom, within_kingdom: within_kingdom,
512
+ within_subkingdom: within_subkingdom, within_superphylum: within_superphylum,
513
+ within_phylum: within_phylum, within_subphylum: within_subphylum, within_superclass: within_superclass,
514
+ within_class: within_class, within_subclass: within_subclass, within_superorder: within_superorder,
515
+ within_order: within_order, within_suborder: within_suborder, within_superfamily: within_superfamily,
516
+ within_family: within_family, within_subfamily: within_subfamily, within_tribe: within_tribe,
517
+ within_subtribe: within_subtribe, within_genus: within_genus, within_subgenus: within_subgenus,
518
+ within_section: within_section, within_species: within_species, verbose: verbose).perform
519
+ end
520
+
521
+ # Search for a name usage with a regex pattern
522
+ #
523
+ # @param dataset_id [String, nil] restricts name usage pattern search within a dataset
524
+ # @param regexp [String] The regular expression pattern
525
+ # @param status [String, nil] The taxonomic status (accepted, provisionally_accepted, synonym, ambiguous_synonym, misapplied, bare_name)
526
+ # @param rank [String, nil] The taxonomic rank
527
+ # @param project_id [String, nil] Filter to names from project_id, required if decision_mode used
528
+ # @param decision_mode [String, nil] The type of decision (block, reviewed, update, update_recursive, ignore)
529
+ #
530
+ # @param offset [Integer] Offset for pagination
531
+ # @param limit [Integer] Limit for pagination
532
+ # @param verbose [Boolean] Print headers to STDOUT
533
+ def self.nameusage_pattern(dataset_id, regexp, status: nil, rank: nil, project_id: nil, decision_mode: nil,
534
+ offset: nil, limit: nil, verbose: false)
535
+ endpoint = "dataset/#{dataset_id}/nameusage/pattern"
536
+ Request.new(endpoint: endpoint, regexp: regexp, project_id: project_id, status: status, rank: rank,
537
+ decision_mode: decision_mode, offset: offset, limit: limit, verbose: verbose).perform
538
+ end
539
+
540
+ # Search the nameusage route, which uses Elastic Search
541
+ #
542
+ # @param q [String] A query string
543
+ # @param dataset_id [String, nil] restricts name usage search within a dataset
544
+ # @param endpoint [String, nil] some endpoints have nested options
545
+ # @param content [Array, String, nil] restrict search to SCIENTIFIC_NAME, or AUTHORSHIP
546
+ # @param issue [Array, String, nil] the data quality issue
547
+ # @param type [String, nil] sets the type of search to PREFIX, WHOLE_WORDS, or EXACT
548
+ # @param rank [String, nil] taxonomic rank of name usages
549
+ # @param min_rank [String, nil] minimum taxonomic rank of name usages
550
+ # @param max_rank [String, nil] maximum taxonomic rank of name usages
551
+ # @param facet [Array, String, nil] the search facet
552
+ #
553
+ # @param sort_by [String, nil] sort results by NAME, TAXONOMIC, INDEX_NAME_ID, NATIVE, or RELEVANCE
554
+ # @param reverse [Boolean] sort in reverse order
555
+ # @param offset [Integer] Offset for pagination
556
+ # @param limit [Integer] Limit for pagination
557
+ # @param verbose [Boolean] Print headers to STDOUT
558
+ #
559
+ # @return [Array, Boolean] An array of hashes
560
+ def self.nameusage_search(q: nil, dataset_id: nil, endpoint: 'nameusage/search', content: nil, issue: nil,
561
+ type: nil, rank: nil, min_rank: nil, max_rank: nil, facet: nil,
562
+ sort_by: nil, reverse: nil, offset: nil, limit: nil,
563
+ verbose: false)
564
+
565
+ # a nil dataset_id will search name usages from all datasets in ChecklistBank
566
+ unless dataset_id.nil?
567
+ endpoint = "dataset/#{dataset_id}/nameusage/search"
568
+ end
569
+
570
+ Request.new(endpoint: endpoint, q: q, content: content, issue: issue, type: type,
571
+ rank: rank, min_rank: min_rank, max_rank: max_rank, facet: facet,
572
+ sort_by: sort_by, reverse: reverse, offset: offset, limit: limit, verbose: verbose).perform
573
+ end
574
+
575
+ # Get a name usage suggestion
576
+ #
577
+ # @param dataset_id [String] restricts name usage search within a dataset
578
+ # @param q [String] A suggestion search query
579
+ # @param fuzzy [Boolean, nil] Whether to include fuzzy matches for misspellings (TODO: might not actually work?)
580
+ # @param min_rank [String, nil] The minimum rank to suggest
581
+ # @param max_rank [String, nil] The maximum rank to suggest
582
+ # @param sort_by [String, nil] The sorting order (name, taxonomic, index_name_id, native, relevance)
583
+ # @param reverse [Boolean, nil] Sort in opposite order
584
+ # @param accepted [Boolean, nil] Suggest only accepted names
585
+ #
586
+ # @limit [Integer, nil] Limit the suggestion number (offset not available)
587
+ # @param verbose [Boolean] Print headers to STDOUT
588
+ #
589
+ # @return [Hash, Boolean] A a hash of name usage suggestions
590
+ def self.nameusage_suggest(dataset_id, q, fuzzy: nil, min_rank: nil, max_rank: nil, sort_by: nil, reverse: nil,
591
+ accepted: nil, limit: nil, verbose: false)
592
+ endpoint = "dataset/#{dataset_id}/nameusage/suggest"
593
+ Request.new(endpoint: endpoint, q: q, fuzzy: fuzzy, min_rank: min_rank, max_rank: max_rank, sort_by: sort_by,
594
+ reverse: reverse, accepted: accepted, limit: limit, verbose: verbose).perform
595
+ end
596
+
597
+ # Get names index info
598
+ #
599
+ # @param nidx_id [Integer] a names index ID
600
+ # @param subresource [String, nil] the subresource (group)
601
+ def self.nidx(nidx_id, subresource: nil, verbose: false)
602
+ endpoint = "nidx/#{nidx_id}"
603
+ endpoint = "nidx/#{nidx_id}/#{subresource}" unless subresource.nil?
604
+ Request.new(endpoint: endpoint, verbose: verbose).perform
605
+ end
606
+
607
+ # Get names index matches
608
+ # @param q [String, nil] A match query
609
+ # @param authorship [String, nil] An authorship string
610
+ # @param rank [String, nil] The taxonomic rank
611
+ # @param code [String, nil] The nomenclatural code
612
+ #
613
+ # @param verbose [Boolean] Print headers to STDOUT
614
+ #
615
+ # @return [Hash, Boolean] A match hash
616
+ def self.nidx_match(q, authorship: nil, rank: nil, code: nil, verbose: false)
617
+ endpoint = "nidx/match"
618
+ Request.new(endpoint: endpoint, q: q, authorship: authorship, rank: rank, code: code, verbose: verbose).perform
619
+ end
620
+
621
+ # Parse a {subresource}
622
+ #
623
+ # This is the generic parser wrapper. For specialized parsers, like the names, homoglyphs, idconverter, metadata,
624
+ # use the specialized parsers below like Colrapi.parser_name(). Returns a list of parsers if no subresource given.
625
+ #
626
+ # @param subresource [String] the type of parser to use
627
+ # @param q [Array, String] a query string or array of query strings to parse
628
+ #
629
+ # @return [Array, Hash, Boolean] An array of parsers, or a parser result hash
630
+ def self.parser(subresource: nil, q: nil, verbose: false)
631
+ endpoint = "parser"
632
+ endpoint = "#{endpoint}/#{subresource}" unless subresource.nil?
633
+ Request.new(endpoint: endpoint, q: q, verbose: verbose).perform
634
+ end
635
+
636
+ # Encode or decode identifiers to different formats (e.g., proquints are used as stable identifiers in ChecklistBank)
637
+ # @param mode [String] encode or decode
638
+ # @param id [String] the identifier to convert
639
+ # @param format [String] the format (proquint, hex, latin29, latin32, latin36, base64)
640
+ #
641
+ # @param verbose [Boolean] Print headers to STDOUT
642
+ #
643
+ # @return [String, Integer, Boolean] A parser result hash
644
+ def self.parser_idconverter(mode, id, format, verbose: false)
645
+ endpoint = "parser/idconverter/#{mode}"
646
+ Request.new(endpoint: endpoint, id: id, format: format, verbose: verbose).perform
647
+ end
648
+
649
+ # Parse metadata
650
+ # @param url [String] The url to a metadata file
651
+ # @param format [String] The format of the metadata (yaml, json, eml, datacite, zenodo)
652
+ #
653
+ # @param verbose [Boolean] Print headers to STDOUT
654
+ #
655
+ # @return [String, Integer, Boolean] A parser result hash
656
+ def self.parser_metadata(url, format: nil, verbose: false)
657
+ endpoint = 'parser/metadata'
658
+ Request.new(endpoint: endpoint, url: url, format: format, verbose: verbose).perform
659
+ end
660
+
661
+ # Parse a scientific name
662
+ #
663
+ # @param name [String] The scientific name to parse
664
+ # @param authorship [String, nil] The authorship string for the scientific name
665
+ # @param rank [String, nil] The rank of the scientific name to parse
666
+ # @param code [String] The nomenclatural code (bacterial, botanical, cultivars, phytosociological, virus, zoological)
667
+ #
668
+ # @return [Hash, Boolean] A hash with the parsed scientific name
669
+ def self.parser_name(name, authorship: nil, rank: nil, code: nil, verbose: false)
670
+ endpoint = 'parser/name'
671
+ Request.new(endpoint: endpoint, name: name, authorship: authorship, rank: rank, code: code,
672
+ verbose: verbose).perform
673
+ end
674
+
675
+ # Get metadata patch
676
+ #
677
+ # @param dataset_id [String] The dataset id
678
+ # @param token [String, nil] The authentication token from retrieved with Colrapi.user_login(user, password)
679
+ def self.patch(dataset_id, patch_id: nil, token: nil, verbose: false)
680
+ endpoint = "dataset/#{dataset_id}/patch"
681
+ unless patch_id.nil?
682
+ endpoint = "#{endpoint}/#{patch_id}"
683
+ end
684
+ Request.new(endpoint: endpoint, token: token, verbose: verbose).perform
685
+ end
686
+
687
+ # Get the latest preview release metadata (or points to the project draft dataset after the preview is released?)
688
+ # (Note: you can also use 3LRC where 3 is the project_id as an ID on any endpoint with dataset_id or project_id
689
+ # to get data from the latest release candidate, or 3LR gets the latest release)
690
+ # @param project_id [String] The project id
691
+ #
692
+ # @param verbose [Boolean] Print headers to STDOUT
693
+ # @return [Array, Boolean] An array of hashes
694
+ def self.preview(project_id, verbose: false)
695
+ Request.new(endpoint: "dataset/#{project_id}/preview", verbose: verbose).perform
696
+ end
697
+
698
+ # Get a reference with @reference_id from dataset @dataset_id via the reference route
699
+ #
700
+ # @param dataset_id [String] The dataset id
701
+ # @param reference_id [String] The reference id
702
+ # @param subresource [String] The reference subresource endpoint (orphans)
703
+ # @param issue [Array, String] The data quality issue (https://api.checklistbank.org/vocab/issue)
704
+ #
705
+ # @param offset [Integer] Offset for pagination
706
+ # @param limit [Integer] Limit for pagination
707
+ # @param verbose [Boolean] Print headers to STDOUT
708
+ #
709
+ # @return [Array, Boolean] An array of hashes
710
+ def self.reference(dataset_id, reference_id: nil, subresource: nil, issue: nil, offset: nil, limit: nil,
711
+ verbose: false)
712
+ endpoint = "dataset/#{dataset_id}/reference"
713
+ if subresource == 'orphans'
714
+ reference_id = nil
715
+ endpoint = "#{endpoint}/orphans"
716
+ end
717
+ unless reference_id.nil?
718
+ endpoint = "#{endpoint}/#{reference_id}"
719
+ end
720
+ Request.new(endpoint: endpoint, issue: issue, offset: offset, limit: limit, verbose: verbose).perform
721
+ end
722
+
723
+ # Get reviewer info
724
+ #
725
+ # @param dataset_id [String] The dataset id
726
+ # @param token [String, nil] The authentication token from retrieved with Colrapi.user_login(user, password)
727
+ #
728
+ # # @return [Array, Hash, Boolean] An array of hashes
729
+ def self.reviewer(dataset_id, token, verbose: false)
730
+ endpoint = "dataset/#{dataset_id}/reviewer"
731
+ Request.new(endpoint: endpoint, token: token, verbose: verbose).perform
732
+ end
733
+
734
+ # Get sector metadata, which allows importing datasets into project subtrees
735
+ #
736
+ # @param dataset_id [String] The dataset id
737
+ # @param sector_id [Integer, nil] The sector id
738
+ # @param name [String] The scientific name to query
739
+ # @param rank [String, nil] The rank of the scientific name
740
+ # @param modified_by [Integer, nil] Filter by a user id on last modified by
741
+ # @param broken [Boolean, nil] Whether the decision is broken or not
742
+ # @param subject_dataset_id [String, nil] The source dataset id
743
+ # @param last_synced_before [Date, nil] Filter by sectors synced before this date
744
+ # @param mode [String, nil] Filter by type of sector (attach, union, merge)
745
+ # @param subject [Boolean, nil] TODO: what does this do? All decisions with subject=true are bare names, so maybe it checks if the subject taxon exists?
746
+ # @param min_size [Integer, nil] The minimum number of records in the sector
747
+ # @param without_data [Boolean, nil] Filters to empty sectors with no data synced into the project yet
748
+ #
749
+ # @param offset [Integer] Offset for pagination
750
+ # @param limit [Integer] Limit for pagination
751
+ # @param verbose [Boolean] Print headers to STDOUT
752
+ #
753
+ # @return [Hash, Boolean] An hash of results
754
+ def self.sector(dataset_id, sector_id: nil, name: nil, rank: nil, modified_by: nil, broken: nil,
755
+ subject_dataset_id: nil, last_synced_before: nil, mode: nil, subject: nil, min_size: nil, without_data: nil,
756
+ offset: nil, limit: nil, verbose: false)
757
+ endpoint = "dataset/#{dataset_id}/sector"
758
+ if sector_id.nil?
759
+ Request.new(endpoint: endpoint, name: name, rank: rank, modified_by: modified_by, broken: broken,
760
+ subject_dataset_id: subject_dataset_id, last_synced_before: last_synced_before, mode: mode,
761
+ subject: subject, min_size: min_size, without_data: without_data,
762
+ offset: offset, limit: limit, verbose: verbose).perform
763
+ else
764
+ endpoint = "#{endpoint}/#{sector_id}"
765
+ Request.new(endpoint: endpoint, verbose: verbose).perform
766
+ end
767
+ end
768
+
769
+ # Get sector sync info
770
+ #
771
+ # @param dataset_id [String] The dataset id
772
+ # @param sector_id [Integer, nil] The sector id
773
+ # @param state [Array, String, nil] The sector sync state (e.g., waiting, processing, inserting, indexing, finished, etc.)
774
+ # @param running [Boolean, nil] Filter to sector syncs that are only running
775
+ # @param attempt [Integer, nil] The sync attempt number for sector_id
776
+ # @param subresource [String, nil] The subresource for attempt (names or tree)
777
+ #
778
+ # @param offset [Integer] Offset for pagination
779
+ # @param limit [Integer] Limit for pagination
780
+ # @param verbose [Boolean] Print headers to STDOUT
781
+ #
782
+ # @return [Hash, Boolean] An hash of results
783
+ def self.sector_sync(dataset_id, sector_id: nil, attempt: nil, subresource: nil, state: nil, running: nil, offset: nil, limit: nil, verbose: false)
784
+ endpoint = "dataset/#{dataset_id}/sector/sync"
785
+ if sector_id.nil?
786
+ Request.new(endpoint: endpoint, state: state, running: running, offset: offset, limit: limit,
787
+ verbose:verbose).perform
788
+ else
789
+ if attempt.nil?
790
+ endpoint = "dataset/#{dataset_id}/sector/#{sector_id}/sync"
791
+ else
792
+ endpoint = "dataset/#{dataset_id}/sector/#{sector_id}/sync/#{attempt}"
793
+ endpoint = "#{endpoint}/#{subresource}" unless subresource.nil?
794
+ end
795
+ Request.new(endpoint: endpoint, verbose:verbose).perform
796
+ end
797
+ end
798
+
799
+ # Get source metadata for datasets assembled into a project dataset
800
+ #
801
+ # @param dataset_id [String] The project dataset id
802
+ # @param source_id [String] The source dataset id
803
+ # @param not_current_only [String] Return only not current sources
804
+ # @param original [String] TODO: what does this do?
805
+ #
806
+ # @return [Array, Hash, Boolean] An array of source hashes, or a hash of a source
807
+ def self.source(dataset_id, source_id: nil, not_current_only: nil, original: nil, verbose: false)
808
+ endpoint = "dataset/#{dataset_id}/source"
809
+ if source_id.nil?
810
+ Request.new(endpoint: endpoint, not_current_only: not_current_only, verbose: verbose).perform
811
+ else
812
+ endpoint = "dataset/#{dataset_id}/source/#{source_id}"
813
+ Request.new(endpoint: endpoint, original: original, verbose: verbose).perform
814
+ end
815
+ end
816
+
817
+
818
+ # Get the dataset settings
819
+ # @param dataset_id [String] The dataset id
820
+ #
821
+ # @return [Hash, Boolean] A hash including the dataset settings
822
+ def self.settings(dataset_id)
823
+ Request.new(endpoint: "dataset/#{dataset_id}/settings").perform
824
+ end
825
+
826
+ # Get a synonym with @synonym_id from dataset @dataset_id via the synonym route
827
+ #
828
+ # @param dataset_id [String] The dataset id
829
+ # @param synonym_id [String] The synonym id
830
+ # @param subresource [String] The synonym subresource endpoint (source)
831
+ #
832
+ # @param offset [Integer] Offset for pagination
833
+ # @param limit [Integer] Limit for pagination
834
+ # @param verbose [Boolean] Print headers to STDOUT
835
+ #
836
+ # @return [Array, Boolean] An array of hashes
837
+ def self.synonym(dataset_id, synonym_id: nil, subresource: nil, offset: nil, limit: nil, verbose: false)
838
+ endpoint = "dataset/#{dataset_id}/synonym"
839
+ unless synonym_id.nil?
840
+ endpoint = "#{endpoint}/#{synonym_id}"
841
+ end
842
+ if subresource == 'source'
843
+ endpoint = "#{endpoint}/source"
844
+ end
845
+ Request.new(endpoint: endpoint, offset: offset, limit: limit, verbose: verbose).perform
846
+ end
847
+
848
+ # Get the full list of taxon IDs for a dataset (returns 1 ID string per line, not JSON)
849
+ #
850
+ # @param dataset_id [String] The dataset id
851
+ #
852
+ # @return [Array, Boolean] An array of hashes
853
+ def self.taxon_ids(dataset_id, verbose: false)
854
+ Request.new(endpoint: "dataset/#{dataset_id}/taxon/ids", verbose: verbose).perform
855
+ end
856
+
857
+ # Get a taxon with @id from dataset @dataset_id via the taxon route
858
+ #
859
+ # @param dataset_id [String] The dataset id
860
+ # @param taxon_id [String] The taxon id
861
+ # @param subresource [String] The taxon subresource endpoint (classification, distribution, info, interaction, media,
862
+ # relation, source, synonyms, treatment, or vernacular)
863
+ # @param format [String] The format of the treatment (plain_text, markdown, xml, html, tax_pub, taxon_x, rdf)
864
+ #
865
+ # @param offset [Integer] Offset for pagination
866
+ # @param limit [Integer] Limit for pagination
867
+ # @param verbose [Boolean] Print headers to STDOUT
868
+ #
869
+ # @return [Array, Boolean] An array of hashes
870
+ def self.taxon(dataset_id, taxon_id: nil, subresource: nil, format: nil, offset: nil, limit: nil, verbose: false)
871
+ endpoint = "dataset/#{dataset_id}/taxon"
872
+ unless taxon_id.nil?
873
+ endpoint = "#{endpoint}/#{taxon_id}"
874
+ end
875
+
876
+ if !subresource.nil?
877
+ endpoint = "#{endpoint}/#{subresource}"
878
+ end
879
+ Request.new(endpoint: endpoint, offset: offset, format: format, limit: limit, verbose: verbose).perform
880
+ end
881
+
882
+ # Get the root taxa
883
+ #
884
+ # @param dataset_id [String] The dataset id
885
+ # @param taxon_id [String] The taxon id
886
+ # @param children [Boolean] Display the children of taxon_id
887
+ #
888
+ # @param offset [Integer] Offset for pagination
889
+ # @param limit [Integer] Limit for pagination
890
+ # @param verbose [Boolean] Print headers to STDOUT
891
+ #
892
+ # @return [Array, Boolean] An array of hashes
893
+ def self.tree(dataset_id, taxon_id: nil, children: false, offset: nil, limit: nil, verbose: false)
894
+ endpoint = "dataset/#{dataset_id}/tree"
895
+ endpoint = "#{endpoint}/#{taxon_id}" unless taxon_id.nil?
896
+ endpoint = "#{endpoint}/children" unless taxon_id.nil? or !children
897
+ Request.new(endpoint: endpoint, offset: offset, limit: limit, verbose: verbose).perform
898
+ end
899
+
900
+ # Get user data
901
+ #
902
+ # @param user_id [Integer, nil] The user id
903
+ # @param q [String, nil] The search query
904
+ # @param role [String, nil] The user role (admin, editor, or reviewer)
905
+ #
906
+ # @param offset [Integer] Offset for pagination
907
+ # @param limit [Integer] Limit for pagination
908
+ # @param token [String, nil] The authentication token from retrieved with Colrapi.user_login(user, password)
909
+ # @param verbose [Boolean] Print headers to STDOUT
910
+ #
911
+ # @return [Array, Boolean] An array of hashes
912
+ def self.user(user_id: nil, q: nil, role: nil, offset: nil, limit: nil, token: nil, verbose: false)
913
+ if user_id.nil?
914
+ endpoint = "user"
915
+ Request.new(endpoint: endpoint, q: q, role: role, offset: offset, limit: limit, token: token,
916
+ verbose: verbose).perform
917
+ else
918
+ endpoint = "user/#{user_id}"
919
+ Request.new(endpoint: endpoint, token: token, verbose: verbose).perform
920
+ end
921
+ end
922
+
923
+ # Get datasets user can access
924
+ # @param token [String] The access token from Colrapi.user_login()
925
+ # @param dataset_id [String, nil] A dataset id to check
926
+ # @param origin [Array, String, nil] Filter by the origin of a dataset (external, project, release, xrelease)
927
+ #
928
+ # @return [Array, Boolean] An array of datasets, or returns a boolean if dataset_id is provided
929
+ def self.user_dataset(token, dataset_id: nil, origin: nil, verbose: false)
930
+ endpoint = "user/dataset"
931
+ if dataset_id.nil?
932
+ Request.new(endpoint: endpoint, token: token, origin: origin, verbose: verbose).perform
933
+ else
934
+ endpoint = "user/dataset/#{dataset_id}"
935
+ Request.new(endpoint: endpoint, token: token, verbose: verbose).perform
936
+ end
937
+ end
938
+
939
+ # Authenticate user and get authentication token
940
+ def self.user_login(user, password, verbose: false)
941
+ Request.new(endpoint: "user/login", user: user, password: password, verbose: verbose).perform
942
+ end
943
+
944
+ # Get the authenticated user
945
+ #
946
+ # @param token [String, nil] The authentication token from retrieved with Colrapi.user_login(user, password)
947
+ # @param verbose [Boolean] Print headers to STDOUT
948
+ #
949
+ # @return [Array, Boolean] An array of hashes
950
+ def self.user_me(token, verbose: false)
951
+ Request.new(endpoint: "user/me", token: token, verbose: verbose).perform
952
+ end
953
+
954
+ # Get verbatim data
955
+ #
956
+ # @param dataset_id [String] The dataset id
957
+ # @param verbatim_id [String] The verbatim id
958
+ # @param q [String] The search query string
959
+ # @param issue [Array, String] Filter by data quality issue (e.g., ACCEPTED_NAME_MISSING, DUPLICATE_NAME, URL_INVALID)
960
+ # @param type [Array, String] The file type (e.g., acef:AcceptedSpecies, col:Taxon, dwc:Taxon)
961
+ #
962
+ # TODO: May not work yet: https://github.com/CatalogueOfLife/backend/issues/1201
963
+ # @param term [Array, String] Filter by term (http://api.checklistbank.org/vocab/term)
964
+ # @param term_operator [String] The operator to use with term ('and' or 'or')
965
+ #
966
+ # @param offset [Integer] Offset for pagination
967
+ # @param limit [Integer] Limit for pagination
968
+ # @param verbose [Boolean] Print headers to STDOUT
969
+ #
970
+ # @return [Array, Boolean] An array of hashes
971
+ def self.verbatim(dataset_id, verbatim_id: nil, q: nil, issue: nil, type: nil, term: nil, term_operator: nil,
972
+ offset: nil, limit: nil, verbose: false)
973
+ endpoint = "dataset/#{dataset_id}/verbatim"
974
+ if verbatim_id.nil?
975
+ Request.new(endpoint: endpoint, q: q, issue: issue, type: type, term: term, term_operator: term_operator,
976
+ offset: offset, limit: limit, verbose: verbose).perform
977
+ else
978
+ endpoint = "#{endpoint}/#{verbatim_id}"
979
+ Request.new(endpoint: endpoint, verbose: verbose).perform
980
+ end
981
+ end
982
+
983
+ # Get vernacular names
984
+ #
985
+ # @param dataset_id [String, nil] The dataset id
986
+ # @param q [String] A vernacular name search query
987
+ # @param language [String, nil] The language of the vernacular name (see: http://api.checklistbank.org/vocab/language)
988
+ #
989
+ # @param offset [Integer] Offset for pagination
990
+ # @param limit [Integer] Limit for pagination
991
+ # @param verbose [Boolean] Print headers to STDOUT
992
+ #
993
+ # @return [Hash] A hash of vernacular results
994
+ def self.vernacular(dataset_id: nil, q: nil, language: nil, offset: nil, limit: nil, verbose: false)
995
+ if dataset_id.nil?
996
+ endpoint = 'vernacular'
997
+ Request.new(endpoint: endpoint, q: q, language: language, offset: offset, limit: limit, verbose: verbose).perform
998
+ else
999
+ endpoint = "dataset/#{dataset_id}/vernacular"
1000
+ Request.new(endpoint: endpoint, q: q, language: language, offset: offset, limit: limit, verbose: verbose).perform
1001
+ end
1002
+ end
1003
+
1004
+ # Get backend version
1005
+ #
1006
+ # @return [String] A version string
1007
+ def self.version(verbose: false)
1008
+ Request.new(endpoint: 'version', verbose: verbose).perform
1009
+ end
1010
+
1011
+ # Get vocab
1012
+ # @param term [String] The vocab term
1013
+ # @param subresource [String] The subresource which is usually the id, code, or name
1014
+ # @param children [Boolean] Returns the geotime's children if true
1015
+ #
1016
+ # @param verbose [Boolean] Print headers to STDOUT
1017
+ #
1018
+ # @return [Array]
1019
+ def self.vocab(term: nil, subresource: nil, children: false, verbose: false)
1020
+ endpoint = "vocab"
1021
+ endpoint = "#{endpoint}/#{term}" unless term.nil?
1022
+ endpoint = "#{endpoint}/#{subresource}" unless term.nil? or subresource.nil?
1023
+ endpoint = "#{endpoint}/children" if children and term == "geotime"
1024
+ Request.new(endpoint: endpoint, verbose: verbose).perform
1025
+ end
1026
+ end