bolognese 0.3 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +1 -1
  3. data/{LICENSE → LICENSE.md} +0 -0
  4. data/README.md +81 -1
  5. data/lib/bolognese.rb +1 -0
  6. data/lib/bolognese/author_utils.rb +1 -0
  7. data/lib/bolognese/cli.rb +6 -6
  8. data/lib/bolognese/crossref.rb +23 -19
  9. data/lib/bolognese/datacite.rb +21 -17
  10. data/lib/bolognese/datacite_utils.rb +14 -5
  11. data/lib/bolognese/doi_utils.rb +2 -3
  12. data/lib/bolognese/metadata.rb +11 -5
  13. data/lib/bolognese/orcid.rb +1 -1
  14. data/lib/bolognese/schema_org.rb +157 -0
  15. data/lib/bolognese/utils.rb +31 -1
  16. data/lib/bolognese/version.rb +1 -1
  17. data/spec/crossref_spec.rb +86 -26
  18. data/spec/datacite_spec.rb +43 -2
  19. data/spec/{doi_spec.rb → doi_utils_spec.rb} +2 -2
  20. data/spec/fixtures/vcr_cassettes/Bolognese_CLI/read/crossref/as_crossref.yml +8 -8
  21. data/spec/fixtures/vcr_cassettes/Bolognese_CLI/read/crossref/as_datacite.yml +12 -12
  22. data/spec/fixtures/vcr_cassettes/Bolognese_CLI/read/crossref/as_schema_org.yml +12 -12
  23. data/spec/fixtures/vcr_cassettes/Bolognese_CLI/read/datacite/as_datacite.yml +10 -10
  24. data/spec/fixtures/vcr_cassettes/Bolognese_CLI/read/datacite/as_schema_org.yml +16 -16
  25. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/doi_registration_agency/crossref.yml +931 -4
  26. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/doi_registration_agency/datacite.yml +931 -4
  27. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/doi_registration_agency/medra.yml +931 -4
  28. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/doi_registration_agency/not_found.yml +931 -4
  29. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/get_metadata/DOI_with_ORCID_ID.yml +506 -0
  30. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/get_metadata/DOI_with_SICI_DOI.yml +31 -94
  31. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/get_metadata/DOI_with_data_citation.yml +138 -14992
  32. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/get_metadata/date_in_future.yml +19 -2405
  33. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/get_metadata/journal_article.yml +107 -884
  34. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/get_metadata/not_found_error.yml +92 -2
  35. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/get_metadata/posted_content.yml +89 -5415
  36. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/get_metadata_as_datacite_xml/DOI_with_ORCID_ID.yml +506 -0
  37. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/get_metadata_as_datacite_xml/DOI_with_data_citation.yml +137 -671
  38. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/get_metadata_as_string/DOI_with_data_citation.yml +719 -0
  39. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/normalize_doi/SICI_doi.yml +930 -0
  40. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/normalize_doi/doi.yml +930 -0
  41. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/normalize_doi/doi_from_url_without_doi_proxy.yml +930 -0
  42. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/normalize_doi/doi_prefix_too_long.yml +930 -0
  43. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/normalize_doi/doi_prefix_with_string.yml +930 -0
  44. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/normalize_doi/doi_with_protocol.yml +930 -0
  45. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/normalize_doi/dx_doi_org_url.yml +930 -0
  46. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/normalize_doi/https_url.yml +930 -0
  47. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/normalize_doi/not_valid_doi_prefix.yml +930 -0
  48. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/normalize_ids/doi.yml +930 -0
  49. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/normalize_ids/url.yml +930 -0
  50. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/normalize_url/doi.yml +930 -0
  51. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/normalize_url/url.yml +930 -0
  52. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/parse_attribute/array.yml +930 -0
  53. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/parse_attribute/hash.yml +930 -0
  54. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/parse_attribute/nil.yml +930 -0
  55. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/parse_attribute/string.yml +930 -0
  56. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/parse_attributes/array.yml +930 -0
  57. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/parse_attributes/hash.yml +930 -0
  58. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/parse_attributes/nil.yml +930 -0
  59. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/parse_attributes/string.yml +930 -0
  60. data/spec/fixtures/vcr_cassettes/Bolognese_Datacite/get_metadata/BlogPosting.yml +248 -78
  61. data/spec/fixtures/vcr_cassettes/Bolognese_Datacite/get_metadata/Dataset.yml +1687 -105
  62. data/spec/fixtures/vcr_cassettes/Bolognese_Datacite/get_metadata/Date.yml +458 -0
  63. data/spec/fixtures/vcr_cassettes/Bolognese_Datacite/get_metadata_as_string/Dataset.yml +173 -0
  64. data/spec/fixtures/vcr_cassettes/Bolognese_Metadata/find_PID_provider/crossref.yml +4 -4
  65. data/spec/fixtures/vcr_cassettes/Bolognese_Metadata/find_PID_provider/crossref_doi_not_url.yml +4 -4
  66. data/spec/fixtures/vcr_cassettes/Bolognese_Metadata/find_PID_provider/datacite.yml +4 -4
  67. data/spec/fixtures/vcr_cassettes/Bolognese_Metadata/find_PID_provider/datacite_doi_http.yml +4 -4
  68. data/spec/fixtures/vcr_cassettes/Bolognese_Metadata/find_PID_provider/orcid.yml +2 -2
  69. data/spec/fixtures/vcr_cassettes/Bolognese_SchemaOrg/get_metadata/BlogPosting.yml +632 -0
  70. data/spec/fixtures/vcr_cassettes/Bolognese_SchemaOrg/get_metadata/not_found_error.yml +93 -0
  71. data/spec/metadata_spec.rb +11 -5
  72. data/spec/schema_org_spec.rb +31 -0
  73. data/spec/utils_spec.rb +87 -0
  74. metadata +35 -6
  75. data/lib/bolognese/pid_utils.rb +0 -23
  76. 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: d4728c17ca6677056bae7bb34fd334b2a018bbf5
