datacite-mapping 0.2.4 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. checksums.yaml +5 -5
  2. data/.rubocop.yml +27 -11
  3. data/.ruby-version +1 -1
  4. data/CHANGES.md +25 -0
  5. data/Gemfile +2 -0
  6. data/LICENSE.md +1 -1
  7. data/README.md +10 -5
  8. data/Rakefile +5 -3
  9. data/datacite-mapping.gemspec +10 -9
  10. data/examples/reading.rb +1 -1
  11. data/examples/writing.rb +1 -0
  12. data/lib/datacite/mapping/affiliation.rb +44 -0
  13. data/lib/datacite/mapping/alternate_identifier.rb +6 -2
  14. data/lib/datacite/mapping/contributor.rb +35 -7
  15. data/lib/datacite/mapping/contributor_name.rb +42 -0
  16. data/lib/datacite/mapping/creator.rb +43 -9
  17. data/lib/datacite/mapping/creator_name.rb +42 -0
  18. data/lib/datacite/mapping/date.rb +17 -5
  19. data/lib/datacite/mapping/date_value.rb +10 -2
  20. data/lib/datacite/mapping/description.rb +10 -4
  21. data/lib/datacite/mapping/empty_filtering_nodes.rb +3 -0
  22. data/lib/datacite/mapping/funding_reference.rb +31 -10
  23. data/lib/datacite/mapping/geo_location.rb +8 -1
  24. data/lib/datacite/mapping/geo_location_box.rb +17 -10
  25. data/lib/datacite/mapping/geo_location_node.rb +12 -8
  26. data/lib/datacite/mapping/geo_location_point.rb +11 -6
  27. data/lib/datacite/mapping/geo_location_polygon.rb +13 -2
  28. data/lib/datacite/mapping/identifier.rb +18 -14
  29. data/lib/datacite/mapping/module_info.rb +5 -3
  30. data/lib/datacite/mapping/name_identifier.rb +12 -6
  31. data/lib/datacite/mapping/name_type.rb +18 -0
  32. data/lib/datacite/mapping/namespace_extensions.rb +2 -0
  33. data/lib/datacite/mapping/publisher.rb +42 -0
  34. data/lib/datacite/mapping/read_only_nodes.rb +9 -3
  35. data/lib/datacite/mapping/related_identifier.rb +43 -4
  36. data/lib/datacite/mapping/resource.rb +37 -21
  37. data/lib/datacite/mapping/resource_type.rb +7 -1
  38. data/lib/datacite/mapping/rights.rb +35 -6
  39. data/lib/datacite/mapping/subject.rb +7 -4
  40. data/lib/datacite/mapping/title.rb +7 -4
  41. data/lib/datacite/mapping.rb +3 -1
  42. data/spec/.rubocop.yml +3 -0
  43. data/spec/data/datacite4/{datacite-example-Box_dateCollected_DataCollector-v4.0.xml → datacite-example-Box_dateCollected_DataCollector-v4.xml} +9 -11
  44. data/spec/data/datacite4/{datacite-example-GeoLocation-v4.0.xml → datacite-example-GeoLocation-v4.xml} +11 -10
  45. data/spec/data/datacite4/{datacite-example-HasMetadata-v4.0.xml → datacite-example-HasMetadata-v4.xml} +18 -13
  46. data/spec/data/datacite4/{datacite-example-ResearchGroup_Methods-v4.0.xml → datacite-example-ResearchGroup_Methods-v4.xml} +14 -12
  47. data/spec/data/datacite4/{datacite-example-ResourceTypeGeneral_Collection-v4.0.xml → datacite-example-ResourceTypeGeneral_Collection-v4.xml} +9 -9
  48. data/spec/data/datacite4/datacite-example-affiliation-v4.xml +114 -0
  49. data/spec/data/datacite4/{datacite-example-complicated-v4.0.xml → datacite-example-complicated-v4.xml} +14 -11
  50. data/spec/data/datacite4/datacite-example-datapaper-v4.xml +32 -0
  51. data/spec/data/datacite4/{datacite-example-dataset-v4.0.xml → datacite-example-dataset-v4.xml} +20 -14
  52. data/spec/data/datacite4/datacite-example-full-v4.xml +114 -0
  53. data/spec/data/datacite4/{datacite-example-fundingReference-v.4.0.xml → datacite-example-fundingReference-v4.xml} +16 -13
  54. data/spec/data/datacite4/datacite-example-polygon-advanced-v4.xml +141 -0
  55. data/spec/data/datacite4/datacite-example-polygon-v4.xml +161 -0
  56. data/spec/data/datacite4/{datacite-example-relationTypeIsIdenticalTo-v4.0.xml → datacite-example-relationTypeIsIdenticalTo-v4.xml} +17 -17
  57. data/spec/data/datacite4/datacite-example-software-v4.xml +66 -0
  58. data/spec/data/datacite4/{datacite-example-video-v4.0.xml → datacite-example-video-v4.xml} +7 -7
  59. data/spec/data/datacite4/{datacite-example-workflow-v4.0.xml → datacite-example-workflow-v4.xml} +13 -11
  60. data/spec/data/datacite4/metadata.xsd +102 -57
  61. data/spec/rspec_custom_matchers.rb +11 -8
  62. data/spec/spec_helper.rb +2 -0
  63. data/spec/unit/datacite/mapping/alternate_identifier_spec.rb +2 -0
  64. data/spec/unit/datacite/mapping/contributor_spec.rb +9 -1
  65. data/spec/unit/datacite/mapping/creator_spec.rb +11 -3
  66. data/spec/unit/datacite/mapping/date_spec.rb +2 -0
  67. data/spec/unit/datacite/mapping/date_value_spec.rb +2 -0
  68. data/spec/unit/datacite/mapping/description_spec.rb +2 -0
  69. data/spec/unit/datacite/mapping/funding_reference_spec.rb +13 -1
  70. data/spec/unit/datacite/mapping/geo_location_box_spec.rb +2 -0
  71. data/spec/unit/datacite/mapping/geo_location_point_spec.rb +2 -0
  72. data/spec/unit/datacite/mapping/geo_location_polygon_spec.rb +22 -20
  73. data/spec/unit/datacite/mapping/geo_location_spec.rb +24 -22
  74. data/spec/unit/datacite/mapping/identifier_spec.rb +8 -6
  75. data/spec/unit/datacite/mapping/name_identifier_spec.rb +2 -0
  76. data/spec/unit/datacite/mapping/related_identifier_spec.rb +2 -0
  77. data/spec/unit/datacite/mapping/resource_spec.rb +34 -33
  78. data/spec/unit/datacite/mapping/rights_spec.rb +3 -14
  79. data/spec/unit/datacite/mapping/subject_spec.rb +2 -0
  80. data/spec/unit/datacite/mapping/title_spec.rb +2 -0
  81. metadata +74 -60
  82. data/spec/data/datacite4/datacite-example-full-v4.0.xml +0 -71
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'xml/mapping_extensions'
2
4
 
