relaton-bib 0.9.2 → 1.0.4
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.
- checksums.yaml +4 -4
- data/.hound.yml +2 -0
- data/README.adoc +14 -7
- data/docs/hash.adoc +53 -53
- data/lib/relaton_bib/bib_item_locality.rb +59 -16
- data/lib/relaton_bib/bibliographic_item.rb +6 -2
- data/lib/relaton_bib/bibtex_parser.rb +22 -20
- data/lib/relaton_bib/document_relation.rb +49 -25
- data/lib/relaton_bib/document_relation_collection.rb +18 -5
- data/lib/relaton_bib/document_status.rb +46 -8
- data/lib/relaton_bib/formatted_string.rb +3 -3
- data/lib/relaton_bib/hash_converter.rb +59 -21
- data/lib/relaton_bib/localized_string.rb +33 -12
- data/lib/relaton_bib/typed_title_string.rb +1 -1
- data/lib/relaton_bib/version.rb +1 -1
- data/lib/relaton_bib/xml_parser.rb +94 -20
- data/relaton-bib.gemspec +3 -3
- metadata +17 -16
@@ -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,
|
171
|
-
#
|
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
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
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
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
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::
|
29
|
-
attr_reader :
|
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
|
-
# @
|
33
|
-
# @param
|
34
|
-
|
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
|
-
|
37
|
-
|
38
|
-
|
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
|
-
|
48
|
-
|
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["
|
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
|
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::
|
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
|
-
|
23
|
+
@array = relation.map { |r| r.is_a?(Hash) ? DocumentRelation.new(r) : r }
|
14
24
|
end
|
15
25
|
|
16
|
-
# @
|
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 }
|
40
|
-
hash["format"] = 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]&.
|
260
|
-
|
261
|
-
|
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
|
-
|
268
|
-
def relation_bibitem_hash_to_bib(ret, rel, idx)
|
286
|
+
def relation_bibitem_hash_to_bib(rel)
|
269
287
|
if rel[:bibitem]
|
270
|
-
|
288
|
+
rel[:bibitem] = bib_item hash_to_bib(rel[:bibitem], true)
|
271
289
|
else
|
272
290
|
warn "[relaton-bib] bibitem missing: #{rel}"
|
273
|
-
|
291
|
+
rel[:bibitem] = nil
|
274
292
|
end
|
275
293
|
end
|
276
294
|
|
277
|
-
# @param
|
278
|
-
# @
|
279
|
-
def bib_item(
|
280
|
-
BibliographicItem.new
|
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
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
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])
|