relaton-bib 0.9.2 → 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -167,8 +167,12 @@ module RelatonBib
167
167
  #
168
168
  # @param relation [Array<Hash>]
169
169
  # @option relation [String] :type
170
- # @option relation [RelatonBib::BibliographicItem, RelatonIso::IsoBibliographicItem] :bibitem
171
- # @option relation [Array<RelatonBib::BibItemLocality>] :bib_locality
170
+ # @option relation [RelatonBib::BibliographicItem,
171
+ # RelatonIso::IsoBibliographicItem] :bibitem
172
+ # @option relation [Array<RelatonBib::Locality,
173
+ # RelatonBib::LocalityStack>] :locality
174
+ # @option relation [Array<RelatonBib::SourceLocality,
175
+ # RelatonBib::SourceLocalityStack>] :source_locality
172
176
  #
173
177
  # @param link [Array<Hash, RelatonBib::TypedUri>]
174
178
  # @option link [String] :type
@@ -147,17 +147,16 @@ module RelatonBib
147
147
  # @param bibtex [BibTeX::Entry]
148
148
  # @return [Array<RelatonBib::BiblioNote>]
149
149
  def fetch_note(bibtex)
150
- note = []
151
- note << BiblioNote.new(type: "annote", content: bibtex.annote.to_s) if bibtex["annote"]
152
-
153
- if bibtex["howpublished"]
154
- note << BiblioNote.new(type: "howpublished", content: bibtex.howpublished.to_s)
150
+ bibtex.select do |k, _v|
151
+ %i[annote howpublished comment note content].include? k
152
+ end.reduce([]) do |mem, note|
153
+ type = case note[0]
154
+ when :note then nil
155
+ when :content then "tableOfContents"
156
+ else note[0].to_s
157
+ end
158
+ mem << BiblioNote.new(type: type, content: note[1].to_s)
155
159
  end
156
-
157
- note << BiblioNote.new(type: "comment", content: bibtex.comment.to_s) if bibtex["comment"]
158
- note << BiblioNote.new(content: bibtex.note.to_s) if bibtex["note"]
159
- note << BiblioNote.new(type: "tableOfContents", content: bibtex["content"]) if bibtex["content"]
160
- note
161
160
  end
162
161
 
163
162
  # @param bibtex [BibTeX::Entry]
@@ -172,16 +171,19 @@ module RelatonBib
172
171
  # @param bibtex [BibTeX::Entry]
173
172
  # @return [Array<RelatonBib::BibItemLocality>]
174
173
  def fetch_extent(bibtex)
175
- extent = []
176
- extent << BibItemLocality.new("chapter", bibtex.chapter.to_s) if bibtex["chapter"]
177
-
178
- if bibtex["pages"]
179
- from, to = bibtex.pages.to_s.split "-"
180
- extent << BibItemLocality.new("page", from, to)
174
+ bibtex.select do |k, _v|
175
+ %i[chapter pages volume].include? k
176
+ end.reduce([]) do |mem, loc|
177
+ if loc[0] == :pages
178
+ type = "page"
179
+ from, to = loc[1].to_s.split "-"
180
+ else
181
+ type = loc[0].to_s
182
+ from = loc[1].to_s
183
+ to = nil
184
+ end
185
+ mem << BibItemLocality.new(type, from, to)
181
186
  end
182
-
183
- extent << BibItemLocality.new("volume", bibtex.volume.to_s) if bibtex["volume"]
184
- extent
185
187
  end
186
188
 
187
189
  # @param bibtex [BibTeX::Entry]
@@ -192,7 +194,7 @@ module RelatonBib
192
194
  series << Series.new(
193
195
  type: "journal",
194
196
  title: TypedTitleString.new(content: bibtex.journal.to_s),
195
- number: bibtex["number"]&.to_s
197
+ number: bibtex["number"]&.to_s,
196
198
  )
197
199
  end
198
200
 
@@ -1,59 +1,83 @@
1
1
  module RelatonBib