4
- data.tar.gz: 69525494936ec8e6e4fe396f9b490b9fe19f1aa8
3
+ metadata.gz: 782e0858e5840b106b79b3c340a3d4bf572840b9
4
+ data.tar.gz: d85f7f7b269377b12a0ab25581001448ecd1dc92
5
5
  SHA512:
6
- metadata.gz: 85aa5235f96786e7f005ee588abb8d9f6bff889102d4b8d7a5b2ec91badcfd6b1f84cf2f0fdf33813768b396f98774a1ed4cd570089255628f105c2effc862d9
7
- data.tar.gz: 6db1eb5f1ab14ec751468e4192a0d09a05a12dbf79193a80c0ceb30e9deb41c641d76d9331eba1775422308baa94f531abbae8d92cb2b0908c8f9c84ebec06ca
6
+ metadata.gz: e59c29a2b61e97623e4ff6b1284e695c26cdb780bac6458006d9863e84b4e1728d47983222fc5d1ee86e18683a796ba717f167af03e2952aaa3d0fa8ce8be19c
7
+ data.tar.gz: 5f6eaeabccd3a86ff1534ad78bd34934539c3aa7351636983c299e9e953038068641aea0cfb5f18954be61b5db5e5c2de5e1ac9398ef2b6345fffc3b22ec1fbf
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- bolognese (0.3)
4
+ bolognese (0.4.1)
5
5
  activesupport (~> 4.2, >= 4.2.5)
6
6
  builder (~> 3.2, >= 3.2.2)
7
7
  dotenv (~> 2.1, >= 2.1.1)
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).
@@ -7,6 +7,7 @@ require "bolognese/version"
7
7
  require "bolognese/metadata"
8
8
  require "bolognese/crossref"
9
9
  require "bolognese/datacite"
10
+ require "bolognese/schema_org"
10
11
  require "bolognese/orcid"
11
12
  require "bolognese/cli"
12
13
  require "bolognese/string"
@@ -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"
@@ -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
@@ -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(doi)
44
- @id = normalize_doi(doi)
45
- end
36
+ def initialize(id: nil, string: nil)
37
+ id = normalize_doi(id) if id.present?
46
38
 
47
- def raw
48
- response = Maremma.get(@id, accept: "application/vnd.crossref.unixref+xml", host: true, raw: true)
49
- @raw ||= response.body.fetch("data", nil)
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
- doi_from_url(id)
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.dig("crossref").keys.last
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
@@ -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(doi)
31
- @id = normalize_doi(doi)
32
- end
23
+ def initialize(id: nil, string: nil)
24
+ id = normalize_doi(id) if id.present?
33
25
 
34
- def raw
35
- response = Maremma.get(id, accept: "application/vnd.datacite.datacite+xml", raw: true)
36
- @raw = response.body.fetch("data", nil)
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
- doi_from_url(id)
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" => contributor[:contributor_type]) do
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"], person["name"]].compact.join(", ")
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[:given_name]) if person["givenName"].present?
104
- xml.send(:'familyName', person[:family_name]) if person["familyName"].present?
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
 
@@ -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].upcase
21
+ uri.path[1..-1].downcase
22
22
  elsif url.is_a?(String) && url.starts_with?("doi:")
23
- url[4..-1].upcase
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
@@ -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 'pid_utils'
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::PidUtils
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
- get_doi_ra(id).fetch("id", nil) || "orcid"
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
@@ -1,6 +1,6 @@
1
1
  module Bolognese
2
2
  class Orcid < Metadata
3
- include Bolognese::PidUtils
3
+ include Bolognese::Utils
4
4
  # def get_orcid_metadata(orcid, options = {})
5
5
  # return {} if orcid.blank?
6
6
 
@@ -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