3
5
  module Datacite
@@ -52,12 +54,13 @@ module Datacite
52
54
  @nsec = datetime.to_time.nsec
53
55
  @zone = datetime.zone
54
56
  end
55
- fail ArgumentError, "Unable to parse date value '#{val}'" unless @year
57
+ raise ArgumentError, "Unable to parse date value '#{val}'" unless @year
56
58
  end
57
59
 
58
60
  def <=>(other)
59
61
  return nil unless other.class == self.class
60
- [:year, :month, :day, :hour, :minute, :sec, :nsec].each do |v|
62
+
63
+ %i[year month day hour minute sec nsec].each do |v|
61
64
  order = send(v) <=> other.send(v)
62
65
  return order if order.nonzero?
63
66
  end
@@ -84,24 +87,28 @@ module Datacite
84
87
  def to_year(val)
85
88
  return val if val.is_a?(Integer)
86
89
  return val.year if val.respond_to?(:year)
90
+
87
91
  matchdata = val.to_s.match(/^[0-9]+/)
88
92
  matchdata[0].to_i if matchdata
89
93
  end
90
94
 
91
95
  def to_month(val)
92
96
  return val.month if val.respond_to?(:month)
97
+
93
98
  matchdata = val.to_s.match(/^[0-9]+-([0-9]{2})(?![0-9])/)