2
- # module DocumentRelationType
3
- # PARENT = 'parent'
4
- # CHILD = 'child'
5
- # OBSOLETES = 'obsoletes'
6
- # UPDATES = 'updates'
7
- # COMPLEMENTS = 'complements'
8
- # DERIVED_FORM = 'derivedForm'
9
- # ADOPTED_FORM = 'adoptedForm'
10
- # EQUIVALENT = 'equivalent'
11
- # IDENTICAL = 'identical'
12
- # NONEQUIVALENT = 'nonequivalent'
13
- # end
14
-
15
2
  # Documett relation
16
3
  class DocumentRelation
17
4
  include RelatonBib
18
5
 
6
+ TYPES = %w[
7
+ includes includedIn hasPart partOf merges mergedInto splits splitInto
8
+ instance hasInstance exemplarOf hasExemplar manifestationOf
9
+ hasManifestation reproductionOf hasReproduction reprintOf hasReprint
10
+ expressionOf hasExpression translatedFrom hasTranslation arrangementOf
11
+ hasArrangement abridgementOf hasAbridgement annotationOf hasAnnotation
12
+ draftOf hasDraft editionOf hasEdition updates updatedBy derivedFrom
13
+ derives describes describedBy catalogues cataloguedBy hasSuccessor
14
+ successorOf adaptedFrom hasAdaptation adoptedFrom adoptedAs reviewOf
15
+ hasReview commentaryOf hasCommentary related complements complementOf
16
+ obsoletes obsoletedBy cited isCitedIn
17
+ ].freeze
18
+
19
19
  # @return [String]
20
20
  attr_reader :type
21
21
 
22
+ # @return [RelatonBib::FormattedString, NilClass]
23
+ attr_reader :description
24
+
22
25
  # @return [String]
23
26
  # attr_reader :identifier, :url
24
27
 
25
28
  # @return [RelatonBib::BibliographicItem]
26
29
  attr_reader :bibitem
27
30
 
28
- # @return [Array<RelatonBib::BibItemLocality>]
29
- attr_reader :bib_locality
31
+ # @return [Array<RelatonBib::Locality, RelatonBib::LocalityStack>]
32
+ attr_reader :locality
33
+
34
+ # @return [Array<RelatonBib::SourceLocality,
35
+ # RelatonBib::SourceLocalityStack>]
36
+ attr_reader :source_locality
30
37
 
31
38
  # @param type [String]
32
- # @param bibitem [RelatonBib::BibliographicItem, RelatonIso::IsoBibliographicItem]
33
- # @param bib_locality [Array<RelatonBib::BibItemLocality>]
34
- def initialize(type:, bibitem:, bib_locality: [])
39
+ # @parma description [RelatonBib::FormattedString, NilClass]
40
+ # @param bibitem [RelatonBib::BibliographicItem,
41
+ # RelatonIso::IsoBibliographicItem]
42
+ # @param locality [Array<RelatonBib::Locality, RelatonBib::LocalityStack>]
43
+ # @param source_locality [Array<RelatonBib::SourceLocality,
44
+ # RelatonBib::SourceLocalityStack>]
45
+ def initialize(type:, description: nil, bibitem:, locality: [],
46
+ source_locality: [])
35
47
  type = "obsoletes" if type == "Now withdrawn"
36
- @type = type
37
- @bib_locality = bib_locality
38
- @bibitem = bibitem
48
+ unless TYPES.include? type
49
+ warn "[relaton-bib] WARNING: invalid relation type: #{type}"
50
+ end
51
+ @type = type
52
+ @description = description
53
+ @locality = locality
54
+ @source_locality = source_locality
55
+ @bibitem = bibitem
39
56
  end
40
57
 
58
+ # rubocop:disable Metrics/AbcSize
59
+
41
60
  # @param builder [Nokogiri::XML::Builder]
42
61
  def to_xml(builder, **opts)
43
62
  opts.delete :bibdata
44
63
  opts.delete :note
45
64
  builder.relation(type: type) do
65
+ builder.description { description.to_xml builder } if description
46
66
  bibitem.to_xml(builder, **opts.merge(embedded: true))
