Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Breaking out PDCMetadata classes into thier own files #325

Merged
merged 2 commits into from
Aug 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions app/models/pdc_metadata/affiliation.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# frozen_string_literal: true
# Class for storing an affiliation in our local representation
module PDCMetadata
# value: "datacite"
# identifier: "https://ror.org/04aj4c181"
# scheme: "ROR"
# scheme_uri: "https://ror.org/"
class Affiliation
attr_accessor :value, :identifier, :scheme, :scheme_uri
def initialize(value: nil, identifier: nil, scheme: nil, scheme_uri: nil)
@value = value
@identifier = identifier
@scheme = scheme
@scheme_uri = scheme_uri
end
end
end
65 changes: 65 additions & 0 deletions app/models/pdc_metadata/creator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# frozen_string_literal: true
# Class for storing a creator in our local representation
module PDCMetadata
# value: "Miller, Elizabeth"
# name_type: "Personal"
# given_name: "Elizabeth"
# family_name: "Miller"
class Creator
attr_accessor :value, :name_type, :given_name, :family_name, :identifier, :affiliations, :sequence

class << self
def from_hash(creator)
given_name = creator["given_name"]
family_name = creator["family_name"]
orcid = creator.dig("identifier", "scheme") == "ORCID" ? creator.dig("identifier", "value") : nil
sequence = (creator["sequence"] || "").to_i
PDCMetadata::Creator.new_person(given_name, family_name, orcid, sequence)
end
end

# rubocop:disable Metrics/ParameterLists
def initialize(value: nil, name_type: nil, given_name: nil, family_name: nil, identifier: nil, sequence: 0)
@value = value
@name_type = name_type
@given_name = given_name
@family_name = family_name
@identifier = identifier
@affiliations = []
@sequence = sequence
end
# rubocop:enable Metrics/ParameterLists

def orcid_url
identifier&.orcid_url
end

def orcid
identifier&.orcid
end

def self.new_person(given_name, family_name, orcid_id = nil, sequence = 0)
full_name = "#{family_name}, #{given_name}"
creator = Creator.new(value: full_name, name_type: "Personal", given_name: given_name, family_name: family_name, sequence: sequence)
if orcid_id.present?
creator.identifier = NameIdentifier.new_orcid(orcid_id.strip)
end
creator
end

def to_xml(builder)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

love this!

if name_type == "Personal"
builder.creator("nameType" => "Personal") do
builder.creatorName value
builder.givenName given_name
builder.familyName family_name
identifier&.to_xml(builder)
end
else
builder.creator("nameType" => "Organization") do
builder.creatorName value
end
end
end
end
end
42 changes: 42 additions & 0 deletions app/models/pdc_metadata/name_identifier.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# frozen_string_literal: true
# Class for storing a named identifier for the creator in our local representation. This identifier can be a person or organization.
# **Please Note:**
# The class name NameIdentifier is being utilized becuase it matches with the DataCite Schema: https://support.datacite.org/docs/datacite-metadata-schema-v44-mandatory-properties#24-nameidentifier
# It also matches with the DaCite xml mapping gem that we are utilizing: https://github.com/CDLUC3/datacite-mapping/blob/master/lib/datacite/mapping/name_identifier.rb
module PDCMetadata
# value: "0000-0001-5000-0007"
# scheme: "ORCID"
# scheme_uri: "https://orcid.org/""
class NameIdentifier
attr_accessor :value, :scheme, :scheme_uri
def initialize(value: nil, scheme: nil, scheme_uri: nil)
@value = value
@scheme = scheme
@scheme_uri = scheme_uri
end

def orcid_url
return nil unless scheme == "ORCID"
"#{scheme_uri}/#{value}"
end

def orcid
return nil unless scheme == "ORCID"
value
end

# Convenience method since this is the most common (only?) identifier that we are currently supporting
def self.new_orcid(value)
NameIdentifier.new(value: value, scheme: "ORCID", scheme_uri: "https://orcid.org")
end

def to_xml(builder)
builder.nameIdentifier(
"schemeURI" => scheme_uri,
"nameIdentifierScheme" => scheme
) do
builder.text value
end
end
end
end
159 changes: 24 additions & 135 deletions app/models/pdc_metadata/resource.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ module PDCMetadata
# Represents a PUL Datacite resource
# https://support.datacite.org/docs/datacite-metadata-schema-v44-properties-overview
#
# rubocop:disable Metrics/ClassLength
class Resource
attr_accessor :creators, :titles, :publisher, :publication_year, :resource_type,
:description, :doi, :ark
Expand Down Expand Up @@ -68,25 +67,7 @@ def to_xml
end
xml.creators do
@creators.each do |creator|
if creator.name_type == "Personal"
xml.creator("nameType" => "Personal") do
xml.creatorName creator.value
xml.givenName creator.given_name
xml.familyName creator.family_name
unless creator.name_identifier.nil?
xml.nameIdentifier(
"schemeURI" => creator.name_identifier.scheme_uri,
"nameIdentifierScheme" => creator.name_identifier.scheme
) do
xml.text creator.name_identifier.value
end
end
end
else
xml.creator("nameType" => "Organization") do
xml.creatorName creator.value
end
end
creator.to_xml(xml)
end
end
xml.publisher do
Expand All @@ -103,129 +84,37 @@ def to_xml
# rubocop:enable Metrics/BlockLength
# rubocop:enable Metrics/AbcSize