94
99
  matchdata[1].to_i if matchdata
95
100
  end
96
101
 
97
102
  def to_day(val)
98
103
  return val.day if val.respond_to?(:day)
104
+
99
105
  matchdata = val.to_s.match(/^[0-9]+-[0-9]{2}-([0-9]{2})(?![0-9])/)
100
106
  matchdata[1].to_i if matchdata
101
107
  end
102
108
 
103
109
  def to_datetime(val)
104
110
  return val if val.is_a?(DateTime)
111
+
105
112
  DateTime.parse(val.to_s)
106
113
  rescue ArgumentError
107
114
  nil
@@ -110,6 +117,7 @@ module Datacite
110
117
  def to_date(val)
111
118
  return val if val.is_a?(::Date)
112
119
  return ::Date.parse(val.iso8601) if val.respond_to?(:iso8601)
120
+
113
121
  ::Date.parse(val.to_s)
114
122
  rescue ArgumentError
115
123
  nil
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'xml/mapping_extensions'
2
4
 
3
5
  module Datacite
@@ -17,6 +19,9 @@ module Datacite
17
19
  # @!parse TABLE_OF_CONTENTS = TableOfContents
18
20
  new :TABLE_OF_CONTENTS, 'TableOfContents'
19
21
 
22
+ # @!parse TECHNICAL_INFO = TechnicalInfo
23
+ new :TECHNICAL_INFO, 'TechnicalInfo'
24
+
20
25
  # @!parse OTHER = Other
21
26
  new :OTHER, 'Other'
22
27
 
@@ -88,12 +93,13 @@ module Datacite
88
93
  end
89
94
 
90
95
  def language=(value)
91
- @language = value && value.strip
96
+ @language = value&.strip
92
97
  end
93
98
 
94
- def value=(v)
95
- new_value = v && v.strip
96
- fail ArgumentError, 'Value cannot be empty or nil' unless new_value && !new_value.empty?
99
+ def value=(a_value)
100
+ new_value = a_value&.strip
101
+ raise ArgumentError, 'Value cannot be empty or nil' unless new_value && !new_value.empty?
102
+
97
103
  @value = new_value
98
104
  end
99
105
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'xml/mapping_extensions'
2
4
 
3
5
  module Datacite
@@ -6,6 +8,7 @@ module Datacite
6
8
  module EmptyNodeUtils
7
9
  def not_empty(element)
8
10
  return unless element
11
+
9
12
  text = element.text
10
13
  empty = text.nil? || text.strip.empty?
11
14
  warn "Ignoring empty element #{element}" if empty
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'xml/mapping_extensions'
2
4
 
3
5
  module Datacite
@@ -13,6 +15,9 @@ module Datacite
13
15
  # @!parse CROSSREF_FUNDER = 'Crossref Funder ID'
14
16
  new :CROSSREF_FUNDER_ID, 'Crossref Funder ID'
15
17
 
18
+ # @!parse ROR = ROR
19
+ new :ROR, 'ROR'
20
+
16
21
  # @!parse OTHER = Other
17
22
  new :OTHER, 'Other'
18
23
  end
@@ -22,18 +27,21 @@ module Datacite
22
27
 
23
28
  # @param type [FunderIdentifierType] the identifier type. Cannot be nil.
24
29
  # @param value [String] the identifier value. Cannot be nil.
25
- def initialize(type:, value:)
30
+ def initialize(type:, scheme_uri: nil, value:)
26
31
  self.type = type
32
+ self.scheme_uri = scheme_uri
27
33
  self.value = value
28
34
  end
29
35
 
30
36
  def value=(value)
31
- fail ArgumentError, 'Value cannot be empty or nil' unless value && !value.empty?
37
+ raise ArgumentError, 'Value cannot be empty or nil' unless value && !value.empty?
38
+
32
39
  @value = value
33
40
  end
34
41
 
35
42
  def type=(value)