47
- bib_locality.each do |l|
48
- builder.locality { l.to_xml builder }
49
- end
67
+ locality.each { |l| l.to_xml builder }
68
+ source_locality.each { |l| l.to_xml builder }
50
69
  end
51
70
  end
71
+ # rubocop:enable Metrics/AbcSize
52
72
 
53
73
  # @return [Hash]
54
74
  def to_hash
55
75
  hash = { "type" => type, "bibitem" => bibitem.to_hash }
56
- hash["bib_locality"] = single_element_array(bib_locality) if bib_locality&.any?
76
+ hash["description"] = description.to_hash if description
77
+ hash["locality"] = single_element_array(locality) if locality&.any?
78
+ if source_locality&.any?
79
+ hash["source_locality"] = single_element_array(source_locality)
80
+ end
57
81
  hash
58
82
  end
59
83
  end
@@ -1,21 +1,34 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "forwardable"
4
+
3
5
  module RelatonBib
4
6
  # Document relation collection
5
- class DocRelationCollection < Array
7
+ class DocRelationCollection
8
+ extend Forwardable
9
+
10
+ def_delegators :@array, :<<, :[], :first, :last, :empty?, :any?, :size,
11
+ :each, :detect, :map, :length
12
+
6
13
  # @param relation [Array<RelatonBib::DocumentRelation, Hash>]
7
14
  # @option relation [String] :type
8
15
  # @option relation [String] :identifier
9
16
  # @option relation [String, NIllClass] :url (nil)
10
- # @option relation [Array<RelatonBib::BibItemLocality>] :bib_locality
17
+ # @option relation [Array<RelatonBib::Locality,
18
+ # RelatonBib::LocalityStack>] :locality
19
+ # @option relation [Array<RelatonBib::SourceLocality,
20
+ # RelatonBib::SourceLocalityStack>] :source_locality
11
21
  # @option relation [RelatonBib::BibliographicItem, NillClass] :bibitem (nil)
12
22
  def initialize(relation)
13
- super relation.map { |r| r.is_a?(Hash) ? DocumentRelation.new(r) : r }
23
+ @array = relation.map { |r| r.is_a?(Hash) ? DocumentRelation.new(r) : r }
14
24
  end
15
25
 
16
- # @return [Array<RelatonBib::DocumentRelation>]
26
+ # @todo We don't have replace type anymore. Suppose we should update this
27
+ # method or delete it.
28
+ #
29
+ # @return [RelatonBib::DocRelationCollection]
17
30
  def replaces
18
- select { |r| r.type == "replace" }
31
+ DocRelationCollection.new(@array.select { |r| r.type == "replace" })
19
32
  end
20
33
  end
21
34
  end
@@ -14,12 +14,12 @@ module RelatonBib
14
14
  # @return [String, NilClass]
15
15
  attr_reader :iteration
16
16
 
17
- # @param stage [String]
18
- # @param substage [String, NilClass]
17
+ # @param stage [String, Hash, RelatonBib::DocumentStatus::Stage]
18
+ # @param substage [String, Hash, NilClass, RelatonBib::DocumentStatus::Stage]
19
19
  # @param iteration [String, NilClass]
20
20
  def initialize(stage:, substage: nil, iteration: nil)
21
- @stage = stage
22
- @substage = substage
21
+ @stage = stage_new stage
22
+ @substage = stage_new substage
23
23
  @iteration = iteration
24
24
  end
25
25
 
@@ -27,18 +27,56 @@ module RelatonBib
27
27
  def to_xml(builder)
28
28
  builder.status do
29
29
  # FormattedString.instance_method(:to_xml).bind(status).call builder
30
- builder.stage stage
31
- builder.substage substage if substage
30
+ builder.stage { |b| stage.to_xml b }
31
+ builder.substage { |b| substage.to_xml b } if substage
32
32
  builder.iteration iteration unless iteration.to_s.empty?
33
33
  end
34
34
  end
35
35
 
36
36
  # @return [Hash]
37
37
  def to_hash
38
- hash = { "stage" => stage }
39
- hash["substage"] = substage if substage
38
+ hash = { "stage" => stage.to_hash }
39
+ hash["substage"] = substage.to_hash if substage
40
40
  hash["iteration"] = iteration if iteration
