bolognese 0.3 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/{LICENSE → LICENSE.md} +0 -0
- data/README.md +81 -1
- data/lib/bolognese.rb +1 -0
- data/lib/bolognese/author_utils.rb +1 -0
- data/lib/bolognese/cli.rb +6 -6
- data/lib/bolognese/crossref.rb +23 -19
- data/lib/bolognese/datacite.rb +21 -17
- data/lib/bolognese/datacite_utils.rb +14 -5
- data/lib/bolognese/doi_utils.rb +2 -3
- data/lib/bolognese/metadata.rb +11 -5
- data/lib/bolognese/orcid.rb +1 -1
- data/lib/bolognese/schema_org.rb +157 -0
- data/lib/bolognese/utils.rb +31 -1
- data/lib/bolognese/version.rb +1 -1
- data/spec/crossref_spec.rb +86 -26
- data/spec/datacite_spec.rb +43 -2
- data/spec/{doi_spec.rb → doi_utils_spec.rb} +2 -2
- data/spec/fixtures/vcr_cassettes/Bolognese_CLI/read/crossref/as_crossref.yml +8 -8
- data/spec/fixtures/vcr_cassettes/Bolognese_CLI/read/crossref/as_datacite.yml +12 -12
- data/spec/fixtures/vcr_cassettes/Bolognese_CLI/read/crossref/as_schema_org.yml +12 -12
- data/spec/fixtures/vcr_cassettes/Bolognese_CLI/read/datacite/as_datacite.yml +10 -10
- data/spec/fixtures/vcr_cassettes/Bolognese_CLI/read/datacite/as_schema_org.yml +16 -16
- data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/doi_registration_agency/crossref.yml +931 -4
- data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/doi_registration_agency/datacite.yml +931 -4
- data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/doi_registration_agency/medra.yml +931 -4
- data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/doi_registration_agency/not_found.yml +931 -4
- data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/get_metadata/DOI_with_ORCID_ID.yml +506 -0
- data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/get_metadata/DOI_with_SICI_DOI.yml +31 -94
- data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/get_metadata/DOI_with_data_citation.yml +138 -14992
- data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/get_metadata/date_in_future.yml +19 -2405
- data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/get_metadata/journal_article.yml +107 -884
- data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/get_metadata/not_found_error.yml +92 -2
- data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/get_metadata/posted_content.yml +89 -5415
- data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/get_metadata_as_datacite_xml/DOI_with_ORCID_ID.yml +506 -0
- data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/get_metadata_as_datacite_xml/DOI_with_data_citation.yml +137 -671
- data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/get_metadata_as_string/DOI_with_data_citation.yml +719 -0
- data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/normalize_doi/SICI_doi.yml +930 -0
- data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/normalize_doi/doi.yml +930 -0
- data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/normalize_doi/doi_from_url_without_doi_proxy.yml +930 -0
- data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/normalize_doi/doi_prefix_too_long.yml +930 -0
- data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/normalize_doi/doi_prefix_with_string.yml +930 -0
- data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/normalize_doi/doi_with_protocol.yml +930 -0
- data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/normalize_doi/dx_doi_org_url.yml +930 -0
- data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/normalize_doi/https_url.yml +930 -0
- data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/normalize_doi/not_valid_doi_prefix.yml +930 -0
- data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/normalize_ids/doi.yml +930 -0
- data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/normalize_ids/url.yml +930 -0
- data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/normalize_url/doi.yml +930 -0
- data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/normalize_url/url.yml +930 -0
- data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/parse_attribute/array.yml +930 -0
- data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/parse_attribute/hash.yml +930 -0
- data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/parse_attribute/nil.yml +930 -0
- data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/parse_attribute/string.yml +930 -0
- data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/parse_attributes/array.yml +930 -0
- data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/parse_attributes/hash.yml +930 -0
- data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/parse_attributes/nil.yml +930 -0
- data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/parse_attributes/string.yml +930 -0
- data/spec/fixtures/vcr_cassettes/Bolognese_Datacite/get_metadata/BlogPosting.yml +248 -78
- data/spec/fixtures/vcr_cassettes/Bolognese_Datacite/get_metadata/Dataset.yml +1687 -105
- data/spec/fixtures/vcr_cassettes/Bolognese_Datacite/get_metadata/Date.yml +458 -0
- data/spec/fixtures/vcr_cassettes/Bolognese_Datacite/get_metadata_as_string/Dataset.yml +173 -0
- data/spec/fixtures/vcr_cassettes/Bolognese_Metadata/find_PID_provider/crossref.yml +4 -4
- data/spec/fixtures/vcr_cassettes/Bolognese_Metadata/find_PID_provider/crossref_doi_not_url.yml +4 -4
- data/spec/fixtures/vcr_cassettes/Bolognese_Metadata/find_PID_provider/datacite.yml +4 -4
- data/spec/fixtures/vcr_cassettes/Bolognese_Metadata/find_PID_provider/datacite_doi_http.yml +4 -4
- data/spec/fixtures/vcr_cassettes/Bolognese_Metadata/find_PID_provider/orcid.yml +2 -2
- data/spec/fixtures/vcr_cassettes/Bolognese_SchemaOrg/get_metadata/BlogPosting.yml +632 -0
- data/spec/fixtures/vcr_cassettes/Bolognese_SchemaOrg/get_metadata/not_found_error.yml +93 -0
- data/spec/metadata_spec.rb +11 -5
- data/spec/schema_org_spec.rb +31 -0
- data/spec/utils_spec.rb +87 -0
- metadata +35 -6
- data/lib/bolognese/pid_utils.rb +0 -23
- data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/get_metadata/DOI_test.yml +0 -843
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 782e0858e5840b106b79b3c340a3d4bf572840b9
|
4
|
+
data.tar.gz: d85f7f7b269377b12a0ab25581001448ecd1dc92
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e59c29a2b61e97623e4ff6b1284e695c26cdb780bac6458006d9863e84b4e1728d47983222fc5d1ee86e18683a796ba717f167af03e2952aaa3d0fa8ce8be19c
|
7
|
+
data.tar.gz: 5f6eaeabccd3a86ff1534ad78bd34934539c3aa7351636983c299e9e953038068641aea0cfb5f18954be61b5db5e5c2de5e1ac9398ef2b6345fffc3b22ec1fbf
|
data/Gemfile.lock
CHANGED
data/{LICENSE → LICENSE.md}
RENAMED
File without changes
|
data/README.md
CHANGED
@@ -1,3 +1,83 @@
|
|
1
1
|
# bolognese
|
2
2
|
|
3
|
-
Command-line utility for conversion of DOI metadata.
|
3
|
+
Command-line utility for conversion of DOI metadata from and to [schema.org](https://schema.org) in JSON-LD.
|
4
|
+
|
5
|
+
## Features
|
6
|
+
|
7
|
+
* convert [Crossref XML](https://support.crossref.org/hc/en-us/articles/214936283-UNIXREF-query-output-format) to schema.org/JSON-LD
|
8
|
+
* convert [DataCite XML](http://schema.datacite.org/) to schema.org/JSON-LD
|
9
|
+
* fetch schema.org/JSON-LD from a URL
|
10
|
+
* convert schema.org/JSON-LD to [DataCite XML](http://schema.datacite.org/)
|
11
|
+
* convert Crossref XML to [DataCite XML](http://schema.datacite.org/)
|
12
|
+
|
13
|
+
Conversion to Crossref XML is not yet supported.
|
14
|
+
|
15
|
+
## Installation
|
16
|
+
|
17
|
+
The usual way with Bundler: add the following to your `Gemfile` to install the
|
18
|
+
current version of the gem:
|
19
|
+
|
20
|
+
```ruby
|
21
|
+
gem 'bolognese'
|
22
|
+
```
|
23
|
+
|
24
|
+
Then run `bundle install` to install into your environment.
|
25
|
+
|
26
|
+
You can also install the gem system-wide in the usual way:
|
27
|
+
|
28
|
+
```bash
|
29
|
+
gem install bolognese
|
30
|
+
```
|
31
|
+
|
32
|
+
## Commands
|
33
|
+
|
34
|
+
The bolognese commands understand URLs and DOIs as arguments. The `--as` command
|
35
|
+
line flag sets the format, either `crossref`, `datacite`, or `schema_org` (default).
|
36
|
+
|
37
|
+
## Examples
|
38
|
+
|
39
|
+
Convert Crossref XML to schema.org/JSON-LD:
|
40
|
+
```
|
41
|
+
bolognese read https://doi.org/10.7554/elife.01567
|
42
|
+
```
|
43
|
+
|
44
|
+
Read Crossref XML:
|
45
|
+
```
|
46
|
+
bolognese read https://doi.org/10.7554/elife.01567 --as crossref
|
47
|
+
```
|
48
|
+
|
49
|
+
Convert Crossref XML to DataCite XML:
|
50
|
+
```
|
51
|
+
bolognese read https://doi.org/10.7554/elife.01567 --as datacite
|
52
|
+
```
|
53
|
+
|
54
|
+
Convert DataCite XML to schema.org/JSON-LD:
|
55
|
+
```
|
56
|
+
bolognese read 10.5061/DRYAD.8515
|
57
|
+
```
|
58
|
+
|
59
|
+
Read DataCite XML:
|
60
|
+
```
|
61
|
+
bolognese read 10.5061/DRYAD.8515 --as datacite
|
62
|
+
```
|
63
|
+
|
64
|
+
## Development
|
65
|
+
|
66
|
+
We use rspec for unit testing:
|
67
|
+
|
68
|
+
```
|
69
|
+
bundle exec rspec
|
70
|
+
```
|
71
|
+
|
72
|
+
Follow along via [Github Issues](https://github.com/datacite/bolognese/issues).
|
73
|
+
|
74
|
+
### Note on Patches/Pull Requests
|
75
|
+
|
76
|
+
* Fork the project
|
77
|
+
* Write tests for your new feature or a test that reproduces a bug
|
78
|
+
* Implement your feature or make a bug fix
|
79
|
+
* Do not mess with Rakefile, version or history
|
80
|
+
* Commit, push and make a pull request. Bonus points for topical branches.
|
81
|
+
|
82
|
+
## License
|
83
|
+
**bolognese** is released under the [MIT License](https://github.com/datacite/bolognese/blob/master/LICENSE.md).
|
data/lib/bolognese.rb
CHANGED
@@ -48,6 +48,7 @@ module Bolognese
|
|
48
48
|
Array(authors).map { |author| get_one_author(author, options) }
|
49
49
|
end
|
50
50
|
|
51
|
+
# pase nameIdentifier from DataCite
|
51
52
|
def get_name_identifier(author)
|
52
53
|
name_identifier = author.dig("nameIdentifier", "text")
|
53
54
|
name_identifier_scheme = author.dig("nameIdentifier", "nameIdentifierScheme") || "ORCID"
|
data/lib/bolognese/cli.rb
CHANGED
@@ -19,19 +19,19 @@ module Bolognese
|
|
19
19
|
desc "read pid", "read metadata for PID"
|
20
20
|
method_option :as, default: "schema_org"
|
21
21
|
def read(pid)
|
22
|
-
provider = Metadata.new(pid).provider
|
22
|
+
provider = Metadata.new(id: pid).provider
|
23
23
|
|
24
24
|
case
|
25
25
|
when provider == "crossref" && options[:as] == "crossref"
|
26
|
-
puts Crossref.new(pid).raw
|
26
|
+
puts Crossref.new(id: pid).raw
|
27
27
|
when provider == "crossref" && options[:as] == "datacite"
|
28
|
-
puts Crossref.new(pid).as_datacite
|
28
|
+
puts Crossref.new(id: pid).as_datacite
|
29
29
|
when provider == "crossref"
|
30
|
-
puts Crossref.new(pid).as_schema_org
|
30
|
+
puts Crossref.new(id: pid).as_schema_org
|
31
31
|
when provider == "datacite" && options[:as] == "datacite"
|
32
|
-
puts Datacite.new(pid).raw
|
32
|
+
puts Datacite.new(id: pid).raw
|
33
33
|
when "datacite"
|
34
|
-
puts Datacite.new(pid).as_schema_org
|
34
|
+
puts Datacite.new(id: pid).as_schema_org
|
35
35
|
else
|
36
36
|
puts "not implemented"
|
37
37
|
end
|
data/lib/bolognese/crossref.rb
CHANGED
@@ -1,12 +1,5 @@
|
|
1
|
-
require_relative 'doi_utils'
|
2
|
-
require_relative 'datacite_utils'
|
3
|
-
require_relative 'utils'
|
4
|
-
|
5
1
|
module Bolognese
|
6
2
|
class Crossref < Metadata
|
7
|
-
include Bolognese::DoiUtils
|
8
|
-
include Bolognese::Utils
|
9
|
-
include Bolognese::DataciteUtils
|
10
3
|
|
11
4
|
# CrossRef types from https://api.crossref.org/types
|
12
5
|
CR_TO_SO_TRANSLATIONS = {
|
@@ -38,15 +31,17 @@ module Bolognese
|
|
38
31
|
"PostedContent" => nil
|
39
32
|
}
|
40
33
|
|
41
|
-
attr_reader = :id, :metadata, :schema_org
|
34
|
+
attr_reader = :id, :raw, :metadata, :schema_org
|
42
35
|
|
43
|
-
def initialize(
|
44
|
-
|
45
|
-
end
|
36
|
+
def initialize(id: nil, string: nil)
|
37
|
+
id = normalize_doi(id) if id.present?
|
46
38
|
|
47
|
-
|
48
|
-
|
49
|
-
|
39
|
+
if string.present?
|
40
|
+
@raw = string
|
41
|
+
elsif id.present?
|
42
|
+
response = Maremma.get(id, accept: "application/vnd.crossref.unixref+xml", host: true, raw: true)
|
43
|
+
@raw = response.body.fetch("data", nil)
|
44
|
+
end
|
50
45
|
end
|
51
46
|
|
52
47
|
def metadata
|
@@ -58,7 +53,11 @@ module Bolognese
|
|
58
53
|
end
|
59
54
|
|
60
55
|
def doi
|
61
|
-
|
56
|
+
bibliographic_metadata.dig("doi_data", "doi")
|
57
|
+
end
|
58
|
+
|
59
|
+
def id
|
60
|
+
normalize_doi(doi)
|
62
61
|
end
|
63
62
|
|
64
63
|
def journal_metadata
|
@@ -69,7 +68,7 @@ module Bolognese
|
|
69
68
|
if metadata.dig("crossref", "journal", "journal_article").present?
|
70
69
|
metadata.dig("crossref", "journal", "journal_article")
|
71
70
|
else
|
72
|
-
k = metadata.
|
71
|
+
k = metadata.fetch("crossref", {}).keys.last
|
73
72
|
metadata.dig("crossref", k).presence || {}
|
74
73
|
end
|
75
74
|
end
|
@@ -104,7 +103,12 @@ module Bolognese
|
|
104
103
|
end
|
105
104
|
|
106
105
|
def description
|
107
|
-
bibliographic_metadata.fetch("abstract", {}).values.first
|
106
|
+
des = bibliographic_metadata.fetch("abstract", {}).values.first
|
107
|
+
if des.is_a?(Hash)
|
108
|
+
des.to_xml
|
109
|
+
elsif des.is_a?(String)
|
110
|
+
des
|
111
|
+
end
|
108
112
|
end
|
109
113
|
|
110
114
|
def license
|
@@ -124,7 +128,7 @@ module Bolognese
|
|
124
128
|
person = bibliographic_metadata.dig("contributors", "person_name")
|
125
129
|
Array(person).select { |a| a["contributor_role"] == "author" }.map do |a|
|
126
130
|
{ "@type" => "Person",
|
127
|
-
"@id" => a["ORCID"],
|
131
|
+
"@id" => parse_attribute(a["ORCID"]),
|
128
132
|
"givenName" => a["given_name"],
|
129
133
|
"familyName" => a["surname"] }.compact
|
130
134
|
end
|
@@ -134,7 +138,7 @@ module Bolognese
|
|
134
138
|
person = bibliographic_metadata.dig("contributors", "person_name")
|
135
139
|
Array(person).select { |a| a["contributor_role"] == "editor" }.map do |a|
|
136
140
|
{ "@type" => "Person",
|
137
|
-
"@id" => a["ORCID"],
|
141
|
+
"@id" => parse_attribute(a["ORCID"]),
|
138
142
|
"givenName" => a["given_name"],
|
139
143
|
"familyName" => a["surname"] }.compact
|
140
144
|
end.presence
|
data/lib/bolognese/datacite.rb
CHANGED
@@ -1,12 +1,5 @@
|
|
1
|
-
require_relative 'doi_utils'
|
2
|
-
require_relative 'datacite_utils'
|
3
|
-
require_relative 'utils'
|
4
|
-
|
5
1
|
module Bolognese
|
6
2
|
class Datacite < Metadata
|
7
|
-
include Bolognese::DoiUtils
|
8
|
-
include Bolognese::DataciteUtils
|
9
|
-
include Bolognese::Utils
|
10
3
|
|
11
4
|
DC_TO_SO_TRANSLATIONS = {
|
12
5
|
"Audiovisual" => "VideoObject",
|
@@ -25,15 +18,17 @@ module Bolognese
|
|
25
18
|
"Other" => "CreativeWork"
|
26
19
|
}
|
27
20
|
|
28
|
-
attr_reader = :id, :metadata, :schema_org
|
21
|
+
attr_reader = :id, :raw, :metadata, :schema_org
|
29
22
|
|
30
|
-
def initialize(
|
31
|
-
|
32
|
-
end
|
23
|
+
def initialize(id: nil, string: nil)
|
24
|
+
id = normalize_doi(id) if id.present?
|
33
25
|
|
34
|
-
|
35
|
-
|
36
|
-
|
26
|
+
if string.present?
|
27
|
+
@raw = string
|
28
|
+
elsif id.present?
|
29
|
+
response = Maremma.get(id, accept: "application/vnd.datacite.datacite+xml", raw: true)
|
30
|
+
@raw = response.body.fetch("data", nil)
|
31
|
+
end
|
37
32
|
end
|
38
33
|
|
39
34
|
def metadata
|
@@ -45,7 +40,11 @@ module Bolognese
|
|
45
40
|
end
|
46
41
|
|
47
42
|
def doi
|
48
|
-
|
43
|
+
metadata.fetch("identifier", {}).fetch("text", nil)
|
44
|
+
end
|
45
|
+
|
46
|
+
def id
|
47
|
+
normalize_doi(doi)
|
49
48
|
end
|
50
49
|
|
51
50
|
def type
|
@@ -67,7 +66,12 @@ module Bolognese
|
|
67
66
|
end
|
68
67
|
|
69
68
|
def description
|
70
|
-
metadata.dig("descriptions", "description", "text")
|
69
|
+
des = metadata.dig("descriptions", "description", "text")
|
70
|
+
if des.is_a?(Hash)
|
71
|
+
des.to_xml
|
72
|
+
elsif des.is_a?(String)
|
73
|
+
des.strip
|
74
|
+
end
|
71
75
|
end
|
72
76
|
|
73
77
|
def license
|
@@ -89,7 +93,7 @@ module Bolognese
|
|
89
93
|
end
|
90
94
|
|
91
95
|
def dates
|
92
|
-
Array(metadata.dig("dates", "date"))
|
96
|
+
Array.wrap(metadata.dig("dates", "date"))
|
93
97
|
end
|
94
98
|
|
95
99
|
def date_created
|
@@ -22,6 +22,7 @@ module Bolognese
|
|
22
22
|
|
23
23
|
LICENSE_NAMES = {
|
24
24
|
"http://creativecommons.org/publicdomain/zero/1.0/" => "Public Domain (CC0 1.0)",
|
25
|
+
"http://creativecommons.org/licenses/by/3.0/" => "Creative Commons Attribution 3.0 (CC-BY 3.0)",
|
25
26
|
"https://creativecommons.org/licenses/by/4.0/" => "Creative Commons Attribution 4.0 (CC-BY 4.0)",
|
26
27
|
"https://creativecommons.org/licenses/by-nc/4.0/" => "Creative Commons Attribution Noncommercial 4.0 (CC-BY-NC 4.0)",
|
27
28
|
"https://creativecommons.org/licenses/by-sa/4.0/" => "Creative Commons Attribution Share Alike 4.0 (CC-BY-SA 4.0)",
|
@@ -88,7 +89,7 @@ module Bolognese
|
|
88
89
|
|
89
90
|
xml.contributors do
|
90
91
|
Array(editor).each do |contributor|
|
91
|
-
xml.contributor("contributorType" =>
|
92
|
+
xml.contributor("contributorType" => "Editor") do
|
92
93
|
insert_person(xml, contributor, "contributor")
|
93
94
|
end
|
94
95
|
end
|
@@ -96,12 +97,12 @@ module Bolognese
|
|
96
97
|
end
|
97
98
|
|
98
99
|
def insert_person(xml, person, type)
|
99
|
-
person_name = [person["familyName"], person["givenName"]
|
100
|
+
person_name = [person["familyName"], person["givenName"]].compact.join(", ").presence || person["name"]
|
100
101
|
|
101
102
|
xml.send(:'creatorName', person_name) if type == "creator"
|
102
103
|
xml.send(:'contributorName', person_name) if type == "contributor"
|
103
|
-
xml.send(:'givenName', person[
|
104
|
-
xml.send(:'familyName', person[
|
104
|
+
xml.send(:'givenName', person["givenName"]) if person["givenName"].present?
|
105
|
+
xml.send(:'familyName', person["familyName"]) if person["familyName"].present?
|
105
106
|
xml.nameIdentifier(person["@id"], 'schemeURI' => 'http://orcid.org/', 'nameIdentifierScheme' => 'ORCID') if person["@id"].present?
|
106
107
|
end
|
107
108
|
|
@@ -165,6 +166,14 @@ module Bolognese
|
|
165
166
|
xml.version(version)
|
166
167
|
end
|
167
168
|
|
169
|
+
def is_part_of
|
170
|
+
related_identifiers("IsPartOf").first
|
171
|
+
end
|
172
|
+
|
173
|
+
def related_identifiers
|
174
|
+
Array.wrap(is_part_of) + Array(has_part) + Array(citation)
|
175
|
+
end
|
176
|
+
|
168
177
|
def insert_related_identifiers(xml)
|
169
178
|
return xml unless related_identifiers.present?
|
170
179
|
|
@@ -187,7 +196,7 @@ module Bolognese
|
|
187
196
|
return xml unless description.present?
|
188
197
|
|
189
198
|
xml.descriptions do
|
190
|
-
xml.description(description)
|
199
|
+
xml.description(description, 'descriptionType' => "Abstract")
|
191
200
|
end
|
192
201
|
end
|
193
202
|
|
data/lib/bolognese/doi_utils.rb
CHANGED
@@ -18,9 +18,9 @@ module Bolognese
|
|
18
18
|
def doi_from_url(url)
|
19
19
|
if /(http|https):\/\/(dx\.)?doi\.org\/(\w+)/.match(url)
|
20
20
|
uri = Addressable::URI.parse(url)
|
21
|
-
uri.path[1..-1].
|
21
|
+
uri.path[1..-1].downcase
|
22
22
|
elsif url.is_a?(String) && url.starts_with?("doi:")
|
23
|
-
url[4..-1].
|
23
|
+
url[4..-1].downcase
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
@@ -43,6 +43,5 @@ module Bolognese
|
|
43
43
|
{ "errors" => response.body.fetch("errors", nil) || response.body.fetch("data", nil) }
|
44
44
|
end
|
45
45
|
end
|
46
|
-
|
47
46
|
end
|
48
47
|
end
|
data/lib/bolognese/metadata.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require_relative 'doi_utils'
|
2
2
|
require_relative 'author_utils'
|
3
3
|
require_relative 'date_utils'
|
4
|
-
require_relative '
|
4
|
+
require_relative 'datacite_utils'
|
5
5
|
require_relative 'utils'
|
6
6
|
|
7
7
|
module Bolognese
|
@@ -9,12 +9,12 @@ module Bolognese
|
|
9
9
|
include Bolognese::DoiUtils
|
10
10
|
include Bolognese::AuthorUtils
|
11
11
|
include Bolognese::DateUtils
|
12
|
-
include Bolognese::
|
12
|
+
include Bolognese::DataciteUtils
|
13
13
|
include Bolognese::Utils
|
14
14
|
|
15
|
-
attr_reader :id, :provider
|
15
|
+
attr_reader :id, :raw, :provider
|
16
16
|
|
17
|
-
def initialize(id)
|
17
|
+
def initialize(id: nil)
|
18
18
|
@id = normalize_id(id)
|
19
19
|
@provider = find_provider(@id)
|
20
20
|
end
|
@@ -24,7 +24,13 @@ module Bolognese
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def find_provider(id)
|
27
|
-
|
27
|
+
if /(http|https):\/\/(dx\.)?doi\.org\/(\w+)/.match(id)
|
28
|
+
get_doi_ra(id).fetch("id", nil)
|
29
|
+
elsif /\A(?:http:\/\/orcid\.org\/)?(\d{4}-\d{4}-\d{4}-\d{3}[0-9X]+)\z/.match(id)
|
30
|
+
"orcid"
|
31
|
+
else
|
32
|
+
"schema_org"
|
33
|
+
end
|
28
34
|
end
|
29
35
|
end
|
30
36
|
end
|
data/lib/bolognese/orcid.rb
CHANGED
@@ -0,0 +1,157 @@
|
|
1
|
+
module Bolognese
|
2
|
+
class SchemaOrg < Metadata
|
3
|
+
|
4
|
+
DC_TO_SO_TRANSLATIONS = {
|
5
|
+
"Audiovisual" => "VideoObject",
|
6
|
+
"Collection" => "Collection",
|
7
|
+
"Dataset" => "Dataset",
|
8
|
+
"Event" => "Event",
|
9
|
+
"Image" => "ImageObject",
|
10
|
+
"InteractiveResource" => nil,
|
11
|
+
"Model" => nil,
|
12
|
+
"PhysicalObject" => nil,
|
13
|
+
"Service" => "Service",
|
14
|
+
"Software" => "SoftwareSourceCode",
|
15
|
+
"Sound" => "AudioObject",
|
16
|
+
"Text" => "ScholarlyArticle",
|
17
|
+
"Workflow" => nil,
|
18
|
+
"Other" => "CreativeWork"
|
19
|
+
}
|
20
|
+
|
21
|
+
attr_reader = :id, :raw, :metadata, :schema_org
|
22
|
+
|
23
|
+
def initialize(id: nil, string: nil)
|
24
|
+
id = normalize_url(id) if id.present?
|
25
|
+
|
26
|
+
if string.present?
|
27
|
+
@raw = string
|
28
|
+
elsif id.present?
|
29
|
+
response = Maremma.get(id)
|
30
|
+
@raw = response.body.fetch("data", nil)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def metadata
|
35
|
+
@metadata ||= begin
|
36
|
+
if raw.present?
|
37
|
+
doc = Nokogiri::XML(raw)
|
38
|
+
tag = doc.at_xpath('//script[@type="application/ld+json"]')
|
39
|
+
Maremma.from_json(tag)
|
40
|
+
else
|
41
|
+
{}
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def exists?
|
47
|
+
metadata.present?
|
48
|
+
end
|
49
|
+
|
50
|
+
def doi
|
51
|
+
doi_from_url(id)
|
52
|
+
end
|
53
|
+
|
54
|
+
def id
|
55
|
+
normalize_url(metadata.fetch("@id", nil))
|
56
|
+
end
|
57
|
+
|
58
|
+
def url
|
59
|
+
normalize_url(metadata.fetch("url", nil))
|
60
|
+
end
|
61
|
+
|
62
|
+
def type
|
63
|
+
metadata.fetch("@type", nil)
|
64
|
+
end
|
65
|
+
|
66
|
+
def additional_type
|
67
|
+
metadata.fetch("additionalType", nil)
|
68
|
+
end
|
69
|
+
|
70
|
+
def name
|
71
|
+
metadata.fetch("name", nil)
|
72
|
+
end
|
73
|
+
|
74
|
+
def alternate_name
|
75
|
+
metadata.fetch("alternateName", nil)
|
76
|
+
end
|
77
|
+
|
78
|
+
def author
|
79
|
+
Array(metadata.fetch("author", nil)).map { |a| a.except("name") }
|
80
|
+
end
|
81
|
+
|
82
|
+
def description
|
83
|
+
metadata.fetch("description", nil)
|
84
|
+
end
|
85
|
+
|
86
|
+
def license
|
87
|
+
metadata.fetch("license", nil)
|
88
|
+
end
|
89
|
+
|
90
|
+
def version
|
91
|
+
metadata.fetch("version", nil)
|
92
|
+
end
|
93
|
+
|
94
|
+
def keywords
|
95
|
+
metadata.fetch("keywords", nil)
|
96
|
+
end
|
97
|
+
|
98
|
+
def date_created
|
99
|
+
metadata.fetch("dateCreated", nil)
|
100
|
+
end
|
101
|
+
|
102
|
+
def date_published
|
103
|
+
metadata.fetch("datePublished", nil)
|
104
|
+
end
|
105
|
+
|
106
|
+
def date_modified
|
107
|
+
metadata.fetch("dateModified", nil)
|
108
|
+
end
|
109
|
+
|
110
|
+
def related_identifiers(relation_type)
|
111
|
+
normalize_ids(metadata.fetch(relation_type, nil))
|
112
|
+
end
|
113
|
+
|
114
|
+
def is_part_of
|
115
|
+
related_identifiers("isPartOf").first
|
116
|
+
end
|
117
|
+
|
118
|
+
def has_part
|
119
|
+
related_identifiers("hasPart")
|
120
|
+
end
|
121
|
+
|
122
|
+
def citation
|
123
|
+
related_identifiers("citation")
|
124
|
+
end
|
125
|
+
|
126
|
+
def publisher
|
127
|
+
metadata.fetch("publisher", nil)
|
128
|
+
end
|
129
|
+
|
130
|
+
def provider
|
131
|
+
metadata.fetch("provider", nil)
|
132
|
+
end
|
133
|
+
|
134
|
+
def as_schema_org
|
135
|
+
{ "@context" => "http://schema.org",
|
136
|
+
"@type" => type,
|
137
|
+
"@id" => id,
|
138
|
+
"url" => url,
|
139
|
+
"name" => name,
|
140
|
+
"alternateName" => alternate_name,
|
141
|
+
"author" => author,
|
142
|
+
"description" => description,
|
143
|
+
"license" => license,
|
144
|
+
"version" => version,
|
145
|
+
"keywords" => keywords,
|
146
|
+
"dateCreated" => date_created,
|
147
|
+
"datePublished" => date_published,
|
148
|
+
"dateModified" => date_modified,
|
149
|
+
"isPartOf" => is_part_of,
|
150
|
+
"hasPart" => has_part,
|
151
|
+
"citation" => citation,
|
152
|
+
"publisher" => publisher,
|
153
|
+
"provider" => provider
|
154
|
+
}.compact
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|