36
- fail ArgumentError, 'Type cannot be nil' unless value
43
+ raise ArgumentError, 'Type cannot be nil' unless value
44
+
37
45
  @type = value
38
46
  end
39
47
 
@@ -45,6 +53,10 @@ module Datacite
45
53
  # @return [FunderIdentifierType] the identifier type. Cannot be nil.
46
54
  typesafe_enum_node :type, '@funderIdentifierType', class: FunderIdentifierType
47
55
 
56
+ # @!attribute [rw] scheme_uri
57
+ # @return [URI, nil] the URI of the identifier scheme. Optional.
58
+ uri_node :scheme_uri, '@schemeURI', default_value: nil
59
+
48
60
  # @!attribute [rw] value
49
61
  # @return [String] the identifier value. Cannot be nil.
50
62
  text_node :value, 'text()'
@@ -59,7 +71,8 @@ module Datacite
59
71
  end
60
72
 
61
73
  def value=(value)
62
- fail ArgumentError, 'Value cannot be empty or nil' unless value && !value.empty?
74
+ raise ArgumentError, 'Value cannot be empty or nil' unless value && !value.empty?
75
+
63
76
  @value = value
64
77
  end
65
78
 
@@ -89,15 +102,11 @@ module Datacite
89
102
  end
90
103
 
91
104
  def award_number=(value)
92
- @award_number = if value.nil? || value.is_a?(AwardNumber)
93
- value
94
- else
95
- AwardNumber.new(value: value.to_s)
96
- end
105
+ @award_number = award_number_or_nil(value)
97
106
  end
98
107
 
99
108
  def to_s
100
- fields = [:name, :identifier, :award_number, :award_title].map { |f| "#{f}: #{send(f)}" }
109
+ fields = %i[name identifier award_number award_title].map { |f| "#{f}: #{send(f)}" }
101
110
  "FundingReference { #{fields.join(', ')} }"
102
111
  end
103
112
 
@@ -107,6 +116,18 @@ module Datacite
107
116
  text_node :award_title, 'awardTitle', default_value: nil
108
117
 
109
118
  fallback_mapping :datacite_3, :_default
119
+
120
+ private
121
+
122
+ def award_number_or_nil(value)
123
+ return nil unless value
124
+ return value if value.is_a?(AwardNumber)
125
+
126
+ new_value = value.to_s.strip
127
+ return nil if new_value.empty?
128
+
129
+ AwardNumber.new(value: new_value)
130
+ end
110
131
  end
111
132
  end
112
133
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'xml/mapping_extensions'
2
4
  require 'datacite/mapping/geo_location_point'
3
5
  require 'datacite/mapping/geo_location_box'
@@ -19,11 +21,12 @@ module Datacite
19
21
  # @param box [GeoLocationBox, nil] the latitude-longitude quadrangle containing the area where the data was gathered or about which the data is focused.
20
22
  # @param place [String, nil] the spatial region or named place where the data was gathered or about which the data is focused.
21
23
  # @param polygon [GeoLocationPolygon, nil] a drawn polygon area containing the area where the data was gathered or about which the data is focused.
22
- def initialize(point: nil, box: nil, place: nil, polygon: nil)
24
+ def initialize(point: nil, box: nil, place: nil, polygon: nil, polygons: [])
23
25
  self.point = point
24
26
  self.box = box
25
27
  self.place = place
26
28
  self.polygon = polygon
29
+ self.polygons = polygons
27
30
  end
28
31
 
29
32
  def place=(value)
@@ -48,6 +51,10 @@ module Datacite
48
51
  # # @return [GeoLocationPolygon] a drawn polygon area containing the area where the data was gathered or about which the data is focused.
49
52
  object_node :polygon, 'geoLocationPolygon', class: GeoLocationPolygon, default_value: nil
50
53
 
54
+ # @!attribute [rw] polygons
55
+ # @return [Array<GeoLocationPolygon>] multiple polygons where data is contained
56
+ array_node :polygons, 'geoLocationPolygons', 'geoLocationPolygon', class: GeoLocationPolygon, default_value: []
57
+
51
58
  # @!attribute [rw] place