41
41
  hash
42
42
  end
43
+
44
+ private
45
+
46
+ # @param stg [RelatonBib::DocumentStatus::Stage, Hash, String, NilClass]
47
+ def stage_new(stg)
48
+ if stg.is_a?(Stage) then stg
49
+ elsif stg.is_a?(Hash) then Stage.new(stg)
50
+ elsif stg.is_a?(String) then Stage.new(value: stg)
51
+ end
52
+ end
53
+
54
+ class Stage
55
+ # @return [String]
56
+ attr_reader :value
57
+
58
+ # @return [String, NilClass]
59
+ attr_reader :abbreviation
60
+
61
+ # @parma value [String]
62
+ # @param abbreviation [String, NilClass]
63
+ def initialize(value:, abbreviation: nil)
64
+ @value = value
65
+ @abbreviation = abbreviation
66
+ end
67
+
68
+ # @param [Nokogiri::XML::Builder]
69
+ def to_xml(builder)
70
+ builder.parent[:abbreviation] = abbreviation if abbreviation
71
+ builder.text value
72
+ end
73
+
74
+ # @return [Hash]
75
+ def to_hash
76
+ hash = { "value" => value }
77
+ hash["abbreviation"] = abbreviation if abbreviation
78
+ hash
79
+ end
80
+ end
43
81
  end
44
82
  end
@@ -12,7 +12,7 @@ module RelatonBib
12
12
  # @return [String]
13
13
  attr_reader :format
14
14
 
15
- # @param content [String]
15
+ # @param content [String, Array<RelatonBib::LocalizedString>]
16
16
  # @param language [String, NilClass] language code Iso639
17
17
  # @param script [String, NilClass] script code Iso15924
18
18
  # @param format [String] the content type
@@ -36,8 +36,8 @@ module RelatonBib
36
36
  hash = super
37
37
  return hash unless format
38
38
 
39
- hash = { "content" => hash } if hash.is_a? String
40
- hash["format"] = format if format
39
+ hash = { "content" => hash } unless hash.is_a? Hash
40
+ hash["format"] = format
41
41
  hash
42
42
  end
43
43
  end
@@ -1,6 +1,11 @@
1
1
  module RelatonBib
2
2
  class HashConverter
3
3
  class << self
4
+ # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
5
+
6
+ # @param args [Hash]
7
+ # @param neated [TrueClas, FalseClass] default true
8
+ # @return [Hash]
4
9
  def hash_to_bib(args, nested = false)
5
10
  return nil unless args.is_a?(Hash)
6
11
 
@@ -30,6 +35,7 @@ module RelatonBib
30
35
  ret[:license] = array(ret[:license])
31
36
  ret
32
37
  end
38
+ # rubocop:enable Metrics/MethodLength, Metrics/AbcSize
33
39
 
34
40
  def timestamp_hash(ret)
35
41
  ret[:fetched] ||= Date.today.to_s
@@ -151,12 +157,21 @@ module RelatonBib
151
157
 
152
158
  def docstatus_hash_to_bib(ret)
153
159
  ret[:docstatus] && ret[:docstatus] = DocumentStatus.new(
154
- stage: ret[:docstatus][:stage],
155
- substage: ret[:docstatus][:substage],
160
+ stage: stage(ret[:docstatus][:stage]),
161
+ substage: stage(ret[:docstatus][:substage]),
156
162
  iteration: ret[:docstatus][:iteration],
157
163
  )
158
164
  end
159
165
 
166
+ # @param stg [Hash]
167
+ # @return [RelatonBib::DocumentStatus::Stage]
168
+ def stage(stg)
169
+ return unless stg
170
+
171
+ args = stg.is_a?(String) ? { value: stg } : stg
172
+ DocumentStatus::Stage.new(**args)
173
+ end
174
+
160
175
  def contributors_hash_to_bib(ret)
161
176
  return unless ret[:contributor]
162
177
 
@@ -252,47 +267,70 @@ module RelatonBib
252
267
  end
