Skip to content

Commit

Permalink
Merge pull request #92 from datacite/support-rightsidentifier
Browse files Browse the repository at this point in the history
Adding support for spdx rightsidentifier
  • Loading branch information
Martin Fenner authored Jun 3, 2020
2 parents a0672da + 8b65e7c commit 027d2da
Show file tree
Hide file tree
Showing 40 changed files with 6,243 additions and 50 deletions.
8 changes: 7 additions & 1 deletion lib/bolognese/datacite_utils.rb
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,13 @@ def insert_rights_list(xml)
r["rightsUri"] = normalize_id(rights)
end

attributes = { 'rightsURI' => r["rightsUri"], 'xml:lang' => r["lang"] }.compact
attributes = {
"rightsURI" => r["rightsUri"],
"rightsIdentifier" => r["rightsIdentifier"],
"rightsIdentifierScheme" => r["rightsIdentifierScheme"],
"schemeURI" => r["schemeUri"],
"xml:lang" => r["lang"]
}.compact

xml.rights(r["rights"], attributes)
end
Expand Down
1 change: 1 addition & 0 deletions lib/bolognese/metadata_utils.rb
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ def citeproc_hsh
"publisher" => publisher,
"title" => parse_attributes(titles, content: "title", first: true),
"URL" => url,
"copyright" => Array.wrap(rights_list).map { |l| l["rights"] }.first,
"version" => version_info
}.compact.symbolize_keys
end
Expand Down
3 changes: 2 additions & 1 deletion lib/bolognese/readers/bibtex_reader.rb
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ def read_bibtex(string: nil, **options)
"dateType" => "Issued" }]
end
publication_year = meta.try(:date).present? ? meta.date.to_s[0..3] : nil
rights_list = meta.try(:copyright).present? ? [hsh_to_spdx("rightsURI" => meta[:copyright])] : []