52
59
  # @return [String, nil] the spatial region or named place where the data was gathered or about which the data is focused.
53
60
  text_node :place, 'geoLocationPlace', default_value: nil
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'xml/mapping'
2
4
  require 'datacite/mapping/geo_location_node'
3
5
 
@@ -53,31 +55,35 @@ module Datacite
53
55
  when 4
54
56
  init_from_array(args)
55
57
  else
56
- fail ArgumentError, "Can't construct GeoLocationBox from arguments: #{args}"
58
+ raise ArgumentError, "Can't construct GeoLocationBox from arguments: #{args}"
57
59
  end
58
60
  end
59
61
 
60
62
  def south_latitude=(value)
61
- fail ArgumentError, 'South latitude cannot be nil' unless value
62
- fail ArgumentError, "#{value} is not a valid south latitude" unless value >= -90 && value <= 90
63
+ raise ArgumentError, 'South latitude cannot be nil' unless value
64
+ raise ArgumentError, "#{value} is not a valid south latitude" unless value >= -90 && value <= 90
65
+
63
66
  @south_latitude = value
64
67
  end
65
68
 
66
69
  def west_longitude=(value)
67
- fail ArgumentError, 'West longitude cannot be nil' unless value
68
- fail ArgumentError, "#{value} is not a valid west longitude" unless value >= -180 && value <= 180
70
+ raise ArgumentError, 'West longitude cannot be nil' unless value
71
+ raise ArgumentError, "#{value} is not a valid west longitude" unless value >= -180 && value <= 180
72
+
69
73
  @west_longitude = value
70
74
  end
71
75
 
72
76
  def north_latitude=(value)
73
- fail ArgumentError, 'North latitude cannot be nil' unless value
74
- fail ArgumentError, "#{value} is not a valid north latitude" unless value >= -90 && value <= 90
77
+ raise ArgumentError, 'North latitude cannot be nil' unless value
78
+ raise ArgumentError, "#{value} is not a valid north latitude" unless value >= -90 && value <= 90
79
+
75
80
  @north_latitude = value
76
81
  end
77
82
 
78
83
  def east_longitude=(value)
79
- fail ArgumentError, 'East longitude cannot be nil' unless value
80
- fail ArgumentError, "#{value} is not a valid east longitude" unless value >= -180 && value <= 180
84
+ raise ArgumentError, 'East longitude cannot be nil' unless value
85
+ raise ArgumentError, "#{value} is not a valid east longitude" unless value >= -180 && value <= 180
86
+
81
87
  @east_longitude = value
82
88
  end
83
89
 
@@ -94,7 +100,8 @@ module Datacite
94
100
  # {GeoLocationBox}
95
101
  def <=>(other)
96
102
  return nil unless other.class == self.class
97
- [:south_latitude, :west_longitude, :north_latitude, :east_longitude].each do |c|
103
+
104
+ %i[south_latitude west_longitude north_latitude east_longitude].each do |c|
98
105
  order = send(c) <=> other.send(c)
99
106
  return order if order.nonzero?
100
107
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'xml/mapping_extensions'
2
4
 
3
5
  module Datacite
@@ -9,11 +11,12 @@ module Datacite
9
11
  attr_reader :coord_elements
10
12
 
11
13
  def initialize(*args)
12
- fail 'No geometry class provided' unless @geom_class
13
- fail 'No coordinate elements provided' unless @coord_elements
14
- path, *args = super(*args)
14
+ raise 'No geometry class provided' unless @geom_class
15
+ raise 'No coordinate elements provided' unless @coord_elements
16
+
17
+ path, *myargs = super(*args)
15
18
  @path = ::XML::XXPath.new(path)
16
- args
19
+ myargs # rubocop:disable Lint/Void
17
20
  end
18
21
 
19
22
  def datacite_3?
@@ -21,13 +24,14 @@ module Datacite
21
24
  end
22
25
 
23
26
  def extract_attr_value(xml)
24
- return from_text(xml) || from_children(xml)
25
- rescue => e
27
+ from_text(xml) || from_children(xml)
28
+ rescue StandardError => e
26
29
  raise e, "#{@owner}.#{@attrname}: Can't extract #{self.class} from #{xml}: #{e.message}"
