bolognese 0.3 → 0.4.1
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/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
|