relaton-bib 2.0.0.pre.alpha.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -1
  3. data/.rubocop.yml +1 -1
  4. data/CLAUDE.md +96 -0
  5. data/Gemfile +1 -0
  6. data/README.adoc +14 -2
  7. data/grammars/basicdoc.rng +75 -45
  8. data/grammars/biblio-standoc.rng +37 -56
  9. data/grammars/biblio.rng +68 -36
  10. data/grammars/versions.json +25 -25
  11. data/lib/relaton/bib/converter/asciibib/to_asciibib.rb +663 -0
  12. data/lib/relaton/bib/converter/asciibib.rb +13 -0
  13. data/lib/relaton/bib/converter/bibtex/from_bibtex.rb +245 -0
  14. data/lib/relaton/bib/converter/bibtex/to_bibtex.rb +341 -0
  15. data/lib/relaton/bib/converter/bibtex.rb +23 -0
  16. data/lib/relaton/bib/converter/bibxml/from_rfcxml.rb +383 -0
  17. data/lib/relaton/bib/converter/bibxml/from_rfcxml_referencegroup.rb +71 -0
  18. data/lib/relaton/bib/{renderer/rfc.rb → converter/bibxml/to_rfcxml.rb} +100 -92
  19. data/lib/relaton/bib/converter/bibxml/to_rfcxml_referencegroup.rb +52 -0
  20. data/lib/relaton/bib/converter/bibxml.rb +51 -0
  21. data/lib/relaton/bib/hash_parser_v1.rb +121 -78
  22. data/lib/relaton/bib/item_data.rb +83 -22
  23. data/lib/relaton/bib/model/abstract.rb +16 -0
  24. data/lib/relaton/bib/model/date.rb +6 -4
  25. data/lib/relaton/bib/model/depiction.rb +2 -0
  26. data/lib/relaton/bib/model/ext.rb +0 -3
  27. data/lib/relaton/bib/model/formattedref.rb +43 -0
  28. data/lib/relaton/bib/model/ics.rb +9 -0
  29. data/lib/relaton/bib/model/item.rb +12 -4
  30. data/lib/relaton/bib/model/item_base.rb +17 -9
  31. data/lib/relaton/bib/model/keyword.rb +3 -3
  32. data/lib/relaton/bib/model/logo.rb +2 -0
  33. data/lib/relaton/bib/model/organization_type.rb +1 -1
  34. data/lib/relaton/bib/model/relation.rb +2 -2
  35. data/lib/relaton/bib/model/series.rb +5 -3
  36. data/lib/relaton/bib/model/subdivision.rb +2 -0
  37. data/lib/relaton/bib/model/title.rb +38 -0
  38. data/lib/relaton/bib/model/type/string_date.rb +48 -0
  39. data/lib/relaton/bib/model/validity.rb +3 -3
  40. data/lib/relaton/bib/namespace_helper.rb +21 -0
  41. data/lib/relaton/bib/version.rb +1 -1
  42. data/lib/relaton/bib.rb +5 -82
  43. data/relaton-bib.gemspec +5 -2
  44. metadata +63 -29
  45. data/lib/relaton/bib/model/editorial_group.rb +0 -14
  46. data/lib/relaton/bib/model/technical_committee.rb +0 -14
  47. data/lib/relaton/bib/model/workgroup.rb +0 -20
  48. data/lib/relaton/bib/parser/rfc_address.rb +0 -60
  49. data/lib/relaton/bib/parser/rfc_contacts.rb +0 -35
  50. data/lib/relaton/bib/parser/rfc_docidentifier.rb +0 -70
  51. data/lib/relaton/bib/parser/rfc_organization.rb +0 -31
  52. data/lib/relaton/bib/parser/rfc_person.rb +0 -42
  53. data/lib/relaton/bib/parser/rfc_reference.rb +0 -143
  54. data/lib/relaton/bib/parser/rfc_referencegroup.rb +0 -45
  55. data/lib/relaton/bib/parser/rfc_shared.rb +0 -23
  56. data/lib/relaton/bib/renderer/bibtex_builder.rb +0 -348
  57. data/lib/relaton/bibtex_parser.rb +0 -243
  58. data/lib/relaton/bibxml_parser.rb +0 -419
  59. data/lib/relaton/deep_dup.rb +0 -30
  60. data/lib/relaton/hit.rb +0 -52
  61. data/lib/relaton/hit_collection.rb +0 -105
  62. data/lib/relaton/workers_pool.rb +0 -43
  63. data/lib/relaton/xml_parser.rb +0 -716