27
30
  end
28
31
 
29
- def set_attr_value(xml, value) # rubocop:disable Metrics/AbcSize
30
- fail "Invalid value: expected #{geom_class} instance, was #{value || 'nil'}" unless value && value.is_a?(geom_class)
32
+ def set_attr_value(xml, value)
33
+ raise "Invalid value: expected #{geom_class} instance, was #{value || 'nil'}" unless value&.is_a?(geom_class)
34
+
31
35
  element = @path.first(xml, ensure_created: true)
32
36
 
33
37
  if datacite_3?
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'xml/mapping'
2
4
  require 'datacite/mapping/geo_location_node'
3
5
 
@@ -33,19 +35,21 @@ module Datacite
33
35
  when 2
34
36
  init_from_array(args)
35
37
  else
36
- fail ArgumentError, "Can't construct GeoLocationPoint from arguments: #{args}"
38
+ raise ArgumentError, "Can't construct GeoLocationPoint from arguments: #{args}"
37
39
  end
38
40
  end
39
41
 
40
42
  def latitude=(value)
41
- fail ArgumentError, 'Latitude cannot be nil' unless value
42
- fail ArgumentError, "#{value} is not a valid latitude" unless value >= -90 && value <= 90
43
+ raise ArgumentError, 'Latitude cannot be nil' unless value
44
+ raise ArgumentError, "#{value} is not a valid latitude" unless value >= -90 && value <= 90
45
+
43
46
  @latitude = value
44
47
  end
45
48
 
46
49
  def longitude=(value)
47
- fail ArgumentError, 'Longitude cannot be nil' unless value
48
- fail ArgumentError, "#{value} is not a valid longitude" unless value >= -180 && value <= 180
50
+ raise ArgumentError, 'Longitude cannot be nil' unless value
51
+ raise ArgumentError, "#{value} is not a valid longitude" unless value >= -180 && value <= 180
52
+
49
53
  @longitude = value
50
54
  end
51
55
 
@@ -62,7 +66,8 @@ module Datacite
62
66
  # {GeoLocationPoint}
63
67
  def <=>(other)
64
68
  return nil unless other.class == self.class
65
- [:latitude, :longitude].each do |c|
69
+
70
+ %i[latitude longitude].each do |c|
66
71
  order = send(c) <=> other.send(c)
67
72
  return order if order.nonzero?
68
73
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'xml/mapping'
2
4
 
3
5
  module Datacite
@@ -11,10 +13,11 @@ module Datacite
11
13
  # @param points [Array<GeoLocationPoint>] an array of points defining the polygon area.
12
14
  # Per the spec, the array should contain at least four points, the first and last being
13
15
  # identical to close the polygon.
14
- def initialize(points:) # TODO: allow simple array of point args, array of hashes
16
+ def initialize(points:, in_polygon_point: nil) # TODO: allow simple array of point args, array of hashes
15
17
  self.points = points
18
+ self.in_polygon_point = in_polygon_point
16
19
  warn "Polygon should contain at least 4 points, but has #{points.size}" if points.size < 4
17
- warn "Polygon is not closed; last and first point should be identical, but were: [#{points[0]}], [#{points[-1]}]" if points.size > 1 unless points[0] == points[-1]
20
+ warn "Polygon is not closed; last and first point should be identical, but were: [#{points[0]}], [#{points[-1]}]" unless points[0] == points[-1] || points.size <= 1
18
21
  end
19
22
 
20
23
  def points=(value)
@@ -23,6 +26,7 @@ module Datacite
23
26
 
24
27
  def <=>(other)
25
28
  return nil unless other.class == self.class
29
+
26
30
  points <=> other.points
27
31
  end
28
32
 
@@ -42,6 +46,13 @@ module Datacite
42
46
  marshaller: (proc { |xml, value| marshal_point(xml, value) }),
43
47
  unmarshaller: (proc { |xml| unmarshal_point(xml) })
44
48
 
