uc3-dmp-id 0.1.6 → 0.1.7
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/lib/uc3-dmp-id/augmenter.rb +153 -0
- data/lib/uc3-dmp-id/comparator.rb +0 -3
- data/lib/uc3-dmp-id/schemas/author.rb +211 -158
- data/lib/uc3-dmp-id/updater.rb +9 -27
- data/lib/uc3-dmp-id/version.rb +1 -1
- data/lib/uc3-dmp-id.rb +1 -0
- metadata +31 -3
- data/lib/uc3-dmp-id/asserter.rb +0 -216
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5d3c26185a12403a3c3dfa1b9ab0dec6b798b1b127905a22d04f6f929d8cbf73
|
|
4
|
+
data.tar.gz: de6b7a8f6c3395516ed10adc6eb55d0d84a9f52ae785dc36418f408f097c5900
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1e790c4ee74028bc85b924ec1f82b4301be23014f1e0543c69103e285993002be0c00642b0a58a3e2d7418956708142f562f5306af69eeae3377609e5a3f3cb9
|
|
7
|
+
data.tar.gz: 06bd91810cde2da48258c1a22bc699788a131c1e4aaae3b1d12f86edbfb55ac85fd560803dcc84df4632fbafa9257650f56529d0475b03f291a4b9e0b76e829d
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'bibtex'
|
|
4
|
+
require 'securerandom'
|
|
5
|
+
|
|
6
|
+
module Uc3DmpId
|
|
7
|
+
class AugmenterError < StandardError; end
|
|
8
|
+
|
|
9
|
+
# Class that adds items to the :dmphub_modifications array or directly to the
|
|
10
|
+
# :dmpraodmap_related_identifiers array if the confidence level was 'Absolute'
|
|
11
|
+
class Augmenter
|
|
12
|
+
attr_accessor :augmenter, :dmp, :known_mods, :known_works, :known_awards, :logger
|
|
13
|
+
|
|
14
|
+
MSG_MISSING_ANNOTATIONS = 'DMP must have its DMPHub specific annotations!'
|
|
15
|
+
MSG_MISSING_AUGMENTER = 'No Augmenter specified!'
|
|
16
|
+
MSG_MISSING_DMP = 'No DMP or the DMP did not contain enough information to use.'
|
|
17
|
+
|
|
18
|
+
# rubocop:disable Metrics/AbcSize
|
|
19
|
+
def initialize(**args)
|
|
20
|
+
@logger = args[:logger]
|
|
21
|
+
@augmenter = args[:augmenter]
|
|
22
|
+
raise AugmenterError, MSG_MISSING_AUGMENTER unless @augmenter.is_a?(Hash) && !@augmenter['PK'].nil?
|
|
23
|
+
|
|
24
|
+
@dmp = args.fetch(:dmp, {})['dmp'].nil? ? args[:dmp] : args.fetch(:dmp, {})['dmp']
|
|
25
|
+
raise AugmenterError, MSG_MISSING_DMP if @dmp.nil? || @dmp['dmp_id'].nil?
|
|
26
|
+
raise AugmenterError, MSG_MISSING_ANNOTATIONS if @dmp['PK'].nil?
|
|
27
|
+
|
|
28
|
+
_extract_known
|
|
29
|
+
end
|
|
30
|
+
# rubocop:enable Metrics/AbcSize
|
|
31
|
+
|
|
32
|
+
# rubocop:disable Metrics/AbcSize
|
|
33
|
+
def add_modifications(works:)
|
|
34
|
+
mod_hash = _generate_mod_header
|
|
35
|
+
|
|
36
|
+
works.fetch('publications', []).each do |publication|
|
|
37
|
+
# Skip the entry if we already know about this identifier
|
|
38
|
+
next if @known_works.include?(publication['id'])
|
|
39
|
+
|
|
40
|
+
work_hash = _work_to_mod_entry(type: 'publication', work: publication)
|
|
41
|
+
mod_hash.fetch('dmproadmap_related_identifiers', []) << work_hash unless work_hash.nil?
|
|
42
|
+
fundings = publication.fetch('fundingReferences', [])
|
|
43
|
+
next unless fundings.any?
|
|
44
|
+
|
|
45
|
+
award_hash = fundings.map { |funding| _funding_to_mod_entry(funding:) }
|
|
46
|
+
mod_hash.fetch('funding', []) << award_hash unless award_hash.nil?
|
|
47
|
+
end
|
|
48
|
+
return 0 unless mod_hash['dmproadmap_related_identifiers'].any? || mod_hash.fetch('funding', []).any?
|
|
49
|
+
|
|
50
|
+
# Save the DMP
|
|
51
|
+
mods = (@known_mods.nil? ? [] : @known_mods)
|
|
52
|
+
@dmp['dmphub_modifications'] = (@known_mods.nil? ? [] : @known_mods) << mod_hash
|
|
53
|
+
|
|
54
|
+
client = Uc3DmpDynamo::Client.new
|
|
55
|
+
resp = client.put_item(json: @dmp, logger:)
|
|
56
|
+
raise AugmenterError, Helper::MSG_DMP_NO_DMP_ID if resp.nil?
|
|
57
|
+
|
|
58
|
+
# Return the number of modifications added to the DMP
|
|
59
|
+
mod_hash.fetch('dmproadmap_related_identifiers', []).length + mod_hash.fetch('funding', []).length
|
|
60
|
+
end
|
|
61
|
+
# rubocop:enable Metrics/AbcSize
|
|
62
|
+
|
|
63
|
+
private
|
|
64
|
+
|
|
65
|
+
def _generate_mod_header
|
|
66
|
+
JSON.parse({
|
|
67
|
+
id: "#{Time.now.utc.strftime('%Y-%m-%d')}-#{SecureRandom.hex(4)}",
|
|
68
|
+
provenance: @augmenter['name'],
|
|
69
|
+
timestamp: Time.now.utc.iso8601,
|
|
70
|
+
dmproadmap_related_identifiers: [],
|
|
71
|
+
fundings: []
|
|
72
|
+
}.to_json)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# rubocop:disable Metrics/AbcSize
|
|
76
|
+
def _work_to_mod_entry(type:, work:)
|
|
77
|
+
return nil if work['id'].nil?
|
|
78
|
+
|
|
79
|
+
ret = {
|
|
80
|
+
type: 'doi',
|
|
81
|
+
identifier: work['id'],
|
|
82
|
+
descriptor: 'references',
|
|
83
|
+
status: 'pending'
|
|
84
|
+
}
|
|
85
|
+
work_type = work.fetch('type', 'Text')&.downcase&.strip
|
|
86
|
+
ret[:work_type] = work_type == 'text' ? type : work_type
|
|
87
|
+
return JSON.parse(ret.to_json) if work['bibtex'].nil?
|
|
88
|
+
|
|
89
|
+
ret[:citation] = Uc3DmpCitation::Citer.bibtex_to_citation(bibtex_as_string: work['bibtex'])
|
|
90
|
+
JSON.parse(ret.to_json)
|
|
91
|
+
end
|
|
92
|
+
# rubocop:enable Metrics/AbcSize
|
|
93
|
+
|
|
94
|
+
# Convert a funding entry for the dmphub_modification
|
|
95
|
+
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
|
96
|
+
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
97
|
+
def _funding_to_mod_entry(funding:)
|
|
98
|
+
return nil unless funding.is_a?(Hash) && (!funding['awardUri'] || !funding['awardNumber'])
|
|
99
|
+
return nil if @known_awards.include?(funding['awardUri']) || @known_awards.include?(funding['awardNumber'])
|
|
100
|
+
|
|
101
|
+
id = funding['awardUri'] if funding.fetch('awardUri', '').start_with?('http')
|
|
102
|
+
id = funding['awardNumber'] if id.nil?
|
|
103
|
+
|
|
104
|
+
ret = {
|
|
105
|
+
status: 'pending',
|
|
106
|
+
name: funding['funderName'],
|
|
107
|
+
funding_status: 'granted',
|
|
108
|
+
grant_id: {
|
|
109
|
+
type: if id.start_with?('http')
|
|
110
|
+
id.include?('doi') ? 'doi' : 'url'
|
|
111
|
+
else
|
|
112
|
+
'other'
|
|
113
|
+
end,
|
|
114
|
+
identifier: id
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
funder_id = funding['funderIdentifier']
|
|
118
|
+
return JSON.parse(ret.to_json) if funder_id.nil?
|
|
119
|
+
|
|
120
|
+
ret[:funder_id] = {
|
|
121
|
+
type: if funder_id.include?('ror')
|
|
122
|
+
'ror'
|
|
123
|
+
else
|
|
124
|
+
(funder_id.start_with?('http') ? 'url' : 'other')
|
|
125
|
+
end,
|
|
126
|
+
identifier: funder_id
|
|
127
|
+
}
|
|
128
|
+
JSON.parse(ret.to_json)
|
|
129
|
+
end
|
|
130
|
+
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
|
131
|
+
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
132
|
+
|
|
133
|
+
# Retrieve all of the known modifications, related identifiers and awards from the DMP
|
|
134
|
+
# rubocop:disable Metrics/AbcSize
|
|
135
|
+
def _extract_known
|
|
136
|
+
@known_mods = @dmp.fetch('dmphub_modifications', [])
|
|
137
|
+
|
|
138
|
+
ids = @dmp.fetch('dmproadmap_related_identifiers', []).map { |id| id['identifier'] }
|
|
139
|
+
ids += @known_mods.map { |m| m.fetch('dmproadmap_related_identifiers', []).map { |i| i['identifier'] } }
|
|
140
|
+
@known_works = ids.flatten.compact.uniq
|
|
141
|
+
|
|
142
|
+
fundings = @dmp.fetch('project', []).map { |proj| proj.fetch('funding', []) }.flatten.compact.uniq
|
|
143
|
+
awards = fundings.map { |fund| [fund['dmproadmap_funding_opportunity_id'], fund['grant_id']] }
|
|
144
|
+
.flatten.compact.uniq
|
|
145
|
+
|
|
146
|
+
awards += @known_mods.map do |mod|
|
|
147
|
+
mod.fetch('funding', []).map { |fund| [fund['dmproadmap_funding_opportunity_id'], fund['grant_id']] }
|
|
148
|
+
end
|
|
149
|
+
@known_awards = awards.flatten.compact.uniq.map { |award| award['identifier'] }.flatten.compact.uniq
|
|
150
|
+
end
|
|
151
|
+
# rubocop:enable Metrics/AbcSize
|
|
152
|
+
end
|
|
153
|
+
end
|
|
@@ -9,7 +9,6 @@ module Uc3DmpId
|
|
|
9
9
|
# Class that compares incoming data from an external source to the DMP
|
|
10
10
|
# It determines if they are likely related and applies a confidence rating
|
|
11
11
|
class Comparator
|
|
12
|
-
MSG_MISSING_AUGMENTER = 'No Augmenter specified!'
|
|
13
12
|
MSG_MISSING_DMP = 'No DMP or the DMP did not contain enough information to use.'
|
|
14
13
|
|
|
15
14
|
STOP_WORDS = %w[a an and if of or the then they].freeze
|
|
@@ -19,7 +18,6 @@ module Uc3DmpId
|
|
|
19
18
|
|
|
20
19
|
attr_accessor :dmp, :details_hash, :logger
|
|
21
20
|
|
|
22
|
-
# rubocop:disable Metrics/AbcSize
|
|
23
21
|
def initialize(**args)
|
|
24
22
|
@logger = args[:logger]
|
|
25
23
|
@details_hash = {}
|
|
@@ -28,7 +26,6 @@ module Uc3DmpId
|
|
|
28
26
|
_extract_dmp_details(dmp:)
|
|
29
27
|
raise ComparatorError, MSG_MISSING_DMP if @details_hash.empty?
|
|
30
28
|
end
|
|
31
|
-
# rubocop:enable Metrics/AbcSize
|
|
32
29
|
|
|
33
30
|
# Compare the incoming hash with the DMP details that were gathered during initialization.
|
|
34
31
|
#
|
|
@@ -989,173 +989,226 @@ module Uc3DmpId
|
|
|
989
989
|
title: 'Descriptive note',
|
|
990
990
|
examples: ['data received from event data']
|
|
991
991
|
},
|
|
992
|
-
|
|
993
|
-
'$id': '#/properties/dmp/properties/dmphub_modifications/items/properties/
|
|
994
|
-
type: '
|
|
995
|
-
title: '
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
992
|
+
dmproadmap_related_identifiers: {
|
|
993
|
+
'$id': '#/properties/dmp/properties/dmphub_modifications/items/properties/dmproadmap_related_identifiers',
|
|
994
|
+
type: 'array',
|
|
995
|
+
title: 'Related identifier modifications',
|
|
996
|
+
description: 'Identifiers discovered by an external API',
|
|
997
|
+
items: {
|
|
998
|
+
'$id': '#/properties/dmp/properties/dmphub_modifications/items/properties/dmproadmap_related_identifiers/items',
|
|
999
|
+
type: 'object',
|
|
1000
|
+
title: 'A related identifier',
|
|
1001
|
+
properties: {
|
|
1002
|
+
descriptor: {
|
|
1003
|
+
'$id': '#/properties/dmp/properties/dmphub_modifications/items/properties/dmproadmap_related_identifiers/items/properties/descriptor',
|
|
1004
|
+
type: 'string',
|
|
1005
|
+
enum: %w[
|
|
1006
|
+
is_cited_by
|
|
1007
|
+
cites
|
|
1008
|
+
is_supplement_to
|
|
1009
|
+
is_supplemented_by
|
|
1010
|
+
is_described_by
|
|
1011
|
+
describes
|
|
1012
|
+
has_metadata
|
|
1013
|
+
is_metadata_for
|
|
1014
|
+
is_part_of
|
|
1015
|
+
has_part
|
|
1016
|
+
is_referenced_by
|
|
1017
|
+
references
|
|
1018
|
+
is_documented_by
|
|
1019
|
+
documents
|
|
1020
|
+
is_new_version_of
|
|
1021
|
+
is_previous_version_of
|
|
1022
|
+
]
|
|
1023
|
+
},
|
|
1024
|
+
identifier: {
|
|
1025
|
+
'$id': '#/properties/dmp/properties/dmphub_modifications/items/properties/dmproadmap_related_identifiers/items/properties/identifier',
|
|
1026
|
+
type: 'string',
|
|
1027
|
+
title: 'A unique identifier for the item',
|
|
1028
|
+
description: 'Identifier for a DMP',
|
|
1029
|
+
examples: ['https://doi.org/10.1371/journal.pcbi.1006750']
|
|
1030
|
+
},
|
|
1031
|
+
status: {
|
|
1032
|
+
'$id': '#/properties/dmp/properties/dmphub_modifications/items/properties/dmproadmap_related_identifiers/items/properties/status',
|
|
1033
|
+
type: 'string',
|
|
1034
|
+
title: 'Modification status',
|
|
1035
|
+
enum: %w[
|
|
1036
|
+
accepted
|
|
1037
|
+
pending
|
|
1038
|
+
rejected
|
|
1039
|
+
]
|
|
1040
|
+
},
|
|
1041
|
+
type: {
|
|
1042
|
+
'$id': '#/properties/dmp/properties/dmphub_modifications/items/properties/dmproadmap_related_identifiers/items/properties/type',
|
|
1043
|
+
type: 'string',
|
|
1044
|
+
enum: %w[
|
|
1045
|
+
handle
|
|
1046
|
+
doi
|
|
1047
|
+
ark
|
|
1048
|
+
url
|
|
1049
|
+
other
|
|
1050
|
+
]
|
|
1051
|
+
},
|
|
1052
|
+
work_type: {
|
|
1053
|
+
'$id': '#/properties/dmp/properties/dmphub_modifications/items/properties/dmproadmap_related_identifiers/items/properties/work_type',
|
|
1054
|
+
type: 'string'
|
|
1055
|
+
}
|
|
1046
1056
|
},
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
identifier
|
|
1055
|
-
type
|
|
1056
|
-
work_type
|
|
1057
|
-
]
|
|
1057
|
+
required: %w[
|
|
1058
|
+
descriptor
|
|
1059
|
+
identifier
|
|
1060
|
+
type
|
|
1061
|
+
work_type
|
|
1062
|
+
]
|
|
1063
|
+
}
|
|
1058
1064
|
},
|
|
1059
1065
|
funding: {
|
|
1060
1066
|
'$id': '#/properties/dmp/properties/dmphub_modifications/items/properties/funding',
|
|
1061
|
-
type: '
|
|
1062
|
-
title: '
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1067
|
+
type: 'array',
|
|
1068
|
+
title: 'Funding modifications',
|
|
1069
|
+
description: 'Funding information discovered by an external API',
|
|
1070
|
+
items: {
|
|
1071
|
+
'$id': '#/properties/dmp/properties/dmphub_modifications/items/properties/funding/items',
|
|
1072
|
+
type: 'object',
|
|
1073
|
+
title: 'A funding',
|
|
1074
|
+
properties: {
|
|
1075
|
+
dmproadmap_project_number: {
|
|
1076
|
+
'$id': '#/properties/dmp/properties/project/items/properties/funding/items/properties/dmproadmap_project_number',
|
|
1077
|
+
type: 'string',
|
|
1078
|
+
title: "The funder's identifier for the research project",
|
|
1079
|
+
description: "The funder's identifier used to identify the research project",
|
|
1080
|
+
examples: ['prj-XYZ987-UCB']
|
|
1081
|
+
},
|
|
1082
|
+
funder_id: {
|
|
1083
|
+
'$id': '#/properties/dmp/properties/dmphub_modifications/items/properties/funding/items/properties/funder_id',
|
|
1084
|
+
type: 'object',
|
|
1085
|
+
title: 'The Funder ID Schema',
|
|
1086
|
+
description: 'Funder ID of the associated project',
|
|
1087
|
+
properties: {
|
|
1088
|
+
identifier: {
|
|
1089
|
+
'$id': '#/properties/dmp/properties/dmphub_modifications/items/properties/funding/items/properties/funder_id/properties/identifier',
|
|
1090
|
+
type: 'string',
|
|
1091
|
+
title: 'The Funder ID Value Schema',
|
|
1092
|
+
description: 'Funder ID, recommended to use CrossRef Funder Registry. See: https://www.crossref.org/services/funder-registry/',
|
|
1093
|
+
examples: ['501100002428']
|
|
1094
|
+
},
|
|
1095
|
+
type: {
|
|
1096
|
+
'$id': '#/properties/dmp/properties/dmphub_modifications/items/properties/funding/items/properties/funder_id/properties/type',
|
|
1097
|
+
type: 'string',
|
|
1098
|
+
enum: %w[
|
|
1099
|
+
fundref
|
|
1100
|
+
ror
|
|
1101
|
+
url
|
|
1102
|
+
other
|
|
1103
|
+
],
|
|
1104
|
+
title: 'The Funder ID Type Schema',
|
|
1105
|
+
description: 'Identifier type. Allowed values: fundref, url, other',
|
|
1106
|
+
examples: ['fundref']
|
|
1107
|
+
}
|
|
1083
1108
|
},
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
type
|
|
1087
|
-
|
|
1088
|
-
fundref
|
|
1089
|
-
ror
|
|
1090
|
-
url
|
|
1091
|
-
other
|
|
1092
|
-
],
|
|
1093
|
-
title: 'The Funder ID Type Schema',
|
|
1094
|
-
description: 'Identifier type. Allowed values: fundref, url, other',
|
|
1095
|
-
examples: ['fundref']
|
|
1096
|
-
}
|
|
1109
|
+
required: %w[
|
|
1110
|
+
identifier
|
|
1111
|
+
type
|
|
1112
|
+
]
|
|
1097
1113
|
},
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
type
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
applied
|
|
1109
|
-
granted
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
type:
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1114
|
+
funding_status: {
|
|
1115
|
+
'$id': '#/properties/dmp/properties/dmphub_modifications/items/properties/funding/items/properties/funding_status',
|
|
1116
|
+
type: 'string',
|
|
1117
|
+
enum: %w[
|
|
1118
|
+
planned
|
|
1119
|
+
applied
|
|
1120
|
+
granted
|
|
1121
|
+
rejected
|
|
1122
|
+
],
|
|
1123
|
+
title: 'The Funding Status Schema',
|
|
1124
|
+
description: 'To express different phases of project lifecycle. Allowed values: planned, applied, granted, rejected',
|
|
1125
|
+
examples: ['granted']
|
|
1126
|
+
},
|
|
1127
|
+
dmproadmap_funding_opportunity_id: {
|
|
1128
|
+
'$id': '#/properties/dmp/properties/dmphub_modifications/items/properties/funding/items/properties/dmproadmap_funding_opportunity_id',
|
|
1129
|
+
type: 'object',
|
|
1130
|
+
title: 'The Funding Opportunity ID Schema',
|
|
1131
|
+
description: 'Opportunity ID of the associated project',
|
|
1132
|
+
properties: {
|
|
1133
|
+
identifier: {
|
|
1134
|
+
'$id': '#/properties/dmp/properties/dmphub_modifications/items/properties/funding/items/properties/dmproadmap_funding_opportunity_id/properties/identifier',
|
|
1135
|
+
type: 'string',
|
|
1136
|
+
title: 'The Funding Opportunity ID Value Schema',
|
|
1137
|
+
description: 'Opportunity ID',
|
|
1138
|
+
examples: ['ABC-12345-03']
|
|
1139
|
+
},
|
|
1140
|
+
type: {
|
|
1141
|
+
'$id': '#/properties/dmp/properties/dmphub_modifications/items/properties/funding/items/properties/dmproadmap_funding_opportunity_id/properties/type',
|
|
1142
|
+
type: 'string',
|
|
1143
|
+
title: 'The Funding Opportunity ID Type Schema',
|
|
1144
|
+
enum: %w[
|
|
1145
|
+
doi
|
|
1146
|
+
url
|
|
1147
|
+
other
|
|
1148
|
+
],
|
|
1149
|
+
description: 'Identifier type. Allowed values: url, other',
|
|
1150
|
+
examples: ['other']
|
|
1151
|
+
}
|
|
1128
1152
|
},
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
type
|
|
1132
|
-
|
|
1133
|
-
enum: %w[
|
|
1134
|
-
doi
|
|
1135
|
-
url
|
|
1136
|
-
other
|
|
1137
|
-
],
|
|
1138
|
-
description: 'Identifier type. Allowed values: url, other',
|
|
1139
|
-
examples: ['other']
|
|
1140
|
-
}
|
|
1153
|
+
required: %w[
|
|
1154
|
+
identifier
|
|
1155
|
+
type
|
|
1156
|
+
]
|
|
1141
1157
|
},
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
type
|
|
1145
|
-
|
|
1158
|
+
grant_id: {
|
|
1159
|
+
'$id': '#/properties/dmp/properties/dmphub_modifications/items/properties/funding/items/properties/grant_id',
|
|
1160
|
+
type: 'object',
|
|
1161
|
+
title: 'The Funding Grant ID Schema',
|
|
1162
|
+
description: 'Grant ID of the associated project',
|
|
1163
|
+
properties: {
|
|
1164
|
+
identifier: {
|
|
1165
|
+
'$id': '#/properties/dmp/properties/dmphub_modifications/items/properties/funding/items/properties/grant_id/properties/identifier',
|
|
1166
|
+
type: 'string',
|
|
1167
|
+
title: 'The Funding Grant ID Value Schema',
|
|
1168
|
+
description: 'Grant ID',
|
|
1169
|
+
examples: ['776242']
|
|
1170
|
+
},
|
|
1171
|
+
type: {
|
|
1172
|
+
'$id': '#/properties/dmp/properties/dmphub_modifications/items/properties/funding/items/properties/grant_id/properties/type',
|
|
1173
|
+
type: 'string',
|
|
1174
|
+
title: 'The Funding Grant ID Type Schema',
|
|
1175
|
+
enum: %w[
|
|
1176
|
+
doi
|
|
1177
|
+
url
|
|
1178
|
+
other
|
|
1179
|
+
],
|
|
1180
|
+
description: 'Identifier type. Allowed values: url, other',
|
|
1181
|
+
examples: ['other']
|
|
1182
|
+
}
|
|
1183
|
+
},
|
|
1184
|
+
required: %w[
|
|
1185
|
+
identifier
|
|
1186
|
+
type
|
|
1187
|
+
]
|
|
1188
|
+
},
|
|
1189
|
+
status: {
|
|
1190
|
+
'$id': '#/properties/dmp/properties/dmphub_modifications/items/properties/funding/items/properties/status',
|
|
1191
|
+
type: 'string',
|
|
1192
|
+
title: 'Modification status',
|
|
1193
|
+
enum: %w[
|
|
1194
|
+
accepted
|
|
1195
|
+
pending
|
|
1196
|
+
rejected
|
|
1197
|
+
]
|
|
1198
|
+
},
|
|
1199
|
+
name: {
|
|
1200
|
+
'$id': '#/properties/dmp/properties/dmphub_modifications/items/properties/funding/items/properties/name',
|
|
1201
|
+
type: 'string',
|
|
1202
|
+
title: 'The name of the funding instituion / organization',
|
|
1203
|
+
description: 'Name',
|
|
1204
|
+
examples: ['National Science Foundation']
|
|
1205
|
+
}
|
|
1146
1206
|
},
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
examples: ['National Science Foundation']
|
|
1153
|
-
}
|
|
1154
|
-
},
|
|
1155
|
-
required: %w[
|
|
1156
|
-
funding_status
|
|
1157
|
-
name
|
|
1158
|
-
]
|
|
1207
|
+
required: %w[
|
|
1208
|
+
funding_status
|
|
1209
|
+
name
|
|
1210
|
+
]
|
|
1211
|
+
}
|
|
1159
1212
|
},
|
|
1160
1213
|
project: {
|
|
1161
1214
|
'$id': '#/properties/dmp/properties/dmphub_modifications/project',
|
data/lib/uc3-dmp-id/updater.rb
CHANGED
|
@@ -13,7 +13,7 @@ module Uc3DmpId
|
|
|
13
13
|
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
|
14
14
|
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
15
15
|
# -------------------------------------------------------------------------
|
|
16
|
-
def update(provenance:, p_key:, json: {},
|
|
16
|
+
def update(provenance:, p_key:, json: {}, logger: nil)
|
|
17
17
|
raise UpdaterError, Helper::MSG_DMP_INVALID_DMP_ID unless p_key.is_a?(String) && !p_key.strip.empty?
|
|
18
18
|
|
|
19
19
|
mods = Helper.parse_json(json:).fetch('dmp', {})
|
|
@@ -40,13 +40,14 @@ module Uc3DmpId
|
|
|
40
40
|
version = Versioner.generate_version(client:, latest_version:, owner:,
|
|
41
41
|
updater:, logger:)
|
|
42
42
|
raise UpdaterError, Helper::MSG_DMP_UNABLE_TO_VERSION if version.nil?
|
|
43
|
+
# Bail if the system trying to make the update is not the creator of the DMP ID
|
|
44
|
+
raise UpdaterError, Helper::MSG_DMP_FORBIDDEN if owner != updater
|
|
43
45
|
|
|
44
46
|
# Remove the version info because we don't want to save it on the record
|
|
45
47
|
version.delete('dmphub_versions')
|
|
46
48
|
|
|
47
49
|
# Splice the assertions
|
|
48
|
-
version = _process_modifications(owner:, updater:, version:, mods:,
|
|
49
|
-
logger:)
|
|
50
|
+
version = _process_modifications(owner:, updater:, version:, mods:, logger:)
|
|
50
51
|
# Set the :modified timestamps
|
|
51
52
|
now = Time.now.utc
|
|
52
53
|
version['modified'] = now.iso8601
|
|
@@ -117,42 +118,23 @@ module Uc3DmpId
|
|
|
117
118
|
end
|
|
118
119
|
# rubocop:enable Metrics/AbcSize
|
|
119
120
|
|
|
120
|
-
# rubocop:disable Metrics/
|
|
121
|
-
def _process_modifications(owner:, updater:, version:, mods:,
|
|
121
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
122
|
+
def _process_modifications(owner:, updater:, version:, mods:, logger: nil)
|
|
122
123
|
return version unless mods.is_a?(Hash) && !updater.nil?
|
|
123
124
|
return mods unless version.is_a?(Hash) && !owner.nil?
|
|
124
125
|
|
|
125
|
-
updated = if owner == updater
|
|
126
|
-
# Splice together any assertions that may have been made while the user was editing the DMP ID
|
|
127
|
-
Asserter.splice(latest_version: version, modified_version: mods, logger:)
|
|
128
|
-
else
|
|
129
|
-
# Attach the incoming changes as an assertion to the DMP ID since the updater is NOT the owner
|
|
130
|
-
Asserter.add(updater:, latest_version: version, modified_version: mods, note:,
|
|
131
|
-
logger:)
|
|
132
|
-
end
|
|
133
|
-
|
|
134
|
-
_merge_versions(latest_version: version, mods: updated, logger:)
|
|
135
|
-
end
|
|
136
|
-
# rubocop:enable Metrics/ParameterLists
|
|
137
|
-
|
|
138
|
-
# We are replacing the latest version with the modifcations but want to retain the PK, SK and any dmphub_ prefixed
|
|
139
|
-
# entries in the metadata so that we do not lose creation timestamps, provenance ids, etc.
|
|
140
|
-
# rubocop:disable Metrics/AbcSize
|
|
141
|
-
def _merge_versions(latest_version:, mods:, logger: nil)
|
|
142
|
-
return mods unless latest_version.is_a?(Hash)
|
|
143
|
-
|
|
144
126
|
logger.debug(message: 'Modifications before merge.', details: mods) if logger.respond_to?(:debug)
|
|
145
|
-
keys_to_retain =
|
|
127
|
+
keys_to_retain = version.keys.select do |key|
|
|
146
128
|
(key.start_with?('dmphub_') && !%w[dmphub_modifications dmphub_versions].include?(key)) ||
|
|
147
129
|
key.start_with?('PK') || key.start_with?('SK')
|
|
148
130
|
end
|
|
149
131
|
keys_to_retain.each do |key|
|
|
150
|
-
mods[key] =
|
|
132
|
+
mods[key] = version[key]
|
|
151
133
|
end
|
|
152
134
|
logger.debug(message: 'Modifications after merge.', details: mods) if logger.respond_to?(:debug)
|
|
153
135
|
mods
|
|
154
136
|
end
|
|
155
|
-
# rubocop:enable Metrics/AbcSize
|
|
137
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
156
138
|
|
|
157
139
|
# Once the DMP has been updated, we need to update it's DOI metadata
|
|
158
140
|
# -------------------------------------------------------------------------
|
data/lib/uc3-dmp-id/version.rb
CHANGED
data/lib/uc3-dmp-id.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: uc3-dmp-id
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.7
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Brian Riley
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2023-10-
|
|
11
|
+
date: 2023-10-30 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: json
|
|
@@ -52,6 +52,20 @@ dependencies:
|
|
|
52
52
|
- - "~>"
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
54
|
version: '1.3'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: uc3-dmp-citation
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - "~>"
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '0.0'
|
|
62
|
+
type: :runtime
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - "~>"
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '0.0'
|
|
55
69
|
- !ruby/object:Gem::Dependency
|
|
56
70
|
name: uc3-dmp-dynamo
|
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -80,6 +94,20 @@ dependencies:
|
|
|
80
94
|
- - "~>"
|
|
81
95
|
- !ruby/object:Gem::Version
|
|
82
96
|
version: '0.0'
|
|
97
|
+
- !ruby/object:Gem::Dependency
|
|
98
|
+
name: uc3-dmp-external-api
|
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
|
100
|
+
requirements:
|
|
101
|
+
- - "~>"
|
|
102
|
+
- !ruby/object:Gem::Version
|
|
103
|
+
version: '0.0'
|
|
104
|
+
type: :runtime
|
|
105
|
+
prerelease: false
|
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
107
|
+
requirements:
|
|
108
|
+
- - "~>"
|
|
109
|
+
- !ruby/object:Gem::Version
|
|
110
|
+
version: '0.0'
|
|
83
111
|
description: Helpers for working with JSON that represents a DMP ID
|
|
84
112
|
email:
|
|
85
113
|
- brian.riley@ucop.edu
|
|
@@ -89,7 +117,7 @@ extra_rdoc_files: []
|
|
|
89
117
|
files:
|
|
90
118
|
- README.md
|
|
91
119
|
- lib/uc3-dmp-id.rb
|
|
92
|
-
- lib/uc3-dmp-id/
|
|
120
|
+
- lib/uc3-dmp-id/augmenter.rb
|
|
93
121
|
- lib/uc3-dmp-id/comparator.rb
|
|
94
122
|
- lib/uc3-dmp-id/creator.rb
|
|
95
123
|
- lib/uc3-dmp-id/deleter.rb
|
data/lib/uc3-dmp-id/asserter.rb
DELETED
|
@@ -1,216 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'time'
|
|
4
|
-
|
|
5
|
-
module Uc3DmpId
|
|
6
|
-
class AsserterError < StandardError; end
|
|
7
|
-
|
|
8
|
-
# Class that handles changes to a DMP ID's :dmphub_modifications section
|
|
9
|
-
class Asserter
|
|
10
|
-
DEFAULT_DESCRIPTOR = 'references'
|
|
11
|
-
DEFAULT_WORK_TYPE = 'other'
|
|
12
|
-
|
|
13
|
-
class << self
|
|
14
|
-
# Add assertions to a DMP ID - this is performed by non-provenance systems
|
|
15
|
-
# rubocop:disable Metrics/AbcSize, Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
|
|
16
|
-
def add(updater:, latest_version:, modified_version:, note: nil, logger: nil)
|
|
17
|
-
return latest_version unless latest_version.is_a?(Hash)
|
|
18
|
-
|
|
19
|
-
owner = latest_version['dmphub_provenance_id']&.gsub('PROVENANCE#', '')
|
|
20
|
-
# If the updater and provenance are the same just return the :dmp as-is
|
|
21
|
-
return latest_version if updater.nil? || !latest_version.is_a?(Hash) || !modified_version.is_a?(Hash) ||
|
|
22
|
-
updater&.gsub('PROVENANCE#', '') == owner
|
|
23
|
-
|
|
24
|
-
# contact = modified_version['contact']
|
|
25
|
-
# contributor = modified_version.fetch('contributor', [])
|
|
26
|
-
# project = modified_version.fetch('project', [])
|
|
27
|
-
funding = modified_version.fetch('project', []).first&.fetch('funding', [])
|
|
28
|
-
related_works = modified_version.fetch('dmproadmap_related_identifiers', [])
|
|
29
|
-
|
|
30
|
-
if related_works.any?
|
|
31
|
-
latest_version = _add_related_identifier(updater:, latest_version:,
|
|
32
|
-
identifiers: related_works, note:, logger:)
|
|
33
|
-
end
|
|
34
|
-
return latest_version unless !funding.nil? && funding.any?
|
|
35
|
-
|
|
36
|
-
_add_funding_mod(updater:, latest_version:, funding:,
|
|
37
|
-
note:, logger:)
|
|
38
|
-
end
|
|
39
|
-
# rubocop:enable Metrics/AbcSize, Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
|
|
40
|
-
|
|
41
|
-
# Splice together assertions made by the owner of the DMP ID so that any :dmphub_modifications made to
|
|
42
|
-
# the record while it was being updated are not lost
|
|
43
|
-
# rubocop:disable Metrics/AbcSize
|
|
44
|
-
def splice(latest_version:, modified_version:, logger: nil)
|
|
45
|
-
# Return the modified_version if the timestamps are the same OR neither version has :dmphub_modifications
|
|
46
|
-
return modified_version if latest_version['modified'] == modified_version['modified'] ||
|
|
47
|
-
(latest_version.fetch('dmphub_modifications', []).empty? &&
|
|
48
|
-
modified_version.fetch('dmphub_modifications', []).empty?)
|
|
49
|
-
|
|
50
|
-
# Clone any existing :dmphub_modifications on the current DMP ID so we can retain them
|
|
51
|
-
existing_assertions = Helper.deep_copy_dmp(obj: latest_version.fetch('dmphub_modifications', []))
|
|
52
|
-
incoming_assertions = Helper.deep_copy_dmp(obj: modified_version.fetch('dmphub_modifications', []))
|
|
53
|
-
if logger.respond_to?(:debug)
|
|
54
|
-
logger.debug(message: 'Existing dmphub_modifications',
|
|
55
|
-
details: existing_assertions)
|
|
56
|
-
end
|
|
57
|
-
if logger.respond_to?(:debug)
|
|
58
|
-
logger.debug(message: 'Incoming dmphub_modifications',
|
|
59
|
-
details: incoming_assertions)
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
# Keep any :dmphub_modifications and then add the incoming to the Array
|
|
63
|
-
modified_version['dmphub_modifications'] = existing_assertions
|
|
64
|
-
return modified_version unless incoming_assertions.any?
|
|
65
|
-
|
|
66
|
-
# Add any of the assertions still on the incoming record back to the latest record
|
|
67
|
-
incoming_assertions.each { |entry| modified_version['dmphub_modifications'] << entry }
|
|
68
|
-
modified_version
|
|
69
|
-
end
|
|
70
|
-
# rubocop:enable Metrics/AbcSize
|
|
71
|
-
|
|
72
|
-
private
|
|
73
|
-
|
|
74
|
-
# Verify that the DMP ID record does not already have the specified identifiers and then add them
|
|
75
|
-
# to the :latest_version in the :dmphub_modifications Array
|
|
76
|
-
#
|
|
77
|
-
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
|
78
|
-
# rubocop:disable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
|
|
79
|
-
def _add_related_identifier(updater:, latest_version:, identifiers:, note: '', logger: nil)
|
|
80
|
-
return latest_version unless updater.is_a?(String) && latest_version.is_a?(Hash) && identifiers.is_a?(Array)
|
|
81
|
-
|
|
82
|
-
latest_version['dmphub_modifications'] = [] if latest_version['dmphub_modifications'].nil?
|
|
83
|
-
known_mods = latest_version['dmphub_modifications'].map do |mod|
|
|
84
|
-
mod.fetch('dmproadmap_related_identifiers', [])
|
|
85
|
-
end
|
|
86
|
-
known_mods = known_mods.flatten.compact.map { |mod| mod['identifier'].downcase.strip }.compact.uniq
|
|
87
|
-
|
|
88
|
-
asserted = latest_version.fetch('dmproadmap_related_identifiers', [])
|
|
89
|
-
asserted = asserted.flatten.compact.map { |mod| mod['identifier'].downcase.strip }.compact.uniq
|
|
90
|
-
|
|
91
|
-
additions = []
|
|
92
|
-
identifiers.each do |related_identifier|
|
|
93
|
-
# Skip if there is no :type or :identifier value
|
|
94
|
-
if !related_identifier.is_a?(Hash) || related_identifier['type'].nil? || related_identifier['identifier'].nil?
|
|
95
|
-
next
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
id = related_identifier['identifier'].downcase.strip
|
|
99
|
-
# Skip if the :identifier is already listed in :dmphub_modifications or the
|
|
100
|
-
# :dmproadmap_related_identifiers Arrays
|
|
101
|
-
next if known_mods.include?(id) || asserted.include?(id)
|
|
102
|
-
|
|
103
|
-
related_identifier['work_type'] = DEFAULT_WORK_TYPE if related_identifier['work_type'].nil?
|
|
104
|
-
related_identifier['descriptor'] = DEFAULT_DESCRIPTOR if related_identifier['descriptor'].nil?
|
|
105
|
-
additions << related_identifier
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
latest_version['dmproadmap_related_identifiers'] = [] if latest_version['dmproadmap_related_identifiers'].nil?
|
|
109
|
-
assertion = _generate_assertion(updater:, note:,
|
|
110
|
-
mods: JSON.parse({ dmproadmap_related_identifiers: additions }.to_json))
|
|
111
|
-
if logger.respond_to?(:debug)
|
|
112
|
-
logger.debug(message: 'Adding change to :dmphub_modifications.',
|
|
113
|
-
details: assertion)
|
|
114
|
-
end
|
|
115
|
-
latest_version['dmphub_modifications'] << assertion
|
|
116
|
-
latest_version
|
|
117
|
-
end
|
|
118
|
-
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
|
119
|
-
# rubocop:enable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
|
|
120
|
-
|
|
121
|
-
# Verify that the DMP ID record does not already have the specified funding change and then add it
|
|
122
|
-
# to the :latest_version in the :dmphub_modifications Array
|
|
123
|
-
#
|
|
124
|
-
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
|
125
|
-
# rubocop:disable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
|
|
126
|
-
def _add_funding_mod(updater:, latest_version:, funding:, note: '', logger: nil)
|
|
127
|
-
return latest_version unless updater.is_a?(String) && latest_version.is_a?(Hash) && funding.is_a?(Array)
|
|
128
|
-
|
|
129
|
-
known_mods = latest_version['dmphub_modifications'].map do |mod|
|
|
130
|
-
next if mod.nil?
|
|
131
|
-
|
|
132
|
-
mod.fetch('funding', {}).fetch('grant_id', {})['identifier']&.downcase&.strip
|
|
133
|
-
end
|
|
134
|
-
known_mods = known_mods.flatten.compact.uniq
|
|
135
|
-
|
|
136
|
-
asserted = latest_version.fetch('project', [])&.map do |project|
|
|
137
|
-
next if project.nil?
|
|
138
|
-
|
|
139
|
-
project&.fetch('funding', [])&.first&.fetch('grant_id', {})&.[]('identifier')&.downcase&.strip
|
|
140
|
-
end
|
|
141
|
-
asserted = asserted.flatten.compact.uniq
|
|
142
|
-
|
|
143
|
-
fund = funding.reject { |entry| entry['grant_id'].nil? }.first
|
|
144
|
-
# Skip if there is no :grant_id
|
|
145
|
-
return latest_version if !fund.is_a?(Hash) || fund.fetch('grant_id', {})['identifier'].nil?
|
|
146
|
-
|
|
147
|
-
grant_id = fund.fetch('grant_id', {})['identifier'].downcase.strip
|
|
148
|
-
# Skip if the :grant_id is already listed as a :dmphub_modifications or project: :funding
|
|
149
|
-
return latest_version if known_mods.include?(grant_id) || asserted.include?(grant_id)
|
|
150
|
-
|
|
151
|
-
latest_version['dmphub_modifications'] = [] if latest_version['dmphub_modifications'].nil?
|
|
152
|
-
mod = JSON.parse({ funding: fund }.to_json)
|
|
153
|
-
mod['funding']['funding_status'] = 'granted'
|
|
154
|
-
assertion = _generate_assertion(updater:, mods: mod, note:)
|
|
155
|
-
if logger.respond_to?(:debug)
|
|
156
|
-
logger.debug(message: 'Adding change to :dmphub_modifications.',
|
|
157
|
-
details: assertion)
|
|
158
|
-
end
|
|
159
|
-
latest_version['dmphub_modifications'] << assertion
|
|
160
|
-
latest_version
|
|
161
|
-
end
|
|
162
|
-
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
|
163
|
-
# rubocop:enable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
|
|
164
|
-
|
|
165
|
-
# Generate an assertion entry. For example:
|
|
166
|
-
#
|
|
167
|
-
# {
|
|
168
|
-
# "id": "ABCD1234",
|
|
169
|
-
# "provenance": "dmphub",
|
|
170
|
-
# "timestamp": "2023-07-07T14:50:23+00:00",
|
|
171
|
-
# "note": "Data received from OpenAlex, matched by PI names and title keywords.",
|
|
172
|
-
# "confiedence": "Med",
|
|
173
|
-
# "dmproadmap_related_identifiers": {
|
|
174
|
-
# "work_type": "article",
|
|
175
|
-
# "descriptor": "is_cited_by",
|
|
176
|
-
# "type": "doi",
|
|
177
|
-
# "identifier": "https://dx.doi.org/99.9876/ZYX987.V6"
|
|
178
|
-
# }
|
|
179
|
-
# }
|
|
180
|
-
#
|
|
181
|
-
# OR:
|
|
182
|
-
#
|
|
183
|
-
# {
|
|
184
|
-
# "id": "ABCD1234",
|
|
185
|
-
# "provenance": "dmphub",
|
|
186
|
-
# "timestamp": "2023-07-07T14:50:23+00:00",
|
|
187
|
-
# "note": "Data received from the NIH API, matched by the opportunity number.",
|
|
188
|
-
# "confidence": "High",
|
|
189
|
-
# "funding": {
|
|
190
|
-
# "funding_status": "granted",
|
|
191
|
-
# "grant_id": {
|
|
192
|
-
# "identifier": "2019/22702-3",
|
|
193
|
-
# "type": "other"
|
|
194
|
-
# }
|
|
195
|
-
# }
|
|
196
|
-
# }
|
|
197
|
-
def _generate_assertion(updater:, mods:, note: '')
|
|
198
|
-
return nil if updater.nil? || !mods.is_a?(Hash)
|
|
199
|
-
|
|
200
|
-
assertion = {
|
|
201
|
-
id: SecureRandom.hex(4).upcase,
|
|
202
|
-
provenance: updater.gsub('PROVENANCE#', ''),
|
|
203
|
-
timestamp: Time.now.utc.iso8601,
|
|
204
|
-
status: 'pending',
|
|
205
|
-
note:
|
|
206
|
-
}
|
|
207
|
-
mods.each_pair { |key, val| assertion[key] = val }
|
|
208
|
-
JSON.parse(assertion.to_json)
|
|
209
|
-
end
|
|
210
|
-
end
|
|
211
|
-
|
|
212
|
-
def _score_related_work(latest_version:, work:); end
|
|
213
|
-
|
|
214
|
-
def _score_funding(latest_version:, funding:); end
|
|
215
|
-
end
|
|
216
|
-
end
|