@@ -4,20 +4,46 @@ module Relaton
4
4
  # It needed to keep data fot different types of representations (bibitem, bibdata ...).
5
5
  # @TODO: remove this class when Lutaml Model will support transformation between different types of models.
6
6
  class ItemData
7
- attr_accessor :id, :type, :schema_version, :fetched, :formattedref,
8
- :docidentifier, :docnumber, :date, :contributor, :edition,
9
- :version, :note, :language, :locale, :script, :status,
10
- :copyright, :series, :medium, :place, :price, :extent,
11
- :size, :accesslocation, :license, :classification,
12
- :keyword, :validity, :depiction, :ext # , :all_parts
13
-
14
- attr_writer :title, :abstract, :source, :relation
7
+ include Core::ArrayWrapper
8
+ include NamespaceHelper
9
+
10
+ ATTRIBUTES = %i[
11
+ type schema_version fetched formattedref docnumber edition status
12
+ medium size validity ext
13
+ ].freeze
14
+ COLLECTION_ATTRBUTES = %i[
15
+ date contributor version note language locale script
16
+ copyright series place price extent accesslocation license
17
+ classification keyword depiction
18
+ ].freeze
19
+ COLLECTION_WRITE_ONLY_ATTRIBUTES = %i[title abstract source relation].freeze
20
+
21
+ ATTRIBUTES.each { |attr| attr_accessor attr }
22
+ COLLECTION_ATTRBUTES.each { |attr| attr_accessor attr }
23
+ COLLECTION_WRITE_ONLY_ATTRIBUTES.each { |attr| attr_writer attr }
24
+
25
+ attr_reader :id, :docidentifier
15
26
 
16
27
  def initialize(**args)
17
- args.each do |k, v|
18
- instance_variable_set("@#{k}", v) if respond_to?("#{k}=")
28
+ ATTRIBUTES.each { |attr| instance_variable_set("@#{attr}", args[attr]) }
29
+
30
+ (COLLECTION_ATTRBUTES + COLLECTION_WRITE_ONLY_ATTRIBUTES).each do |attr|
31
+ instance_variable_set("@#{attr}", args[attr] || [])
19
32
  end
33
+
34
+ @docidentifier = args[:docidentifier] || []
20
35
  self.schema_version = schema
36
+ @id = args[:id]
37
+ create_id
38
+ end
39
+
40
+ def id=(value)
41
+ @id = value if value
42
+ end
43
+
44
+ def docidentifier=(value)
45
+ @docidentifier = value || []
46
+ create_id
21
47
  end
22
48
 
23
49
  #
@@ -65,7 +91,13 @@ module Relaton
65
91
  end
66
92
 
67
93
  def create_id(without_date: false)
68
- raise NotImplementedError, "`create_id` method not implemented in #{self.class}"
94
+ return id if id && !id.empty?
95
+
96
+ docid = find_primary_docid
97
+ return unless docid
98
+
99
+ pubid = without_date ? docid.content.sub(/:\d{4}$/, "") : docid.content
100
+ self.id = pubid.to_s.gsub(/\W+/, "")
69
101
  end
70
102
 
71
103
  def title(lang = nil)
@@ -94,36 +126,50 @@ module Relaton
94
126
 
95
127
  def to_xml(bibdata: false, **opts)
96
128
  add_notes opts[:note] do
97
- bibdata ? Bibdata.to_xml(self) : Bibitem.to_xml(self)
129
+ bibdata ? namespace::Bibdata.to_xml(self) : namespace::Bibitem.to_xml(self)
98
130
  end
99
131
  end
