datacite-mapping 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +42 -0
- data/.rubocop.yml +28 -0
- data/.ruby-version +1 -0
- data/.travis.yml +2 -0
- data/.yardopts +2 -0
- data/CHANGES.md +3 -0
- data/Gemfile +3 -0
- data/LICENSE.md +22 -0
- data/README.md +168 -0
- data/Rakefile +49 -0
- data/datacite-mapping.gemspec +37 -0
- data/examples/reading.rb +75 -0
- data/examples/writing.rb +49 -0
- data/lib/datacite/mapping.rb +36 -0
- data/lib/datacite/mapping/alternate_identifier.rb +45 -0
- data/lib/datacite/mapping/contributor.rb +125 -0
- data/lib/datacite/mapping/creator.rb +48 -0
- data/lib/datacite/mapping/date.rb +153 -0
- data/lib/datacite/mapping/description.rb +121 -0
- data/lib/datacite/mapping/geo_location.rb +49 -0
- data/lib/datacite/mapping/geo_location_box.rb +137 -0
- data/lib/datacite/mapping/geo_location_point.rb +102 -0
- data/lib/datacite/mapping/identifier.rb +45 -0
- data/lib/datacite/mapping/module_info.rb +12 -0
- data/lib/datacite/mapping/name_identifier.rb +48 -0
- data/lib/datacite/mapping/related_identifier.rb +209 -0
- data/lib/datacite/mapping/resource.rb +201 -0
- data/lib/datacite/mapping/resource_type.rb +83 -0
- data/lib/datacite/mapping/rights.rb +36 -0
- data/lib/datacite/mapping/subject.rb +55 -0
- data/lib/datacite/mapping/title.rb +69 -0
- data/spec/.rubocop.yml +7 -0
- data/spec/data/resource.xml +61 -0
- data/spec/rspec_custom_matchers.rb +69 -0
- data/spec/spec_helper.rb +31 -0
- data/spec/unit/datacite/mapping/alternate_identifier_spec.rb +60 -0
- data/spec/unit/datacite/mapping/contributor_spec.rb +129 -0
- data/spec/unit/datacite/mapping/creator_spec.rb +125 -0
- data/spec/unit/datacite/mapping/date_spec.rb +246 -0
- data/spec/unit/datacite/mapping/description_spec.rb +89 -0
- data/spec/unit/datacite/mapping/geo_location_box_spec.rb +241 -0
- data/spec/unit/datacite/mapping/geo_location_point_spec.rb +148 -0
- data/spec/unit/datacite/mapping/geo_location_spec.rb +116 -0
- data/spec/unit/datacite/mapping/identifier_spec.rb +75 -0
- data/spec/unit/datacite/mapping/name_identifier_spec.rb +89 -0
- data/spec/unit/datacite/mapping/related_identifier_spec.rb +157 -0
- data/spec/unit/datacite/mapping/resource_spec.rb +727 -0
- data/spec/unit/datacite/mapping/resource_type_spec.rb +69 -0
- data/spec/unit/datacite/mapping/rights_spec.rb +78 -0
- data/spec/unit/datacite/mapping/subject_spec.rb +108 -0
- data/spec/unit/datacite/mapping/title_spec.rb +113 -0
- metadata +262 -0
@@ -0,0 +1,121 @@
|
|
1
|
+
require 'xml/mapping_extensions'
|
2
|
+
|
3
|
+
module Datacite
|
4
|
+
module Mapping
|
5
|
+
|
6
|
+
# Controlled vocabulary of description types.
|
7
|
+
class DescriptionType < TypesafeEnum::Base
|
8
|
+
# @!parse ABSTRACT = Abstract
|
9
|
+
new :ABSTRACT, 'Abstract'
|
10
|
+
|
11
|
+
# @!parse METHODS = Methods
|
12
|
+
new :METHODS, 'Methods'
|
13
|
+
|
14
|
+
# @!parse SERIES_INFORMATION = SeriesInformation
|
15
|
+
new :SERIES_INFORMATION, 'SeriesInformation'
|
16
|
+
|
17
|
+
# @!parse TABLE_OF_CONTENTS = TableOfContents
|
18
|
+
new :TABLE_OF_CONTENTS, 'TableOfContents'
|
19
|
+
|
20
|
+
# @!parse OTHER = Other
|
21
|
+
new :OTHER, 'Other'
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
# XML mapping class preserving `<br/>` tags in description values
|
26
|
+
class BreakPreservingValueNode < XML::Mapping::SingleAttributeNode
|
27
|
+
# Collapses a sequence of text nodes and `<br/>` tags into a single string value.
|
28
|
+
# Implements `SingleAttributeNode#xml_to_obj`.
|
29
|
+
# @param obj [Description] the object being created
|
30
|
+
# @param xml [REXML::Element] the XML being read
|
31
|
+
def xml_to_obj(obj, xml)
|
32
|
+
value_str = xml.children.map { |c| c.respond_to?(:value) ? c.value : c.to_s }.join
|
33
|
+
obj.value = value_str.strip
|
34
|
+
end
|
35
|
+
|
36
|
+
# Converts a string value to a sequence of text nodes and `<br/>` tags.
|
37
|
+
# Implements `SingleAttributeNode#obj_to_xml`.
|
38
|
+
# @param obj [Description] the object being serialized
|
39
|
+
# @param xml [REXML::Element] the XML being written
|
40
|
+
def obj_to_xml(obj, xml)
|
41
|
+
value_str = obj.value || ''
|
42
|
+
values = value_str.split(%r{<br[^/]?/>|<br>[^<]*</br>})
|
43
|
+
values.each_with_index do |v, i|
|
44
|
+
xml.add_text(v)
|
45
|
+
xml.add_element('br') unless i + 1 >= values.size
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
XML::Mapping.add_node_class BreakPreservingValueNode
|
50
|
+
|
51
|
+
# A additional information that does not fit in the other more specific {Resource}
|
52
|
+
# attributes.
|
53
|
+
#
|
54
|
+
# Note: In accordance with the DataCite spec, description text can be separated by
|
55
|
+
# HTML `<br/>` tags. The {Description} class will preserve these, but at the expense
|
56
|
+
# of converting escaped `<br/>` in text values to actual `<br/>` tags. For example,
|
57
|
+
# when reading the following tag:
|
58
|
+
#
|
59
|
+
# <description xml:lang="en-us" descriptionType="Abstract">
|
60
|
+
# Line 1<br/>Line 2 containing escaped <br/> tag<br/>Line 3
|
61
|
+
# </description>
|
62
|
+
#
|
63
|
+
# the value will be returned as the string
|
64
|
+
#
|
65
|
+
# "Line 1<br/>Line 2 containing escaped <br/> tag<br/>Line 3"
|
66
|
+
#
|
67
|
+
# in which it is impossible to distinguish the escaped an un-escaped `<br/>`s. The
|
68
|
+
# value would thus be written back to XML as:
|
69
|
+
#
|
70
|
+
# <description xml:lang="en-us" descriptionType="Abstract">
|
71
|
+
# Line 1<br/>Line 2 containing escaped <br/> tag<br/>Line 3
|
72
|
+
# </description>
|
73
|
+
#
|
74
|
+
# Other escaped HTML or XML tags will still be escaped when written back, and other
|
75
|
+
# un-escaped HTML and XML tags are of course not allowed.
|
76
|
+
class Description
|
77
|
+
include XML::Mapping
|
78
|
+
|
79
|
+
# @!attribute [rw] language
|
80
|
+
# @return [String] an IETF BCP 47, ISO 639-1 language code identifying the language.
|
81
|
+
# It's unclear from the spec whether language is required; to play it safe, if it's missing, we default to 'en'.
|
82
|
+
text_node :language, '@xml:lang', default_value: nil
|
83
|
+
|
84
|
+
# @!attribute [rw] type
|
85
|
+
# @return [DescriptionType] the description type.
|
86
|
+
typesafe_enum_node :type, '@descriptionType', class: DescriptionType
|
87
|
+
|
88
|
+
# @!attribute [rw] value
|
89
|
+
# @return [String] the description itself. See {Description} for notes on special
|
90
|
+
# handling of `<br/>` tags.
|
91
|
+
break_preserving_value_node :value, 'node()'
|
92
|
+
|
93
|
+
alias_method :_language, :language
|
94
|
+
private :_language
|
95
|
+
|
96
|
+
alias_method :_language=, :language=
|
97
|
+
private :_language=
|
98
|
+
|
99
|
+
# Initializes a new {Description}
|
100
|
+
# @param language [String] an IETF BCP 47, ISO 639-1 language code identifying the language.
|
101
|
+
# It's unclear from the spec whether language is required; to play it safe, if it's missing, we default to 'en'.
|
102
|
+
# @param type [DescriptionType] the description type.
|
103
|
+
# @param value [String] the description itself. See {Description} for notes on special
|
104
|
+
# handling of `<br/>` tags.
|
105
|
+
def initialize(language: 'en', type:, value:)
|
106
|
+
self.language = language
|
107
|
+
self.type = type
|
108
|
+
self.value = value
|
109
|
+
end
|
110
|
+
|
111
|
+
def language
|
112
|
+
_language || 'en'
|
113
|
+
end
|
114
|
+
|
115
|
+
def language=(value)
|
116
|
+
self._language = value.strip if value
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'xml/mapping_extensions'
|
2
|
+
require_relative 'geo_location_point'
|
3
|
+
require_relative 'geo_location_box'
|
4
|
+
|
5
|
+
module Datacite
|
6
|
+
module Mapping
|
7
|
+
|
8
|
+
# A location at which the data was gathered or about which the data is focused, in the
|
9
|
+
# form of a latitude-longitude point, a latitude-longitude quadrangle, and/or a place name.
|
10
|
+
#
|
11
|
+
# *Note:* Due to a quirk of the DataCite spec, it is possible for a {GeoLocation} to be empty, with
|
12
|
+
# none of these present.
|
13
|
+
class GeoLocation
|
14
|
+
include XML::Mapping
|
15
|
+
|
16
|
+
root_element_name 'geoLocation'
|
17
|
+
|
18
|
+
# @!attribute [rw] point
|
19
|
+
# @return [GeoLocationPoint, nil] the latitude and longitude at which the data was gathered or about which the data is focused.
|
20
|
+
geo_location_point_node :point, 'geoLocationPoint', default_value: nil
|
21
|
+
|
22
|
+
# @!attribute [rw] box
|
23
|
+
# @return [GeoLocationBox, nil] the latitude-longitude quadrangle containing the area where the data was gathered or about which the data is focused.
|
24
|
+
geo_location_box_node :box, 'geoLocationBox', default_value: nil
|
25
|
+
|
26
|
+
# @!attribute [rw] place
|
27
|
+
# @return [String, nil] the spatial region or named place where the data was gathered or about which the data is focused.
|
28
|
+
text_node :place, 'geoLocationPlace', default_value: nil
|
29
|
+
|
30
|
+
# Initializes a new {GeoLocation}
|
31
|
+
# @param point [GeoLocationPoint, nil] the latitude and longitude at which the data was gathered or about which the data is focused.
|
32
|
+
# @param box [GeoLocationBox, nil] the latitude-longitude quadrangle containing the area where the data was gathered or about which the data is focused.
|
33
|
+
# @param place [String, nil] the spatial region or named place where the data was gathered or about which the data is focused.
|
34
|
+
def initialize(point: nil, box: nil, place: nil)
|
35
|
+
self.point = point
|
36
|
+
self.box = box
|
37
|
+
self.place = place
|
38
|
+
end
|
39
|
+
|
40
|
+
alias_method :_place=, :place=
|
41
|
+
private :_place=
|
42
|
+
|
43
|
+
def place=(value)
|
44
|
+
self._place = value.respond_to?(:strip) ? value.strip : value
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
require 'xml/mapping'
|
2
|
+
|
3
|
+
module Datacite
|
4
|
+
module Mapping
|
5
|
+
# A latitude-longitude quadrangle containing the area where the data was gathered or about
|
6
|
+
# which the data is focused.
|
7
|
+
#
|
8
|
+
# @!attribute [rw] south_latitude
|
9
|
+
# @return [Numeric] the latitude of the south edge of the box
|
10
|
+
# @!attribute [rw] west_longitude
|
11
|
+
# @return [Numeric] the longitude of the west edge of the box
|
12
|
+
# @!attribute [rw] north_latitude
|
13
|
+
# @return [Numeric] the latitude of the north edge of the box
|
14
|
+
# @!attribute [rw] east_longitude
|
15
|
+
# @return [Numeric] the longitude of the east edge of the box
|
16
|
+
class GeoLocationBox
|
17
|
+
include Comparable
|
18
|
+
|
19
|
+
attr_reader :south_latitude
|
20
|
+
attr_reader :west_longitude
|
21
|
+
attr_reader :north_latitude
|
22
|
+
attr_reader :east_longitude
|
23
|
+
|
24
|
+
# Initializes a new {GeoLocationBox}. The arguments can be provided
|
25
|
+
# either as a named-parameter hash, or as a list of four coordinates
|
26
|
+
# in the form `lat, long, lat, long` (typically
|
27
|
+
# `south_latitude, west_longitude, north_latitude, east_longitude`
|
28
|
+
# but not necessarily; north/south and east/west will be flipped if
|
29
|
+
# need be). That is, the following forms are equivalent:
|
30
|
+
#
|
31
|
+
# GeoLocationBox.new(
|
32
|
+
# south_latitude: -33.45,
|
33
|
+
# west_longitude: -122.33,
|
34
|
+
# north_latitude: 47.61,
|
35
|
+
# east_longitude: -70.67
|
36
|
+
# )
|
37
|
+
#
|
38
|
+
# GeoLocationBox.new(-33.45, -122.33, 47.61, -70.67)
|
39
|
+
#
|
40
|
+
# @param south_latitude [Numeric]
|
41
|
+
# the latitude of the south edge of the box
|
42
|
+
# @param west_longitude [Numeric]
|
43
|
+
# the longitude of the west edge of the box
|
44
|
+
# @param north_latitude [Numeric]
|
45
|
+
# the latitude of the north edge of the box
|
46
|
+
# @param east_longitude [Numeric]
|
47
|
+
# the longitude of the east edge of the box
|
48
|
+
def initialize(*args)
|
49
|
+
case args.length
|
50
|
+
when 1
|
51
|
+
init_from_hash(args[0])
|
52
|
+
when 4
|
53
|
+
init_from_array(args)
|
54
|
+
else
|
55
|
+
fail ArgumentError, "Can't construct GeoLocationBox from arguments: #{args}"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def south_latitude=(value)
|
60
|
+
fail ArgumentError, 'South latitude cannot be nil' unless value
|
61
|
+
fail ArgumentError, "#{value} is not a valid south latitude" unless value >= -90 && value <= 90
|
62
|
+
@south_latitude = value
|
63
|
+
end
|
64
|
+
|
65
|
+
def west_longitude=(value)
|
66
|
+
fail ArgumentError, 'West longitude cannot be nil' unless value
|
67
|
+
fail ArgumentError, "#{value} is not a valid west longitude" unless value >= -180 && value <= 180
|
68
|
+
@west_longitude = value
|
69
|
+
end
|
70
|
+
|
71
|
+
def north_latitude=(value)
|
72
|
+
fail ArgumentError, 'North latitude cannot be nil' unless value
|
73
|
+
fail ArgumentError, "#{value} is not a valid north latitude" unless value >= -90 && value <= 90
|
74
|
+
@north_latitude = value
|
75
|
+
end
|
76
|
+
|
77
|
+
def east_longitude=(value)
|
78
|
+
fail ArgumentError, 'East longitude cannot be nil' unless value
|
79
|
+
fail ArgumentError, "#{value} is not a valid east longitude" unless value >= -180 && value <= 180
|
80
|
+
@east_longitude = value
|
81
|
+
end
|
82
|
+
|
83
|
+
# Gets the box coordinates as a string.
|
84
|
+
# @return [String] the coordinates of the box as a sequence of four numbers, in the order S W N E.
|
85
|
+
def to_s
|
86
|
+
"#{south_latitude} #{west_longitude} #{north_latitude} #{east_longitude}"
|
87
|
+
end
|
88
|
+
|
89
|
+
# Sorts boxes from north to south and east to west, first by south edge, then west
|
90
|
+
# edge, then north edge, then east edge, and compares them for equality.
|
91
|
+
# @param other [GeoLocationBox] the box to compare
|
92
|
+
# @return [Fixnum, nil] the sort order (-1, 0, or 1), or nil if `other` is not a
|
93
|
+
# {GeoLocationBox}
|
94
|
+
def <=>(other)
|
95
|
+
return nil unless other.class == self.class
|
96
|
+
[:south_latitude, :west_longitude, :north_latitude, :east_longitude].each do |c|
|
97
|
+
order = send(c) <=> other.send(c)
|
98
|
+
return order if order != 0
|
99
|
+
end
|
100
|
+
0
|
101
|
+
end
|
102
|
+
|
103
|
+
# Returns a hash code consistent with {GeoLocationBox#<=>}
|
104
|
+
# @return [Integer] the hash code
|
105
|
+
def hash
|
106
|
+
[south_latitude, west_longitude, north_latitude, east_longitude].hash
|
107
|
+
end
|
108
|
+
|
109
|
+
private
|
110
|
+
|
111
|
+
def init_from_hash(south_latitude:, west_longitude:, north_latitude:, east_longitude:)
|
112
|
+
self.south_latitude = south_latitude
|
113
|
+
self.west_longitude = west_longitude
|
114
|
+
self.north_latitude = north_latitude
|
115
|
+
self.east_longitude = east_longitude
|
116
|
+
end
|
117
|
+
|
118
|
+
def init_from_array(coordinates)
|
119
|
+
self.south_latitude, self.north_latitude = [coordinates[0], coordinates[2]].sort
|
120
|
+
self.west_longitude, self.east_longitude = [coordinates[1], coordinates[3]].sort
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
# XML mapping node for `<geoLocationBox/>`
|
125
|
+
class GeoLocationBoxNode < XML::MappingExtensions::NodeBase
|
126
|
+
# Converts a whitespace-separated list of coordinates to a {GeoLocationBox}.
|
127
|
+
# @param xml_text [String] the coordinates, in the order `lat long lat long`.
|
128
|
+
def to_value(xml_text)
|
129
|
+
stripped = xml_text.strip
|
130
|
+
coords = stripped.split(/\s+/).map(&:to_f)
|
131
|
+
GeoLocationBox.new(*coords)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
XML::Mapping.add_node_class GeoLocationBoxNode
|
135
|
+
|
136
|
+
end
|
137
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'xml/mapping'
|
2
|
+
|
3
|
+
module Datacite
|
4
|
+
module Mapping
|
5
|
+
# A latitude-longitude point at which the data was gathered or about
|
6
|
+
# which the data is focused.
|
7
|
+
#
|
8
|
+
# @!attribute [rw] latitude
|
9
|
+
# @return [Numeric] the latitude
|
10
|
+
# @!attribute [rw] longitude
|
11
|
+
# @return [Numeric] the longitude
|
12
|
+
class GeoLocationPoint
|
13
|
+
include Comparable
|
14
|
+
|
15
|
+
attr_reader :latitude
|
16
|
+
attr_reader :longitude
|
17
|
+
|
18
|
+
# Initializes a new {GeoLocationPoint}. The arguments can be provided
|
19
|
+
# either as a named-parameter hash, or as a pair of coordinates in the
|
20
|
+
# form `lat, long`. That is, the following forms are equivalent:
|
21
|
+
#
|
22
|
+
# GeoLocationPoint.new(latitude: 47.61, longitude: -122.33)
|
23
|
+
#
|
24
|
+
# GeoLocationPoint.new(47.61, -122.33)
|
25
|
+
#
|
26
|
+
# @param latitude [Numeric] the latitude
|
27
|
+
# @param longitude [Numeric] the longitude
|
28
|
+
def initialize(*args)
|
29
|
+
case args.length
|
30
|
+
when 1
|
31
|
+
init_from_hash(args[0])
|
32
|
+
when 2
|
33
|
+
init_from_array(args)
|
34
|
+
else
|
35
|
+
fail ArgumentError, "Can't construct GeoLocationPoint from arguments: #{args}"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def latitude=(value)
|
40
|
+
fail ArgumentError, 'Latitude cannot be nil' unless value
|
41
|
+
fail ArgumentError, "#{value} is not a valid latitude" unless value >= -90 && value <= 90
|
42
|
+
@latitude = value
|
43
|
+
end
|
44
|
+
|
45
|
+
def longitude=(value)
|
46
|
+
fail ArgumentError, 'Longitude cannot be nil' unless value
|
47
|
+
fail ArgumentError, "#{value} is not a valid longitude" unless value >= -180 && value <= 180
|
48
|
+
@longitude = value
|
49
|
+
end
|
50
|
+
|
51
|
+
# Gets the coordinates as a string.
|
52
|
+
# @return [String] the coordinates as a pair of numbers separated by a space, in the
|
53
|
+
# order `lat` `long`.
|
54
|
+
def to_s
|
55
|
+
"#{latitude} #{longitude}"
|
56
|
+
end
|
57
|
+
|
58
|
+
# Sorts points from north to south and from east to west, and compares them for equality.
|
59
|
+
# @param other [GeoLocationPoint] the point to compare
|
60
|
+
# @return [Fixnum, nil] the sort order (-1, 0, or 1), or nil if `other` is not a
|
61
|
+
# {GeoLocationPoint}
|
62
|
+
def <=>(other)
|
63
|
+
return nil unless other.class == self.class
|
64
|
+
[:latitude, :longitude].each do |c|
|
65
|
+
order = send(c) <=> other.send(c)
|
66
|
+
return order if order != 0
|
67
|
+
end
|
68
|
+
0
|
69
|
+
end
|
70
|
+
|
71
|
+
# Returns a hash code consistent with {GeoLocationPoint#<=>}
|
72
|
+
# @return [Integer] the hash code
|
73
|
+
def hash
|
74
|
+
[latitude, longitude].hash
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def init_from_hash(latitude:, longitude:)
|
80
|
+
self.latitude = latitude
|
81
|
+
self.longitude = longitude
|
82
|
+
end
|
83
|
+
|
84
|
+
def init_from_array(args)
|
85
|
+
self.latitude, self.longitude = args
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# XML mapping node for `<geoLocationPoint/>`
|
90
|
+
class GeoLocationPointNode < XML::MappingExtensions::NodeBase
|
91
|
+
# Converts a whitespace-separated pair of coordinates to a {GeoLocationPoint}.
|
92
|
+
# @param xml_text [String] the coordinates, in the order `lat` `long`.
|
93
|
+
def to_value(xml_text)
|
94
|
+
stripped = xml_text.strip
|
95
|
+
coords = stripped.split(/\s+/).map(&:to_f)
|
96
|
+
GeoLocationPoint.new(*coords)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
XML::Mapping.add_node_class GeoLocationPointNode
|
100
|
+
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'xml/mapping'
|
2
|
+
|
3
|
+
module Datacite
|
4
|
+
module Mapping
|
5
|
+
# The persistent identifier that identifies the resource.
|
6
|
+
#
|
7
|
+
# @!attribute [r] identifier_type
|
8
|
+
# @return [String] the identifier type (always 'DOI')
|
9
|
+
# @!attribute [rw] value
|
10
|
+
# @return [String] the identifier value. Must be a valid DOI value (`10.`_registrant code_`/`_suffix_)
|
11
|
+
class Identifier
|
12
|
+
include XML::Mapping
|
13
|
+
|
14
|
+
text_node :identifier_type, '@identifierType'
|
15
|
+
text_node :value, 'text()'
|
16
|
+
|
17
|
+
# Initializes a new {Identifier}
|
18
|
+
# @param value [String]
|
19
|
+
# the identifier value. Must be a valid DOI value (`10.`_registrant code_`/`_suffix_)
|
20
|
+
def initialize(value:)
|
21
|
+
self.identifier_type = 'DOI'
|
22
|
+
self.value = value
|
23
|
+
end
|
24
|
+
|
25
|
+
alias_method :_value=, :value=
|
26
|
+
private :_value=
|
27
|
+
|
28
|
+
alias_method :_identifier_type=, :identifier_type=
|
29
|
+
private :_identifier_type=
|
30
|
+
|
31
|
+
def value=(v)
|
32
|
+
fail ArgumentError, "Identifier value '#{v}' is not a valid DOI" unless v.match(%r{10\..+/.+})
|
33
|
+
self._value = v
|
34
|
+
end
|
35
|
+
|
36
|
+
# Sets the identifier type. Should only be called by the XML mapping engine.
|
37
|
+
# @param v [String]
|
38
|
+
# the identifier type (always 'DOI')
|
39
|
+
def identifier_type=(v)
|
40
|
+
fail ArgumentError, "Identifier type '#{v}' must be 'DOI'" unless 'DOI' == v
|
41
|
+
self._identifier_type = v
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|