49
+ # # @!attribute [rw] in_polygon_point
50
+ # # @return [InPolygonPoint] a point within the target polygon
51
+ object_node :in_polygon_point, 'inPolygonPoint',
52
+ default_value: nil,
53
+ marshaller: (proc { |xml, value| marshal_point(xml, value) }),
54
+ unmarshaller: (proc { |xml| unmarshal_point(xml) })
55
+
45
56
  use_mapping :datacite_3
46
57
 
47
58
  # TODO: does this ever get called?
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'xml/mapping'
2
4
  require 'datacite/mapping/empty_filtering_nodes'
3
5
 
4
6
  module Datacite
5
7
  module Mapping
6
- DOI_PATTERN = %r{10\.\S+/\S+}
8
+ DOI_PATTERN = %r{10\.\S+/\S+}.freeze
7
9
 
8
10
  # The persistent identifier that identifies the resource.
9
11
  #
@@ -14,7 +16,7 @@ module Datacite
14
16
  class Identifier
15
17
  include XML::Mapping
16
18
 
17
- DOI = 'DOI'.freeze
19
+ DOI = 'DOI'
18
20
 
19
21
  # Initializes a new {Identifier}
20
22
  # @param value [String]
@@ -24,19 +26,21 @@ module Datacite
24
26
  self.value = value
25
27
  end
26
28
 
27
- def value=(v)
28
- new_value = v && v.strip
29
- fail ArgumentError, 'Identifier must have a non-nil value' unless new_value
30
- fail ArgumentError, "Identifier value '#{new_value}' is not a valid DOI" unless new_value.match(DOI_PATTERN)
29
+ def value=(new_value)
30
+ new_value = new_value&.strip
31
+ raise ArgumentError, 'Identifier must have a non-nil value' unless new_value
32
+ raise ArgumentError, "Identifier value '#{new_value}' is not a valid DOI" unless new_value.match?(DOI_PATTERN)
33
+
31
34
  @value = new_value
32
35
  end
33
36
 
34
37
  # Sets the identifier type. Should only be called by the XML mapping engine.
35
- # @param v [String]
38
+ # @param new_value [String]
36
39
  # the identifier type (always 'DOI')
37
- def identifier_type=(v)
38
- fail ArgumentError, "Identifier type '#{v}' must be 'DOI'" unless DOI == v
39
- @identifier_type = v
40
+ def identifier_type=(new_value)
41
+ raise ArgumentError, "Identifier type '#{new_value}' must be 'DOI'" unless DOI == new_value
42
+
43
+ @identifier_type = new_value
40
44
  end
41
45
 
42
46
  # Gets the identifiery type.
@@ -48,7 +52,8 @@ module Datacite
48
52
  # @param doi_string [String]
49
53
  def self.from_doi(doi_string)
50
54
  match = doi_string.match(DOI_PATTERN)
51
- fail ArgumentError, "'#{doi_string}' does not appear to contain a valid DOI" unless match
55
+ raise ArgumentError, "'#{doi_string}' does not appear to contain a valid DOI" unless match
56
+
52
57
  Identifier.new(value: match[0])
53
58
  end
54
59
 
@@ -58,18 +63,17 @@ module Datacite
58
63
  fallback_mapping :datacite_3, :_default
59
64
  end
60
65
 
61
- # Custom node to warn (but not blow up) if we read an XML `<resource/>` that's
66
+ # Custom node to allow (but ignore) if we read an XML `<resource/>` that's
62
67
  # missing its `<identifier/>`.
63
68
  class IdentifierNode < XML::Mapping::ObjectNode
64
69
  include EmptyNodeUtils
65
70
  def xml_to_obj(_obj, xml)
66
71
  return super if (element = has_element?(xml)) && not_empty(element)
67
- warn 'Identifier not found; add a valid Identifier to the Resource before saving'
68
72
  end
69
73
 
70
74
  private
71
75
 
72
- def has_element?(xml) # rubocop:disable Style/PredicateName
76
+ def has_element?(xml) # rubocop:disable Naming/PredicateName
73
77
  @path.first(xml)
74
78
  rescue XML::XXPathError
75
79
  false
@@ -1,12 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Datacite
2
4
  module Mapping