100
132
 
101
133
  def to_yaml(**opts)
102
134
  add_notes opts[:note] do
103
- Item.to_yaml(self)
135
+ namespace::Item.to_yaml(self)
104
136
  end
105
137
  end
106
138
 
107
139
  def to_json(**opts)
108
140
  add_notes opts[:note] do
109
- Item.to_json(self)
141
+ namespace::Item.to_json(self)
142
+ end
143
+ end
144
+
145
+ def to_h(**opts)
146
+ add_notes opts[:note] do
147
+ namespace::Item.to_hash(self)
110
148
  end
111
149
  end
112
150
 
113
151
  def to_bibtex
114
- Renderer::BibtexBuilder.build(self).to_s
152
+ Converter::Bibtex.from_item(self).to_s
153
+ end
154
+
155
+ def to_asciibib
156
+ Converter::Asciibib.from_item(self)
115
157
  end
116
158
 
117
159
  def to_rfcxml
118
- Renderer::Rfc.transform(self).to_xml
160
+ Converter::BibXml.from_item(self).to_xml
119
161
  end
120
162
 
121
163
  def deep_clone
122
- Item.from_yaml Item.to_yaml(self)
164
+ namespace::Item.from_yaml namespace::Item.to_yaml(self)
123
165
  end
124
166
 
125
167
  def create_relation(**args)
126
- Relation.new(**args)
168
+ if defined?(namespace::Relation)
169
+ namespace::Relation.new(**args)
170
+ else
171
+ Relation.new(**args)
172
+ end
127
173
  end
128
174
 
129
175
  def delete_title_part!
@@ -145,22 +191,37 @@ module Relaton
145
191
 
146
192
  # some flavor modles have structuredidentifier as not an array
147
193
  # so we need to make it an array use common method
148
- Relaton.array(ext.structuredidentifier).each(&:to_all_parts!)
194
+ array(ext.structuredidentifier).each(&:to_all_parts!)
149
195
  end
150
196
 
151
197
  def ext_remove_date
152
198
  return unless ext
153
199
 
154
- Relaton.array(ext.structuredidentifier).each(&:remove_date!)
200
+ array(ext.structuredidentifier).each(&:remove_date!)
155
201
  end
156
202
 
157
203
  private
158
204
 
205
+ def find_primary_docid
206
+ prim_docids = docidentifier.select(&:primary)
207
+ case prim_docids.size
208
+ when 0 then find_primary_or_english_docid(docidentifier)
209
+ when 1 then prim_docids.first
210
+ else find_primary_or_english_docid(prim_docids)
211
+ end
212
+ end
213
+
214
+ def find_primary_or_english_docid(docids) # rubocop:disable Metrics/CyclomaticComplexity
215
+ docids.reject(&:language).first ||
216
+ docids.find { |i| i.language&.casecmp("en")&.zero? } ||
217
+ docids.first
218
+ end
219
+
159
220
  def add_notes(notes)
160
221
  self.note ||= []
161
- Relaton.array(notes).each { |nt| note << Bib::Note.new(**nt) }
222
+ array(notes).each { |nt| note << Bib::Note.new(**nt) }
162
223
  result = yield
163
- Relaton.array(notes).each { note.pop }
224
+ array(notes).each { note.pop }
164
225
  result
165
226
  end
166
227
  end
@@ -0,0 +1,16 @@
1
+ module Relaton
2
+ module Bib
3
+ class Abstract < LocalizedMarkedUpString
4
+ attribute :format, :string
5
+
6
+ xml do
7
+ root "abstract"
8
+ map_attribute "format", to: :format
9
+ end
10
+
11
+ key_value do
12
+ map "format", to: :format
13
+ end
14
+ end
15
+ end
16
+ end
@@ -1,3 +1,5 @@
1
+ require_relative "type/string_date"
2
+
1
3
  module Relaton
2
4
  module Bib
3
5
  class Date < Lutaml::Model::Serializable
@@ -9,11 +11,11 @@ module Relaton
9
11
  attribute :text, :string
10
12
  choice(min: 1, max: 2) do