# Creates a PDCMetadata::Resource from a JSON string
# rubocop:disable Metrics/MethodLength
# rubocop:disable Metrics/AbcSize
def self.new_from_json(json_string)
resource = PDCMetadata::Resource.new
hash = json_string.blank? ? {} : JSON.parse(json_string)

resource.doi = hash["doi"]
resource.ark = hash["ark"]
resource.description = hash["description"]
class << self
# Creates a PDCMetadata::Resource from a JSON string
def new_from_json(json_string)
resource = PDCMetadata::Resource.new
hash = json_string.blank? ? {} : JSON.parse(json_string)

hash["titles"]&.each do |title|
resource.titles << PDCMetadata::Title.new(title: title["title"], title_type: title["title_type"])
end

hash["creators"]&.each do |creator|
given_name = creator["given_name"]
family_name = creator["family_name"]
orcid = creator.dig("name_identifier", "scheme") == "ORCID" ? creator.dig("name_identifier", "value") : nil
sequence = (creator["sequence"] || "").to_i
resource.creators << PDCMetadata::Creator.new_person(given_name, family_name, orcid, sequence)
end
resource.creators.sort_by!(&:sequence)

resource.publisher = hash["publisher"]
resource.publication_year = hash["publication_year"]

resource
end
# rubocop:enable Metrics/AbcSize
# rubocop:enable Metrics/MethodLength
end
# rubocop:enable Metrics/ClassLength

# value: "Miller, Elizabeth"
# name_type: "Personal"
# given_name: "Elizabeth"
# family_name: "Miller"
class Creator
attr_accessor :value, :name_type, :given_name, :family_name, :name_identifier, :affiliations, :sequence

# rubocop:disable Metrics/ParameterLists
def initialize(value: nil, name_type: nil, given_name: nil, family_name: nil, name_identifier: nil, sequence: 0)
@value = value
@name_type = name_type
@given_name = given_name
@family_name = family_name
@name_identifier = name_identifier
@affiliations = []
@sequence = sequence
end
# rubocop:enable Metrics/ParameterLists
resource.doi = hash["doi"]
resource.ark = hash["ark"]
resource.description = hash["description"]

def orcid_url
name_identifier&.orcid_url
end
hash["titles"]&.each do |title|
resource.titles << PDCMetadata::Title.new(title: title["title"], title_type: title["title_type"])
end

def orcid
name_identifier&.orcid
end
creators_from_json(resource, hash["creators"])
resource.publisher = hash["publisher"]
resource.publication_year = hash["publication_year"]

def self.new_person(given_name, family_name, orcid_id = nil, sequence = 0)
full_name = "#{family_name}, #{given_name}"
creator = Creator.new(value: full_name, name_type: "Personal", given_name: given_name, family_name: family_name, sequence: sequence)
if orcid_id.present?
creator.name_identifier = NameIdentifier.new_orcid(orcid_id.strip)
resource
end
creator
end
end

# value: "0000-0001-5000-0007"
# scheme: "ORCID"
# scheme_uri: "https://orcid.org/""
class NameIdentifier
attr_accessor :value, :scheme, :scheme_uri
def initialize(value: nil, scheme: nil, scheme_uri: nil)
@value = value
@scheme = scheme
@scheme_uri = scheme_uri
end
private

def orcid_url
return nil unless scheme == "ORCID"
"#{scheme_uri}/#{value}"
end
def creators_from_json(resource, creators)
return if creators.blank?

def orcid
return nil unless scheme == "ORCID"
value
end

# Convenience method since this is the most common (only?) identifier that we are currently supporting
def self.new_orcid(value)
NameIdentifier.new(value: value, scheme: "ORCID", scheme_uri: "https://orcid.org")
end
end

# value: "datacite"
# identifier: "https://ror.org/04aj4c181"
# scheme: "ROR"
# scheme_uri: "https://ror.org/"
class Affiliation
attr_accessor :value, :identifier, :scheme, :scheme_uri
def initialize(value: nil, identifier: nil, scheme: nil, scheme_uri: nil)
@value = value
@identifier = identifier
@scheme = scheme
@scheme_uri = scheme_uri
end
end

# value: "100 años de soledad"
# title_type: "TranslatedTitle"
class Title
attr_accessor :title, :title_type
def initialize(title:, title_type: nil)
@title = title
@title_type = title_type
end

def main?
@title_type.blank?
creators.each do |creator|
resource.creators << Creator.from_hash(creator)
end
resource.creators.sort_by!(&:sequence)
end
end
end
end
17 changes: 17 additions & 0 deletions app/models/pdc_metadata/title.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# frozen_string_literal: true
# Class for storing a title in our local representation
module PDCMetadata
# value: "100 años de soledad"
# title_type: "TranslatedTitle"
class Title
attr_accessor :title, :title_type
def initialize(title:, title_type: nil)
@title = title
@title_type = title_type
end

def main?
@title_type.blank?
end
end
end
5 changes: 5 additions & 0 deletions spec/models/pdc_metadata/resource_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,9 @@
no_orcid = PDCMetadata::Creator.new_person("Elizabeth", "Miller")
expect(no_orcid.orcid).to be nil
end

it "creates the expected json" do
work = FactoryBot.create(:shakespeare_and_company_work)
expect(work.metadata).to eq(work.resource.to_json)
end
end