Skip to content
Open
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
2 changes: 1 addition & 1 deletion .rubocop.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Disable line-length check; it's too easy for the cure to be worse than the disease
Metrics/LineLength:
Layout/LineLength:
Enabled: False

# Disable parameter-length check; this is determined by the number of XML attributes defined in the DataCite schema
Expand Down
2 changes: 1 addition & 1 deletion .ruby-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.0.4
3.3.7
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ based on [xml-mapping](http://multi-io.github.io/xml-mapping/) and
[xml-mapping_extensions](https://github.com/dmolesUC3/xml-mapping_extensions).
Full API documentation on [RubyDoc.info](http://www.rubydoc.info/github/CDLUC3/datacite-mapping/master/frames).

Supports [Datacite 4.3](https://schema.labs.datacite.org/meta/kernel-4.3/); backward-compatible with
Supports [Datacite 4.7](https://datacite-metadata-schema.readthedocs.io/en/4.7); backward-compatible with
[Datacite 3.1](https://schema.labs.datacite.org/meta/kernel-3/).

Note that although this gem maintains compatibility with multiple
Expand Down
3 changes: 3 additions & 0 deletions lib/datacite/mapping/contributor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ class ContributorType < TypesafeEnum::Base
# @!parse SUPERVISOR = Supervisor
new :SUPERVISOR, 'Supervisor'

# @!parse TRANSLATOR = Translator
new :TRANSLATOR, 'Translator'

# @!parse WORK_PACKAGE_LEADER = WorkPackageLeader
new :WORK_PACKAGE_LEADER, 'WorkPackageLeader'

Expand Down
3 changes: 3 additions & 0 deletions lib/datacite/mapping/date.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ class DateType < TypesafeEnum::Base
# @!parse COLLECTED = Collected
new :COLLECTED, 'Collected'

# @!parse COVERAGE = Coverage
new :COVERAGE, 'Coverage'

# @!parse CREATED = Created
new :CREATED, 'Created'

Expand Down
8 changes: 4 additions & 4 deletions lib/datacite/mapping/geo_location_polygon.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,15 @@ def to_s
# # @return [Array<GeoLocationPoint>] an array of points defining the polygon area.
array_node :points, 'polygonPoint',
default_value: [],
marshaller: (proc { |xml, value| marshal_point(xml, value) }),
unmarshaller: (proc { |xml| unmarshal_point(xml) })
marshaller: proc { |xml, value| marshal_point(xml, value) },
unmarshaller: proc { |xml| unmarshal_point(xml) }

# # @!attribute [rw] in_polygon_point
# # @return [InPolygonPoint] a point within the target polygon
object_node :in_polygon_point, 'inPolygonPoint',
default_value: nil,
marshaller: (proc { |xml, value| marshal_point(xml, value) }),
unmarshaller: (proc { |xml| unmarshal_point(xml) })
marshaller: proc { |xml, value| marshal_point(xml, value) },
unmarshaller: proc { |xml| unmarshal_point(xml) }

use_mapping :datacite_3

Expand Down
6 changes: 3 additions & 3 deletions lib/datacite/mapping/identifier.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def value=(new_value)
# @param new_value [String]
# the identifier type (always 'DOI')
def identifier_type=(new_value)
raise ArgumentError, "Identifier type '#{new_value}' must be 'DOI'" unless DOI == new_value
raise ArgumentError, "Identifier type '#{new_value}' must be 'DOI'" unless new_value == DOI

@identifier_type = new_value
end
Expand Down Expand Up @@ -68,12 +68,12 @@ def self.from_doi(doi_string)
class IdentifierNode < XML::Mapping::ObjectNode
include EmptyNodeUtils
def xml_to_obj(_obj, xml)
return super if (element = has_element?(xml)) && not_empty(element)
super if (element = element?(xml)) && not_empty(element)
end

private

def has_element?(xml) # rubocop:disable Naming/PredicateName
def element?(xml)
@path.first(xml)
rescue XML::XXPathError
false
Expand Down
38 changes: 37 additions & 1 deletion lib/datacite/mapping/related_identifier.rb
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,24 @@ class RelationType < TypesafeEnum::Base
# @!parse REQUIRES = Requires
new :REQUIRES, 'Requires'

# @!parse IS_PUBLISHED_IN = IsPublishedIn
new :IS_PUBLISHED_IN, 'IsPublishedIn'

# @!parse IS_COLLECTED_BY = IsCollectedBy
new :IS_COLLECTED_BY, 'IsCollectedBy'

# @!parse COLLECTS = Collects
new :COLLECTS, 'Collects'

# @!parse HAS_TRANSLATION = HasTranslation
new :HAS_TRANSLATION, 'HasTranslation'

# @!parse IS_TRANSLATION_OF = IsTranslationOf
new :IS_TRANSLATION_OF, 'IsTranslationOf'

# @!parse OTHER = Other
new :OTHER, 'Other'

end

# Controlled list of related identifier types.
Expand All @@ -120,6 +138,9 @@ class RelatedIdentifierType < TypesafeEnum::Base
# @!parse BIBCODE = bibcode
new :BIBCODE, 'bibcode'

# @!parse CSTR = CSTR
new :CSTR, 'CSTR'

# @!parse DOI = DOI
new :DOI, 'DOI'

Expand Down Expand Up @@ -153,6 +174,15 @@ class RelatedIdentifierType < TypesafeEnum::Base
# @!parse PURL = PURL
new :PURL, 'PURL'

# @!parse RAID = RAiD
new :RAID, 'RAiD'

# @!parse RRID = RRID
new :RRID, 'RRID'

# @!parse SWHID = SWHID
new :SWHID, 'SWHID'

# @!parse UPC = UPC
new :UPC, 'UPC'

Expand Down Expand Up @@ -198,13 +228,15 @@ class RelatedIdentifier

# Initializes a new {RelatedIdentifier}.
# @param relation_type [RelationType] the relationship of the {Resource} to the related resource. Cannot be nil.
# @param relation_type_information [String] additional information about the selected [RelationType], if appropriate.
# @param value [String] the identifier value. Cannot be nil.
# @param identifier_type [RelatedIdentifierType] the type of the related identifier. Cannot be nil.
# @param related_metadata_scheme [String, nil] the name of the metadata scheme. Used only with `HasMetadata`/`IsMetadataFor`. Optional.
# @param scheme_uri [URI, nil] the URI of the metadata scheme. Used only with `HasMetadata`/`IsMetadataFor`. Optional.
# @param scheme_type [String, nil] the type of the metadata scheme. Used only with `HasMetadata`/`IsMetadataFor`. Optional.
def initialize(relation_type:, value:, identifier_type:, related_metadata_scheme: nil, scheme_uri: nil, scheme_type: nil)
def initialize(relation_type:, value:, identifier_type:, relation_type_information: nil, related_metadata_scheme: nil, scheme_uri: nil, scheme_type: nil)
self.relation_type = relation_type
self.relation_type_information = relation_type_information
self.value = value
self.identifier_type = identifier_type
self.related_metadata_scheme = related_metadata_scheme
Expand Down Expand Up @@ -236,6 +268,10 @@ def relation_type=(value)
# @return [RelationType] the relationship of the {Resource} to the related resource. Cannot be nil.
typesafe_enum_node :relation_type, '@relationType', class: RelationType

# @!attribute [rw] relation_type_information
# @return [String, nil] Additional information about the selected relationType, if appropriate. Recommended for use with the relationType Other.
text_node :relation_type_information, '@rrelationTypeInformation', default_value: nil

# @!attribute [rw] value
# @return [String] the identifier value. Cannot be nil.
text_node :value, 'text()'
Expand Down
226 changes: 226 additions & 0 deletions lib/datacite/mapping/related_item.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
# frozen_string_literal: true

require 'xml/mapping_extensions'
require 'datacite/mapping/creator'
require 'datacite/mapping/title'
require 'datacite/mapping/contributor'
require 'datacite/mapping/publisher'

module Datacite
module Mapping

class NumberType < TypesafeEnum::Base
# @!parse ARTICLE = Article
new :ARTICLE, 'Article'

# @!parse CHAPTER = Chapter
new :CHAPTER, 'Chapter'

# @!parse REPORT = Report
new :REPORT, 'Report'

# @!parse OTHER = Other
new :OTHER, 'Other'
end

# @param number_type [identifierType] the type of the related identifier. Cannot be nil.
class Number
include XML::Mapping

def initialize(value:, number_type:)
self.value = value
self.number_type = number_type
end

root_element_name 'number'

# @!attribute [rw] number_type
# @return [NumberType] the type of the related item’s number, e.g., report number or article number.
typesafe_enum_node :number_type, '@numberType', class: NumberType

# @!attribute [rw] value
# @return [String] the identifier value. Cannot be nil.
text_node :value, 'text()'
end

# rubocop:disable Metrics/AbcSize, Metrics/MethodLength

# @param identifier_type [identifierType] the type of the related identifier. Cannot be nil.
# @param related_metadata_scheme [String, nil] the name of the metadata scheme. Used only with `HasMetadata`/`IsMetadataFor`. Optional.
# @param scheme_uri [URI, nil] the URI of the metadata scheme. Used only with `HasMetadata`/`IsMetadataFor`. Optional.
# @param scheme_type [String, nil] the type of the metadata scheme. Used only with `HasMetadata`/`IsMetadataFor`. Optional.
class RelatedItemIdentifier
include XML::Mapping

def initialize(value:, identifier_type:, related_metadata_scheme: nil, scheme_uri: nil, scheme_type: nil)
self.value = value
self.identifier_type = identifier_type
self.related_metadata_scheme = related_metadata_scheme
self.scheme_uri = scheme_uri
self.scheme_type = scheme_type
end

def value=(value)
raise ArgumentError, 'Value cannot be empty or nil' unless value && !value.empty?

@value = value
end

def identifier_type=(value)
raise ArgumentError, 'Identifier type cannot be empty or nil' unless value

@identifier_type = value
end

root_element_name 'relatedItemIdentifier'

# @!attribute [rw] value
# @return [String] the identifier value. Cannot be nil.
text_node :value, 'text()'

# @!attribute [rw] identifier_type
# @return [RelatedIdentifierType] the type of the related identifier. Cannot be nil.
typesafe_enum_node :identifier_type, '@relatedItemIdentifierType', class: RelatedIdentifierType

# @!attribute [rw] related_metadata_scheme
# @return [String, nil] the name of the metadata scheme. Used only with `HasMetadata`/`IsMetadataFor`. Optional.
text_node :related_metadata_scheme, '@relatedMetadataScheme', default_value: nil

# @!attribute [rw] scheme_uri
# @return [URI, nil] the URI of the metadata scheme. Used only with `HasMetadata`/`IsMetadataFor`. Optional.
uri_node :scheme_uri, '@schemeURI', default_value: nil

# @!attribute [rw] scheme_type
# @return [String, nil] the type of the metadata scheme. Used only with `HasMetadata`/`IsMetadataFor`. Optional.
text_node :scheme_type, '@schemeType', default_value: nil
end

# Information about a resource related to the one being registered.
class RelatedItem
include XML::Mapping

attr_writer :related_item_identifier, :creators, :number

# Initializes a new {RelatedItem}.
# @param relation_type [RelationType] the relationship of the {Resource} to the related resource. Cannot be nil.
# @param relation_type_information [String] additional information about the selected [RelationType], if appropriate.
# @param value [String] the identifier value. Cannot be nil.
# @param identifier_type [RelatedItemType] the type of the related identifier. Cannot be nil.
def initialize(relation_type:, related_item_type:, titles:, relation_type_information: nil, related_item_identifier: nil, creators: [], publication_year: nil, volume: nil, issue: nil, number: nil, first_page: nil, last_page: nil, edition: nil, publisher: nil, contributors: [])
self.relation_type = relation_type
self.related_item_type = related_item_type
self.relation_type_information = relation_type_information
self.related_item_identifier = related_item_identifier
self.creators = creators
self.titles = titles
self.publication_year = publication_year
self.volume = volume
self.issue = issue
self.number = number
self.first_page = first_page
self.last_page = last_page
self.publisher = publisher
self.edition = edition
self.contributors = contributors
end

def relation_type=(value)
raise ArgumentError, 'Relation type cannot be nil' unless value

@relation_type = value
end

def related_item_type=(value)
raise ArgumentError, 'Identifier type cannot be empty or nil' unless value

@related_item_type = value
end

def titles=(value)
raise ArgumentError, 'RelatedItem must have at least one title' unless value && !value.empty?

@titles = value
end

def publication_year=(value)
raise ArgumentError, 'Resource must have a four-digit publication year' if value.present? && !value&.to_i&.between?(1000, 9999)

@publication_year = value.to_i
end

# publisher can be entered as a string or a Publisher object, but it will be stored
# as a Publisher object
def publisher=(value)
@publisher = if value.is_a?(Publisher)
value
else
Publisher.new(value: value)
end
end

def contributors=(value)
@contributors = value || []
end

root_element_name 'relatedItem'

# @!attribute [rw] related_item_type
# @return [ResourceTypeGeneral] the general resource type
typesafe_enum_node :related_item_type, '@relatedItemType', class: ResourceTypeGeneral, default_value: nil

# @!attribute [rw] relation_type
# @return [RelationType] the relationship of the {Resource} to the related resource. Cannot be nil.
typesafe_enum_node :relation_type, '@relationType', class: RelationType

# @!attribute [rw] relation_type_information
# @return [String, nil] Additional information about the selected relationType, if appropriate. Recommended for use with the relationType Other.
text_node :relation_type_information, '@rrelationTypeInformation', default_value: nil

# @!attribute [rw] related_item_identifier
# @return [RelatedItemIdentifier, nil] the related item identifier
object_node :related_item_identifier, 'relatedItemIdentifier', class: RelatedItemIdentifier, default_value: nil

# @!attribute [rw] creators
# @return [Array<Creator>] the main researchers involved working on the data, or the authors of the publication in priority order.
array_node :creators, 'creators', 'creator', class: Creator

# @!attribute [rw] titles
# @return [Array<Title>] the names or titles by which a resource is known.
array_node :titles, 'titles', 'title', class: Title

# @!attribute [rw] volume
# @return [String] Volume of the related item.
text_node :volume, 'volume', default_value: nil

# @!attribute [rw] issue
# @return [String] Issue number or name of the related item.
text_node :issue, 'issue', default_value: nil

# @!attribute [rw] related_item_identifier
# @return [RelatedItemIdentifier, nil] the related item identifier
object_node :number, 'number', class: Number, default_value: nil

# @!attribute [rw] firstPage
# @return [String] First page of the resource within the related item, e.g., of the chapter, article, or conference paper in proceedings.
text_node :first_page, 'firstPage', default_value: nil

# @!attribute [rw] lastPage
# @return [String] Last page of the resource within the related item, e.g., of the chapter, article, or conference paper in proceedings.
text_node :last_page, 'lastPage', default_value: nil

# @!attribute [rw] publisher
# @return [Publisher] the name of the entity that holds, archives, publishes prints, distributes, releases, issues, or produces the resource.
object_node :publisher, 'publisher', class: Publisher

# @!attribute [rw] edition
# @return [String] Edition of the related item.
text_node :edition, 'edition', default_value: nil

# @!attribute [rw] contributors
# @return [Array<Contributor>] institutions or persons responsible for collecting, creating, or otherwise contributing to the developement of the dataset.
array_node :contributors, 'contributors', 'contributor', class: Contributor, default_value: []
end

# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
end
end
Loading