11
13
  choice(min: 1, max: 2) do
12
- attribute :from, :string
13
- attribute :to, :string
14
+ attribute :from, StringDate
15
+ attribute :to, StringDate
14
16
  end
15
- # `on` is reserved word in YAML, so use `at` instead to avoid remapping key-value formats
16
- attribute :at, :string
17
+ # `on` is reserved word in YAML, so we use `at` to avoid remapping key-value formats
18
+ attribute :at, StringDate
17
19
  end
18
20
 
19
21
  xml do
@@ -2,11 +2,13 @@ module Relaton
2
2
  module Bib
3
3
  class Depiction < Lutaml::Model::Serializable
4
4
  attribute :scope, :string
5
+ attribute :type, :string
5
6
  attribute :image, Image, collection: true, initialize_empty: true
6
7
 
7
8
  xml do
8
9
  root "depiction"
9
10
  map_attribute "scope", to: :scope
11
+ map_attribute "type", to: :type
10
12
  map_element "image", to: :image
11
13
  end
12
14
  end
@@ -1,5 +1,4 @@
1
1
  require_relative "doctype"
2
- require_relative "editorial_group"
3
2
  require_relative "ics"
4
3
  require_relative "structured_identifier"
5
4
 
@@ -10,7 +9,6 @@ module Relaton
10
9
  attribute :doctype, Doctype
11
10
  attribute :subdoctype, :string
12
11
  attribute :flavor, :string
13
- attribute :editorialgroup, EditorialGroup
14
12
  attribute :ics, ICS, collection: true, initialize_empty: true
15
13
  attribute :structuredidentifier, StructuredIdentifier, collection: true, initialize_empty: true
16
14
 
@@ -20,7 +18,6 @@ module Relaton
20
18
  map_element "doctype", to: :doctype
21
19
  map_element "subdoctype", to: :subdoctype
22
20
  map_element "flavor", to: :flavor
23
- map_element "editorialgroup", to: :editorialgroup
24
21
  map_element "ics", to: :ics
25
22
  map_element "structuredidentifier", to: :structuredidentifier
26
23
  end
@@ -0,0 +1,43 @@
1
+ module Relaton
2
+ module Bib
3
+ class Formattedref < LocalizedMarkedUpString
4
+ attribute :format, :string
5
+
6
+ xml do
7
+ root "formattedref"
8
+ map_attribute "format", to: :format
9
+ end
10
+
11
+ key_value do
12
+ map "format", to: :format
13
+ end
14
+
15
+ # Handle plain string input from YAML/JSON deserialization
16
+ def self.from_yaml(value)
17
+ return new(content: value) if value.is_a?(String)
18
+
19
+ super
20
+ end
21
+
22
+ def self.from_json(value)
23
+ return new(content: value) if value.is_a?(String)
24
+
25
+ super
26
+ end
27
+
28
+ # Serialize as plain string when only content is present
29
+ def self.as(format, instance, options = {})
30
+ return instance.content if simple_content?(instance, format)
31
+
32
+ super
33
+ end
34
+
35
+ def self.simple_content?(instance, format)
36
+ return false if format == :xml
37
+
38
+ instance.format.nil? && instance.language.nil? &&
39
+ instance.script.nil? && instance.locale.nil?
40
+ end
41
+ end
42
+ end
43
+ end
@@ -1,3 +1,5 @@
1
+ require "isoics"
2
+
1
3
  module Relaton
2
4
  module Bib
3
5
  class ICS < Lutaml::Model::Serializable
@@ -9,6 +11,13 @@ module Relaton
9
11
  map_element "code", to: :code
10
12
  map_element "text", to: :text
11
13
  end
14
+
15
+ def text
16
+ val = @text
17
+ return val if val && !val.empty?
18
+
19
+ Isoics.fetch(code)&.description if code
20
+ end
12
21
  end
13
22
  end
14
23
  end
@@ -2,6 +2,8 @@ require "lutaml/model"
2
2
  require "lutaml/model/xml_adapter/nokogiri_adapter"
3
3
  require_relative "localized_string_attrs"
