Skip to content

Commit

Permalink
Breaking out PDCMetadata classes into thier own files (#325)
Browse files Browse the repository at this point in the history
Also removing rubocop violations

Co-authored-by: Hector Correa <hector@hectorcorrea.com>
  • Loading branch information
carolyncole and hectorcorrea committed Aug 23, 2022
1 parent a1b3f1a commit 71b9398
Show file tree
Hide file tree
Showing 6 changed files with 170 additions and 135 deletions.
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)
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

0 comments on commit 71b9398

Please sign in to comment.