3
5
  # The name of this gem
4
- NAME = 'datacite-mapping'.freeze
6
+ NAME = 'datacite-mapping'
5
7
 
6
8
  # The version of this gem
7
- VERSION = '0.2.4'.freeze
9
+ VERSION = '0.4.1'
8
10
 
9
11
  # The copyright notice for this gem
10
- COPYRIGHT = 'Copyright (c) 2016 The Regents of the University of California'.freeze
12
+ COPYRIGHT = 'Copyright (c) 2022 The Regents of the University of California'
11
13
  end
12
14
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'xml/mapping_extensions'
2
4
 
3
5
  module Datacite
@@ -16,14 +18,16 @@ module Datacite
16
18
  self.value = value
17
19
  end
18
20
 
19
- def scheme=(v)
20
- fail ArgumentError, 'Scheme cannot be empty or nil' unless v && !v.empty?
21
- @scheme = v
21
+ def scheme=(new_value)
22
+ raise ArgumentError, 'Scheme cannot be empty or nil' unless new_value && !new_value.empty?
23
+
24
+ @scheme = new_value
22
25
  end
23
26
 
24
- def value=(v)
25
- fail ArgumentError, 'Value cannot be empty or nil' unless v && !v.empty?
26
- @value = v
27
+ def value=(new_value)
28
+ raise ArgumentError, 'Value cannot be empty or nil' unless new_value && !new_value.empty?
29
+
30
+ @value = new_value
27
31
  end
28
32
 
29
33
  root_element_name 'nameIdentifier'
@@ -31,9 +35,11 @@ module Datacite
31
35
  # @!attribute [rw] scheme
32
36
  # @return [String] the name identifier scheme. Cannot be nil.
33
37
  text_node :scheme, '@nameIdentifierScheme'
38
+
34
39
  # @!attribute [rw] scheme_uri
35
40
  # @return [URI, nil] the URI of the identifier scheme. Optional.
36
41
  uri_node :scheme_uri, '@schemeURI', default_value: nil
42
+
37
43
  # @!attribute [rw] value
38
44
  # @return [String] the identifier value. Cannot be nil.
39
45
  text_node :value, 'text()'
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'xml/mapping'
4
+ require 'datacite/mapping/read_only_nodes'
5
+
6
+ module Datacite
7
+ module Mapping
8
+
9
+ # Controlled vocabulary of name types
10
+ class NameType < TypesafeEnum::Base
11
+ # @!parse ORGANIZATIONAL = Organizational
12
+ new :ORGANIZATIONAL, 'Organizational'
13
+
14
+ # @!parse PERSONAL = Personal
15
+ new :PERSONAL, 'Personal'
16
+ end
17
+ end
18
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'xml/mapping_extensions'
2
4
 
3
5
  # TODO: port this to xml-mapping_extensions
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'xml/mapping_extensions'
4
+
5
+ module Datacite
6
+ module Mapping
7
+
8
+ # The type of the resource
9
+ class Publisher
10
+ include XML::Mapping
11
+
12
+ # Initializes a new {Publisher}
13
+ # @param language [String, nil] an IETF BCP 47, ISO 639-1 language code identifying the language.
14
+ # @param value [String] name of the publisher
15
+ def initialize(language: nil, value:)
16
+ self.language = language
17
+ self.value = value
18
+ end
19
+
20
+ def language=(value)
21
+ @language = value&.strip
22
+ end
23
+
24
+ def value=(value)
25
+ new_value = value&.strip
26
+ raise ArgumentError, 'Value cannot be empty or nil' unless new_value && !new_value.empty?
27
+
28
+ @value = new_value.strip
29
+ end
30
+
31
+ # @!attribute [rw] language
32
+ # @return [String] an IETF BCP 47, ISO 639-1 language code identifying the language.
33
+ text_node :language, '@xml:lang', default_value: nil
34
+
35
+ # @!attribute [rw] value
36
+ # @return [String] the title itself.
37
+ text_node :value, 'text()'
38
+
39
+ fallback_mapping :datacite_3, :_default
40
+ end
41
+ end
42
+ end