4
4
  require_relative "localized_string"
5
+ require_relative "formattedref"
6
+ require_relative "abstract"
5
7
  require_relative "date"
6
8
  require_relative "locality"
7
9
  require_relative "locality_stack"
@@ -46,6 +48,8 @@ module Relaton
46
48
 
47
49
  # Item class repesents bibliographic item metadata.
48
50
  class Item < Lutaml::Model::Serializable
51
+ attr_accessor :type # in some cases mehod type is unavailable
52
+
49
53
  model ItemData
50
54
 
51
55
  attribute :id, :string
@@ -55,9 +59,9 @@ module Relaton
55
59
  graphic_work music patent inbook incollection inproceedings journal website
56
60
  webresource dataset archival social_media alert message convesation misc
57
61
  ]
58
- attribute :schema_version, :string
62
+ attribute :schema_version, method: :get_schema_version
59
63
  attribute :fetched, :date
60
- attribute :formattedref, :string, raw: true
64
+ attribute :formattedref, Formattedref
61
65
  attribute :title, Title, collection: true, initialize_empty: true
62
66
  attribute :source, Uri, collection: true, initialize_empty: true
63
67
  attribute :docidentifier, Docidentifier, collection: true, initialize_empty: true
@@ -70,7 +74,7 @@ module Relaton
70
74
  attribute :language, :string, collection: true, initialize_empty: true
71
75
  attribute :locale, :string, collection: true, initialize_empty: true
72
76
  attribute :script, :string, collection: true, initialize_empty: true
73
- attribute :abstract, LocalizedMarkedUpString, collection: true, initialize_empty: true
77
+ attribute :abstract, Abstract, collection: true, initialize_empty: true
74
78
  attribute :status, Status
75
79
  attribute :copyright, Copyright, collection: true, initialize_empty: true
76
80
  attribute :relation, Relation, collection: true, initialize_empty: true
@@ -85,7 +89,7 @@ module Relaton
85
89
  attribute :classification, Docidentifier, collection: true, initialize_empty: true
86
90
  attribute :keyword, Keyword, collection: true, initialize_empty: true
87
91
  attribute :validity, Validity
88
- attribute :depiction, Depiction
92
+ attribute :depiction, Depiction, collection: true, initialize_empty: true
89
93
  attribute :ext, Ext
90
94
 
91
95
  xml do # rubocop:disable Metrics/BlockLength
@@ -124,6 +128,10 @@ module Relaton
124
128
  map_element "depiction", to: :depiction
125
129
  map_element "ext", to: :ext
126
130
  end
131
+
132
+ def get_schema_version
133
+ Relaton.schema_versions["relaton-models"]
134
+ end
127
135
  end
128
136
  end
129
137
  end
@@ -1,19 +1,27 @@
1
1
  module Relaton
2
2
  module Bib
3
+ # Module to remove id, schema-version, fetched & ext attributes from Item subclasses.
4
+ # Used for bibitem/relation instances that don't need these attributes.
5
+ module ItemBaseAttributes
6
+ def self.included(base)
7
+ # we don't need id, schema-version & fetched attributes in relation/bibitem
8
+ base.mappings[:xml].instance_variable_get(:@attributes).delete("id")
9
+ base.mappings[:xml].instance_variable_get(:@attributes).delete("schema-version")
10
+ base.mappings[:xml].instance_variable_get(:@elements).delete("fetched")
11
+ base.mappings[:xml].instance_variable_get(:@elements).delete("ext")
12
+ base.attributes.delete :id
13
+ base.attributes.delete :schema_version
14
+ base.attributes.delete :fetched
15
+ base.attributes.delete :ext
16
+ end
17
+ end
18
+
3
19
  # The class is for relaton bibitem instances.
4
20
  # The in relaton bibitem instances dosn't have schema-version & fetched attributes.
5
21
  class ItemBase < Item
6
22
  model ItemData
7
23
 