253
268
  end
254
269
 
270
+ # @param ret [Hash]
255
271
  def relations_hash_to_bib(ret)
256
272
  return unless ret[:relation]
257
273
 
258
274
  ret[:relation] = array(ret[:relation])
259
- ret[:relation]&.each_with_index do |r, i|
260
- relation_bibitem_hash_to_bib(ret, r, i)
261
- relation_biblocality_hash_to_bib(ret, r, i)
275
+ ret[:relation]&.each do |r|
276
+ if r[:description]
277
+ r[:description] = FormattedString.new r[:description]
278
+ end
279
+ relation_bibitem_hash_to_bib(r)
280
+ relation_locality_hash_to_bib(r)
281
+ relation_source_locality_hash_to_bib(r)
262
282
  end
263
283
  end
264
284
 
265
- # @param ret [Hash]
266
285
  # @param rel [Hash] relation
267
- # @param idx [Integr] index of relation
268
- def relation_bibitem_hash_to_bib(ret, rel, idx)
286
+ def relation_bibitem_hash_to_bib(rel)
269
287
  if rel[:bibitem]
270
- ret[:relation][idx][:bibitem] = bib_item(hash_to_bib(rel[:bibitem], true))
288
+ rel[:bibitem] = bib_item hash_to_bib(rel[:bibitem], true)
271
289
  else
272
290
  warn "[relaton-bib] bibitem missing: #{rel}"
273
- ret[:relation][idx][:bibitem] = nil
291
+ rel[:bibitem] = nil
274
292
  end
275
293
  end
276
294
 
277
- # @param item [Hash]
278
- # @retirn [RelatonBib::BibliographicItem]
279
- def bib_item(item)
280
- BibliographicItem.new(item)
295
+ # @param item_hash [Hash]
296
+ # @return [RelatonBib::BibliographicItem]
297
+ def bib_item(item_hash)
298
+ BibliographicItem.new item_hash
281
299
  end
282
300
 
283
- def relation_biblocality_hash_to_bib(ret, rel, idx)
284
- ret[:relation][idx][:bib_locality] =
285
- array(rel[:bib_locality])&.map do |bl|
286
- BibItemLocality.new(bl[:type], bl[:reference_from],
287
- bl[:reference_to])
288
- end
301
+ # @param rel [Hash] relation
302
+ def relation_locality_hash_to_bib(rel)
303
+ rel[:locality] = array(rel[:locality])&.map do |bl|
304
+ ls = if bl[:locality_stack]
305
+ array(bl[:locality_stack]).map do |l|
306
+ Locality.new(l[:type], l[:reference_from], l[:reference_to])
307
+ end
308
+ else
309
+ [Locality.new(bl[:type], bl[:reference_from], bl[:reference_to])]
310
+ end
311
+ LocalityStack.new ls
312
+ end
313
+ end
314
+
315
+ # @param rel [Hash] relation
316
+ def relation_source_locality_hash_to_bib(rel)
317
+ rel[:source_locality] = array(rel[:source_locality])&.map do |sl|
318
+ sls = if sl[:source_locality_stack]
319
+ array(sl[:source_locality_stack]).map do |l|
320
+ SourceLocality.new(l[:type], l[:reference_from], l[:reference_to])
321
+ end
322
+ else
323
+ [SourceLocality.new(sl[:type], sl[:reference_from], sl[:reference_to])]
324
+ end
325
+ SourceLocalityStack.new sls
326
+ end
289
327
  end
290
328
 
291
329
  def series_hash_to_bib(ret)
292
330
  ret[:series] = array(ret[:series])&.map do |s|
293
331
  s[:formattedref] && s[:formattedref] = formattedref(s[:formattedref])
294
332
  if s[:title]
295
- s[:title] = { content: s[:title] } unless s.is_a?(Hash)
333
+ s[:title] = { content: s[:title] } unless s[:title].is_a?(Hash)
296
334
  s[:title] = typed_title_strig(s[:title])
297
335
  end
298
336
  s[:abbreviation] && s[:abbreviation] = localizedstring(s[:abbreviation])