{ "id" => normalize_doi(doi),
"types" => types,
Expand All @@ -90,7 +91,7 @@ def read_bibtex(string: nil, **options)
"dates" => dates,
"publication_year" => publication_year,
"descriptions" => meta.try(:abstract).present? ? [{ "description" => meta.try(:abstract) && sanitize(meta.abstract.to_s).presence, "descriptionType" => "Abstract" }] : [],
"rights_list" => meta.try(:copyright).present? ? [{ "rightsUri" => meta.try(:copyright).to_s.presence }.compact] : [],
"rights_list" => rights_list,
"state" => state
}.merge(read_options)
end
Expand Down
2 changes: 1 addition & 1 deletion lib/bolognese/readers/citeproc_reader.rb
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def read_citeproc(string: nil, **options)
end
publication_year = get_date_from_date_parts(meta.fetch("issued", nil)).to_s[0..3]
rights_list = if meta.fetch("copyright", nil)
[{ "rightsUri" => normalize_url(meta.fetch("copyright")) }.compact]
[hsh_to_spdx("rightsURI" => meta.fetch("copyright"))]
end
related_identifiers = if meta.fetch("container-title", nil).present? && meta.fetch("ISSN", nil).present?
[{ "type" => "Periodical",
Expand Down
4 changes: 2 additions & 2 deletions lib/bolognese/readers/codemeta_reader.rb
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ def read_codemeta(string: nil, **options)
end

has_title = meta.fetch("title", nil)

titles = has_title.nil? ? [{ "title" => meta.fetch("name", nil) }] : [{ "title" => has_title }]
rights_list = meta.fetch("licenseId", nil).present? ? [hsh_to_spdx("rightsIdentifier" => meta.fetch("licenseId"))] : nil

{ "id" => id,
"types" => types,
Expand All @@ -80,7 +80,7 @@ def read_codemeta(string: nil, **options)
"dates" => dates,
"publication_year" => publication_year,
"descriptions" => meta.fetch("description", nil).present? ? [{ "description" => sanitize(meta.fetch("description")), "descriptionType" => "Abstract" }] : nil,
"rights_list" => [{ "rightsUri" => meta.fetch("license", nil) }.compact],
"rights_list" => rights_list,
"version_info" => meta.fetch("version", nil),
"subjects" => subjects,
"state" => state
Expand Down
2 changes: 1 addition & 1 deletion lib/bolognese/readers/crossref_reader.rb
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ def crossref_license(program_metadata)
access_indicator = Array.wrap(program_metadata).find { |m| m["name"] == "AccessIndicators" }
if access_indicator.present?
Array.wrap(access_indicator["license_ref"]).map do |license|
{ "rightsUri" => normalize_url(parse_attributes(license)) }
hsh_to_spdx("rightsURI" => parse_attributes(license))
end.uniq
else
[]
Expand Down
4 changes: 2 additions & 2 deletions lib/bolognese/readers/datacite_reader.rb
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,9 @@ def read_datacite(string: nil, **options)
if r.blank?
nil
elsif r.is_a?(String)
{ "rights" => r }
name_to_spdx(r)
elsif r.is_a?(Hash)
{ "rights" => r["__content__"], "rightsUri" => normalize_url(r["rightsURI"]), "lang" => r["lang"] }.compact
hsh_to_spdx(r)
end
end.compact

Expand Down
7 changes: 3 additions & 4 deletions lib/bolognese/readers/schema_org_reader.rb
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,9 @@ def read_schema_org(string: nil, **options)
Array.wrap(schema_org_is_supplement_to(meta)) +
Array.wrap(schema_org_is_supplemented_by(meta))

rights_list = [{
"rightsUri" => parse_attributes(meta.fetch("license", nil), content: "id", first: true),
"rights" => parse_attributes(meta.fetch("license", nil), content: "name", first: true)
}]
rights_list = Array.wrap(meta.fetch("license", nil)).compact.map do |rl|
hsh_to_spdx("__content__" => rl["name"], "rightsURI" => rl["id"])
end

funding_references = Array.wrap(meta.fetch("funder", nil)).compact.map do |fr|
if fr["@id"].present?
Expand Down
98 changes: 89 additions & 9 deletions lib/bolognese/utils.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,44 @@

module Bolognese
module Utils
LICENSE_NAMES = {
"http://creativecommons.org/publicdomain/zero/1.0/" => "Public Domain (CC0 1.0)",
"http://creativecommons.org/licenses/by/3.0/" => "Creative Commons Attribution 3.0 (CC-BY 3.0)",
"http://creativecommons.org/licenses/by/4.0/" => "Creative Commons Attribution 4.0 (CC-BY 4.0)",
"http://creativecommons.org/licenses/by-nc/4.0/" => "Creative Commons Attribution Noncommercial 4.0 (CC-BY-NC 4.0)",
"http://creativecommons.org/licenses/by-sa/4.0/" => "Creative Commons Attribution Share Alike 4.0 (CC-BY-SA 4.0)",
"http://creativecommons.org/licenses/by-nc-nd/4.0/" => "Creative Commons Attribution Noncommercial No Derivatives 4.0 (CC-BY-NC-ND 4.0)"
NORMALIZED_LICENSES = {
"https://creativecommons.org/licenses/by/1.0" => "https://creativecommons.org/licenses/by/1.0/legalcode",
"https://creativecommons.org/licenses/by/2.0" => "https://creativecommons.org/licenses/by/2.0/legalcode",
"https://creativecommons.org/licenses/by/2.5" => "https://creativecommons.org/licenses/by/2.5/legalcode",
"https://creativecommons.org/licenses/by/3.0" => "https://creativecommons.org/licenses/by/3.0/legalcode",
"https://creativecommons.org/licenses/by/4.0" => "https://creativecommons.org/licenses/by/4.0/legalcode",
"https://creativecommons.org/licenses/by-nc/1.0" => "https://creativecommons.org/licenses/by-nc/1.0/legalcode",
"https://creativecommons.org/licenses/by-nc/2.0" => "https://creativecommons.org/licenses/by-nc/2.0/legalcode",
"https://creativecommons.org/licenses/by-nc/2.5" => "https://creativecommons.org/licenses/by-nc/2.5/legalcode",
"https://creativecommons.org/licenses/by-nc/3.0" => "https://creativecommons.org/licenses/by-nc/3.0/legalcode",
"https://creativecommons.org/licenses/by-nc/4.0" => "https://creativecommons.org/licenses/by-nc/4.0/legalcode",
"https://creativecommons.org/licenses/by-nd-nc/1.0" => "https://creativecommons.org/licenses/by-nd-nc/1.0/legalcode",
"https://creativecommons.org/licenses/by-nd-nc/2.0" => "https://creativecommons.org/licenses/by-nd-nc/2.0/legalcode",
"https://creativecommons.org/licenses/by-nd-nc/2.5" => "https://creativecommons.org/licenses/by-nd-nc/2.5/legalcode",
"https://creativecommons.org/licenses/by-nd-nc/3.0" => "https://creativecommons.org/licenses/by-nd-nc/3.0/legalcode",
"https://creativecommons.org/licenses/by-nd-nc/4.0" => "https://creativecommons.org/licenses/by-nd-nc/4.0/legalcode",
"https://creativecommons.org/licenses/by-nc-sa/1.0" => "https://creativecommons.org/licenses/by-nc-sa/1.0/legalcode",
"https://creativecommons.org/licenses/by-nc-sa/2.0" => "https://creativecommons.org/licenses/by-nc-sa/2.0/legalcode",
"https://creativecommons.org/licenses/by-nc-sa/2.5" => "https://creativecommons.org/licenses/by-nc-sa/2.5/legalcode",
"https://creativecommons.org/licenses/by-nc-sa/3.0" => "https://creativecommons.org/licenses/by-nc-sa/3.0/legalcode",
"https://creativecommons.org/licenses/by-nc-sa/4.0" => "https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode",
"https://creativecommons.org/licenses/by-nd/1.0" => "https://creativecommons.org/licenses/by-nd/1.0/legalcode",
"https://creativecommons.org/licenses/by-nd/2.0" => "https://creativecommons.org/licenses/by-nd/2.0/legalcode",
"https://creativecommons.org/licenses/by-nd/2.5" => "https://creativecommons.org/licenses/by-nd/2.5/legalcode",
"https://creativecommons.org/licenses/by-nd/3.0" => "https://creativecommons.org/licenses/by-nd/3.0/legalcode",
"https://creativecommons.org/licenses/by-nd/4.0" => "https://creativecommons.org/licenses/by-nd/2.0/legalcode",
"https://creativecommons.org/licenses/by-sa/1.0" => "https://creativecommons.org/licenses/by-sa/1.0/legalcode",
"https://creativecommons.org/licenses/by-sa/2.0" => "https://creativecommons.org/licenses/by-sa/2.0/legalcode",
"https://creativecommons.org/licenses/by-sa/2.5" => "https://creativecommons.org/licenses/by-sa/2.5/legalcode",
"https://creativecommons.org/licenses/by-sa/3.0" => "https://creativecommons.org/licenses/by-sa/3.0/legalcode",
"https://creativecommons.org/licenses/by-sa/4.0" => "https://creativecommons.org/licenses/by-sa/4.0/legalcode",
"https://creativecommons.org/licenses/by-nc-nd/1.0" => "https://creativecommons.org/licenses/by-nc-nd/1.0/legalcode",
"https://creativecommons.org/licenses/by-nc-nd/2.0" => "https://creativecommons.org/licenses/by-nc-nd/2.0/legalcode",
"https://creativecommons.org/licenses/by-nc-nd/2.5" => "https://creativecommons.org/licenses/by-nc-nd/2.5/legalcode",
"https://creativecommons.org/licenses/by-nc-nd/3.0" => "https://creativecommons.org/licenses/by-nc-nd/3.0/legalcode",
"https://creativecommons.org/licenses/by-nc-nd/4.0" => "https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode",
"https://creativecommons.org/licenses/publicdomain" => "https://creativecommons.org/licenses/publicdomain/",
"https://creativecommons.org/publicdomain/zero/1.0" => "https://creativecommons.org/publicdomain/zero/1.0/legalcode",
}

DC_TO_SO_TRANSLATIONS = {
Expand Down Expand Up @@ -475,7 +506,7 @@ def normalize_id(id, options={})
nil
end

def normalize_url(id)
def normalize_url(id, options={})
return nil unless id.present?

# handle info URIs
Expand All @@ -485,13 +516,23 @@ def normalize_url(id)
uri = Addressable::URI.parse(id)

return nil unless uri && uri.host && %w(http https ftp).include?(uri.scheme)

# optionally turn into https URL
uri.scheme = "https" if options[:https]

# clean up URL
PostRank::URI.clean(id)
uri.path = PostRank::URI.clean(uri.path)

uri.to_s
rescue Addressable::URI::InvalidURIError
nil
end

def normalize_cc_url(id)
id = normalize_url(id, https: true)
NORMALIZED_LICENSES.fetch(id, id)
end

def normalize_orcid(orcid)
orcid = validate_orcid(orcid)
return nil unless orcid.present?
Expand Down Expand Up @@ -1056,6 +1097,45 @@ def jsonlint(json)
error_array
end

def name_to_spdx(name)
spdx = JSON.load(File.read(File.expand_path('../../../resources/spdx/licenses.json', __FILE__))).fetch("licenses")
license = spdx.find { |l| l["name"] == name || l["licenseId"] == name || l["seeAlso"].first == normalize_cc_url(name) }

if license
{
"rights" => license["name"],
"rightsUri" => license["seeAlso"].first,
"rightsIdentifier" => license["licenseId"],
"rightsIdentifierScheme" => "SPDX",
"schemeUri" => "https://spdx.org/licenses/" }.compact
else
{ "rights" => name }
end
end

def hsh_to_spdx(hsh)
spdx = JSON.load(File.read(File.expand_path('../../../resources/spdx/licenses.json', __FILE__))).fetch("licenses")
license = spdx.find { |l| l["licenseId"] == hsh["rightsIdentifier"] || l["seeAlso"].first == normalize_cc_url(hsh["rightsURI"]) || l["name"] == hsh["rights"] || l["seeAlso"].first == normalize_cc_url(hsh["rights"]) }

if license
{
"rights" => license["name"],
"rightsUri" => license["seeAlso"].first,
"rightsIdentifier" => license["licenseId"],
"rightsIdentifierScheme" => "SPDX",
"schemeUri" => "https://spdx.org/licenses/",
"lang" => hsh["lang"] }.compact
else
{
"rights" => hsh["__content__"],
"rightsUri" => hsh["rightsURI"],
"rightsIdentifier" => hsh["rightsIdentifier"],
"rightsIdentifierScheme" => hsh["rightsIdentifierScheme"],
"schemeUri" => hsh["schemeUri"],
"lang" => hsh["lang"] }.compact
end
end

def name_to_fos(name)
# first find subject in Fields of Science (OECD)
fos = JSON.load(File.read(File.expand_path('../../../resources/oecd/fos-mappings.json', __FILE__))).fetch("fosFields")
Expand Down
2 changes: 1 addition & 1 deletion lib/bolognese/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module Bolognese
VERSION = "1.6.3"
VERSION = "1.6.4"
end
3 changes: 2 additions & 1 deletion lib/bolognese/writers/bibtex_writer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ def bibtex
issue: container.to_h["issue"],
pages: pages,
publisher: publisher,
year: publication_year
year: publication_year,
copyright: Array.wrap(rights_list).map { |l| l["rights"] }.first,
}.compact
BibTeX::Entry.new(bib).to_s
end
Expand Down
3 changes: 2 additions & 1 deletion lib/bolognese/writers/codemeta_writer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ def codemeta
"tags" => subjects.present? ? Array.wrap(subjects).map { |k| parse_attributes(k, content: "subject", first: true) } : nil,
"datePublished" => get_date(dates, "Issued"),
"dateModified" => get_date(dates, "Updated"),
"publisher" => publisher
"publisher" => publisher,
"license" => Array.wrap(rights_list).map { |l| l["rightsUri"] }.compact.unwrap,
}.compact
JSON.pretty_generate hsh.presence
end
Expand Down
Loading

0 comments on commit 027d2da

Please sign in to comment.