8
- # we don't need id, schema-version & fetched attributes in reation/bibitem
9
- mappings[:xml].instance_variable_get(:@attributes).delete("id")
10
- mappings[:xml].instance_variable_get(:@attributes).delete("schema-version")
11
- mappings[:xml].instance_variable_get(:@elements).delete("fetched")
12
- mappings[:xml].instance_variable_get(:@elements).delete("ext")
13
- attributes.delete :id
14
- attributes.delete :schema_version
15
- attributes.delete :fetched
16
- attributes.delete :ext
24
+ include ItemBaseAttributes
17
25
  end
18
26
  end
19
27
  end
@@ -15,9 +15,9 @@ module Relaton
15
15
  end
16
16
  end
17
17
 
18
- attribute :vocab, LocalizedString, collection: true, initialize_empty: true
19
- attribute :taxon, LocalizedString, collection: (1..), initialize_empty: true
20
- attribute :vocabid, Vocabid
18
+ attribute :vocab, LocalizedString
19
+ attribute :taxon, LocalizedString, collection: true, initialize_empty: true
20
+ attribute :vocabid, Vocabid, collection: true, initialize_empty: true
21
21
 
22
22
  xml do
23
23
  root "keyword"
@@ -1,10 +1,12 @@
1
1
  module Relaton
2
2
  module Bib
3
3
  class Logo < Lutaml::Model::Serializable
4
+ attribute :type, :string
4
5
  attribute :image, Image
5
6
 
6
7
  xml do
7
8
  root "logo"
9
+ map_attribute "type", to: :type
8
10
  map_element "image", to: :image
9
11
  end
10
12
  end
@@ -22,7 +22,7 @@ module Relaton
22
22
  attribute :subdivision, Subdivision, collection: true, initialize_empty: true
23
23
  attribute :abbreviation, LocalizedString
24
24
  attribute :identifier, Identifier, collection: true, initialize_empty: true
25
- attribute :logo, Logo
25
+ attribute :logo, Logo, collection: true, initialize_empty: true
26
26
 
27
27
  xml do
28
28
  map_element "name", to: :name
@@ -9,8 +9,8 @@ module Relaton
9
9
  hasManifestation reproductionOf hasReproduction reprintOf hasReprint
10
10
  expressionOf hasExpression translatedFrom hasTranslation arrangementOf
11
11
  hasArrangement abridgementOf hasAbridgement annotationOf hasAnnotation
12
- draftOfhasDraft preliminaryDraftOf hasPreliminaryDraft revisionDraftOf
13
- hasRevisionDraft editionOf hasEdition updates updatedBy derivedFrom
12
+ draftOf hasDraft predecessorDraftOf hasPredecessorDraft successorDraftOf
13
+ hasSuccessorDraft editionOf hasEdition updates updatedBy derivedFrom
14
14
  derives describes describedBy catalogues cataloguedBy hasSuccessor
15
15
  successorOf adaptedFrom hasAdaptation adoptedFrom adoptedAs reviewOf
16
16
  hasReview commentaryOf hasCommentary related hasComplement complementOf
@@ -1,14 +1,16 @@
1
+ require_relative "type/string_date"
2
+
1
3
  module Relaton
2
4
  module Bib
3
5
  class Series < Lutaml::Model::Serializable
4
6
  attribute :type, :string, values: %w[main alt]
5
- attribute :formattedref, :string, raw: true
7
+ attribute :formattedref, Formattedref
6
8
  attribute :title, Title, collection: (1..)
7
9
  attribute :place, Place
8
10
  attribute :organization, :string
9
11
  attribute :abbreviation, LocalizedString
10
- attribute :from, :date
11
- attribute :to, :date
12
+ attribute :from, StringDate
13
+ attribute :to, StringDate
12
14
  attribute :number, :string
13
15
  attribute :partnumber, :string
14
16
  attribute :run, :string
@@ -4,10 +4,12 @@ module Relaton
4
4
  include OrganizationType
5
5
 
6
6
  attribute :type, :string
7
+ attribute :subtype, :string
7
8
 
8
9
  xml do
9
10
  root "subdivision"
10
11
  map_attribute "type", to: :type
12
+ map_attribute "subtype", to: :subtype
11
13
  end
12
14
  end
13
15
  end
@@ -13,6 +13,44 @@ module Relaton
13
13
  map "type", to: :type
14
14
  map "format", to: :format
15
15
  end
16
+
17
+ class << self
18
+ def from_string(title, lang = nil, script = nil)
19
+ types = %w[title-intro title-main title-part]
20
+ ttls = split_title(title)
21
+ tts = ttls.map.with_index do |p, i|
22
+ next unless p
23
+
24
+ new type: types[i], content: p, language: lang, script: script
25
+ end.compact
26
+ tts << new(type: "main", content: ttls.compact.join(" - "), language: lang, script: script)
27
+ tts
28
+ end
29
+
30
+ private
31
+
32
+ # @param title [String]
33
+ # @return [Array<String, nil>]
34
+ def split_title(title)
35
+ ttls = title.sub(/\w\.Imp\s?\d+\u00A0:\u00A0/, "").split " - "
36
+ case ttls.size
37
+ when 0, 1 then [nil, ttls.first.to_s, nil]
38
+ else intro_or_part ttls
39
+ end
40
+ end
41
+
42
+ # @param ttls [Array<String>]
43
+ # @return [Array<String, nil>]
44
+ def intro_or_part(ttls)
45
+ if /^(Part|Partie) \d+:/.match? ttls[1]
46
+ [nil, ttls[0], ttls[1..].join(" -- ")]
47
+ else
48
+ parts = ttls.slice(2..-1)
49
+ part = parts.join " -- " if parts.any?
50
+ [ttls[0], ttls[1], part]
51
+ end
52
+ end
53
+ end
16
54
  end
17
55
  end
18
56
  end
@@ -0,0 +1,48 @@
1
+ require "forwardable"
2
+
3
+ module Relaton
4
+ module Bib
5
+ class StringDate < Lutaml::Model::Type::Value
6
+ class Value
7
+ include Comparable
8
+ extend Forwardable
9
+ extend Core::DateParser
10
+ include Core::DateParser
11
+
12
+ def_delegators :@value, :split, :to_s
13
+
14
+ def initialize(value)
15
+ @value = value
16
+ end
17
+
18
+ def self.parse_date(date)
19
+ value = super
20
+ new value if value
21
+ end
22
+
23
+ def <=>(other)
24
+ return nil unless other.is_a?(Value)
25
+
26
+ @value <=> other.to_s
27
+ end
28
+
29
+ def to_date
30
+ parse_date(@value, str: false)
31
+ rescue ArgumentError
32
+ nil
33
+ end
34
+ end
35
+
36
+ def self.cast(value)
37
+ case value
38
+ when Value then value
39
+ when String then Value.parse_date(value)
40
+ end
41
+ end
42
+
43
+ def to_yaml
44
+ value.to_s
45
+ end
46
+ end
47
+ end
48
+ end
@@ -1,9 +1,9 @@
1
1
  module Relaton
2
2
  module Bib
3
3
  class Validity < Lutaml::Model::Serializable
4
- attribute :begins, :date
5
- attribute :ends, :date
6
- attribute :revision, :date
4
+ attribute :begins, :date_time
5
+ attribute :ends, :date_time
6
+ attribute :revision, :date_time
7
7
 
8
8
  xml do
9
9
  root "validity"
@@ -0,0 +1,21 @@
1
+ module Relaton
2
+ module Bib
3
+ module NamespaceHelper
4
+ def self.included(base)
5
+ base.extend(ClassMethods)
6
+ end
7
+
8
+ module ClassMethods
9
+ def namespace
10
+ @namespace = Object.const_get name.split("::")[0..1].join("::")
11
+ end
12
+ end
13
+
14
+ private
15
+
16
+ def namespace
17
+ self.class.namespace
18
+ end
19
+ end
20
+ end
21
+ end
@@ -1,5 +1,5 @@
1
1
  module Relaton
2
2
  module Bib
3
- VERSION = "2.0.0-alpha.1".freeze
3
+ VERSION = "2.0.0".freeze
4
4
  end
5
5
  end