relaton-bib 1.20.7 → 2.0.0.pre.alpha.1
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/.rubocop.yml +1 -1
- data/README.adoc +183 -154
- data/bin/console +1 -1
- data/grammars/basicdoc.rng +1516 -645
- data/grammars/biblio-standoc.rng +100 -20
- data/grammars/biblio.rng +959 -356
- data/grammars/versions.json +10 -10
- data/lib/relaton/bib/hash_parser_v1.rb +711 -0
- data/lib/relaton/bib/item_data.rb +168 -0
- data/lib/relaton/bib/model/address.rb +22 -0
- data/lib/relaton/bib/model/affiliation.rb +16 -0
- data/lib/relaton/bib/model/bibdata.rb +24 -0
- data/lib/relaton/bib/model/bibitem.rb +23 -0
- data/lib/relaton/bib/model/contact.rb +18 -0
- data/lib/relaton/bib/model/contribution_info.rb +16 -0
- data/lib/relaton/bib/model/contributor.rb +71 -0
- data/lib/relaton/bib/model/copyright.rb +27 -0
- data/lib/relaton/bib/model/date.rb +29 -0
- data/lib/relaton/bib/model/depiction.rb +14 -0
- data/lib/relaton/bib/model/docidentifier.rb +33 -0
- data/lib/relaton/bib/model/doctype.rb +14 -0
- data/lib/relaton/bib/model/edition.rb +14 -0
- data/lib/relaton/bib/model/editorial_group.rb +14 -0
- data/lib/relaton/bib/model/ext.rb +29 -0
- data/lib/relaton/bib/model/extent.rb +16 -0
- data/lib/relaton/bib/model/full_name_type.rb +64 -0
- data/lib/relaton/bib/model/fullname.rb +11 -0
- data/lib/relaton/bib/model/ics.rb +14 -0
- data/lib/relaton/bib/model/image.rb +28 -0
- data/lib/relaton/bib/model/item.rb +129 -0
- data/lib/relaton/bib/model/item_base.rb +19 -0
- data/lib/relaton/bib/model/keyword.rb +30 -0
- data/lib/relaton/bib/model/locality.rb +18 -0
- data/lib/relaton/bib/model/locality_stack.rb +14 -0
- data/lib/relaton/bib/model/localized_string.rb +57 -0
- data/lib/relaton/bib/model/localized_string_attrs.rb +24 -0
- data/lib/relaton/bib/model/logo.rb +12 -0
- data/lib/relaton/bib/model/medium.rb +22 -0
- data/lib/relaton/bib/model/note.rb +16 -0
- data/lib/relaton/bib/model/organization.rb +13 -0
- data/lib/relaton/bib/model/organization_type.rb +42 -0
- data/lib/relaton/bib/model/person.rb +36 -0
- data/lib/relaton/bib/model/phone.rb +14 -0
- data/lib/relaton/bib/model/place.rb +33 -0
- data/lib/relaton/bib/model/price.rb +14 -0
- data/lib/relaton/bib/model/relation.rb +43 -0
- data/lib/relaton/bib/model/series.rb +32 -0
- data/lib/relaton/bib/model/size.rb +23 -0
- data/lib/relaton/bib/model/source_locality_stack.rb +14 -0
- data/lib/relaton/bib/model/status.rb +27 -0
- data/lib/relaton/bib/model/structured_identifier.rb +48 -0
- data/lib/relaton/bib/model/subdivision.rb +14 -0
- data/lib/relaton/bib/model/technical_committee.rb +14 -0
- data/lib/relaton/bib/model/title.rb +18 -0
- data/lib/relaton/bib/model/uri.rb +18 -0
- data/lib/relaton/bib/model/validity.rb +16 -0
- data/lib/relaton/bib/model/version.rb +14 -0
- data/lib/relaton/bib/model/workgroup.rb +20 -0
- data/lib/relaton/bib/parser/rfc_address.rb +60 -0
- data/lib/relaton/bib/parser/rfc_contacts.rb +35 -0
- data/lib/relaton/bib/parser/rfc_docidentifier.rb +70 -0
- data/lib/relaton/bib/parser/rfc_organization.rb +31 -0
- data/lib/relaton/bib/parser/rfc_person.rb +42 -0
- data/lib/relaton/bib/parser/rfc_reference.rb +143 -0
- data/lib/relaton/bib/parser/rfc_referencegroup.rb +45 -0
- data/lib/relaton/bib/parser/rfc_shared.rb +23 -0
- data/lib/relaton/bib/renderer/bibtex_builder.rb +348 -0
- data/lib/relaton/bib/renderer/rfc.rb +297 -0
- data/lib/relaton/bib/util.rb +18 -0
- data/lib/relaton/bib/version.rb +5 -0
- data/lib/{relaton_bib.rb → relaton/bib.rb} +47 -36
- data/lib/{relaton_bib → relaton}/bibtex_parser.rb +24 -27
- data/lib/{relaton_bib → relaton}/bibxml_parser.rb +43 -46
- data/lib/{relaton_bib → relaton}/hit.rb +3 -3
- data/lib/{relaton_bib → relaton}/hit_collection.rb +2 -2
- data/lib/{relaton_bib → relaton}/workers_pool.rb +1 -1
- data/lib/{relaton_bib → relaton}/xml_parser.rb +49 -51
- data/relaton-bib.gemspec +8 -8
- metadata +95 -74
- data/lib/relaton_bib/bib_item_locality.rb +0 -175
- data/lib/relaton_bib/biblio_note.rb +0 -72
- data/lib/relaton_bib/biblio_version.rb +0 -46
- data/lib/relaton_bib/bibliographic_date.rb +0 -119
- data/lib/relaton_bib/bibliographic_item.rb +0 -668
- data/lib/relaton_bib/bibliographic_size.rb +0 -103
- data/lib/relaton_bib/classification.rb +0 -40
- data/lib/relaton_bib/config.rb +0 -16
- data/lib/relaton_bib/contribution_info.rb +0 -117
- data/lib/relaton_bib/contributor.rb +0 -277
- data/lib/relaton_bib/copyright_association.rb +0 -79
- data/lib/relaton_bib/document_identifier.rb +0 -118
- data/lib/relaton_bib/document_relation.rb +0 -95
- data/lib/relaton_bib/document_relation_collection.rb +0 -57
- data/lib/relaton_bib/document_status.rb +0 -92
- data/lib/relaton_bib/document_type.rb +0 -52
- data/lib/relaton_bib/edition.rb +0 -55
- data/lib/relaton_bib/editorial_group.rb +0 -41
- data/lib/relaton_bib/extent.rb +0 -39
- data/lib/relaton_bib/forename.rb +0 -65
- data/lib/relaton_bib/formatted_ref.rb +0 -17
- data/lib/relaton_bib/formatted_string.rb +0 -133
- data/lib/relaton_bib/full_name.rb +0 -108
- data/lib/relaton_bib/hash_converter.rb +0 -568
- data/lib/relaton_bib/ics.rb +0 -42
- data/lib/relaton_bib/image.rb +0 -95
- data/lib/relaton_bib/localized_string.rb +0 -149
- data/lib/relaton_bib/medium.rb +0 -76
- data/lib/relaton_bib/organization.rb +0 -165
- data/lib/relaton_bib/person.rb +0 -129
- data/lib/relaton_bib/place.rb +0 -203
- data/lib/relaton_bib/renderer/bibtex_builder.rb +0 -312
- data/lib/relaton_bib/renderer/bibxml.rb +0 -296
- data/lib/relaton_bib/series.rb +0 -119
- data/lib/relaton_bib/structured_identifier.rb +0 -173
- data/lib/relaton_bib/technical_committee.rb +0 -34
- data/lib/relaton_bib/typed_title_string.rb +0 -191
- data/lib/relaton_bib/typed_uri.rb +0 -57
- data/lib/relaton_bib/util.rb +0 -16
- data/lib/relaton_bib/validity.rb +0 -52
- data/lib/relaton_bib/version.rb +0 -3
- data/lib/relaton_bib/workgroup.rb +0 -58
- /data/lib/{relaton_bib → relaton}/deep_dup.rb +0 -0
@@ -0,0 +1,348 @@
|
|
1
|
+
# Monkey patch to fix the issue with month quotes in BibTeX
|
2
|
+
module BibTeX
|
3
|
+
class Value
|
4
|
+
def to_s(options = {}) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
5
|
+
if options.key?(:filter)
|
6
|
+
opts = options.reject { |k,| k == :filter || (k == :quotes && (!atomic? || symbol?)) }
|
7
|
+
return convert(options[:filter]).to_s(opts)
|
8
|
+
end
|
9
|
+
|
10
|
+
return value.to_s unless options.key?(:quotes) && atomic?
|
11
|
+
|
12
|
+
q = Array(options[:quotes])
|
13
|
+
[q[0], value, q[-1]].compact.join
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
module Relaton
|
19
|
+
module Bib
|
20
|
+
module Renderer
|
21
|
+
# BibTeX builder.
|
22
|
+
class BibtexBuilder
|
23
|
+
ATTRS = %i[
|
24
|
+
type id title author editor booktitle series number edition contributor
|
25
|
+
date address note relation extent classification keyword docidentifier
|
26
|
+
timestamp link
|
27
|
+
].freeze
|
28
|
+
|
29
|
+
#
|
30
|
+
# Build BibTeX bibliography.
|
31
|
+
#
|
32
|
+
# @param bib [Relaton::Bib::Item]
|
33
|
+
# @param bibtex [BibTeX::Bibliography, nil] BibTeX bibliography
|
34
|
+
#
|
35
|
+
# @return [BibTeX::Bibliography] BibTeX bibliography
|
36
|
+
#
|
37
|
+
def self.build(bib, bibtex = nil)
|
38
|
+
new(bib).build bibtex
|
39
|
+
end
|
40
|
+
|
41
|
+
#
|
42
|
+
# Initialize BibTeX builder.
|
43
|
+
#
|
44
|
+
# @param bib [Relaton::Bib::Item]
|
45
|
+
def initialize(bib)
|
46
|
+
@bib = bib
|
47
|
+
end
|
48
|
+
|
49
|
+
#
|
50
|
+
# Build BibTeX bibliography.
|
51
|
+
#
|
52
|
+
# @param bibtex [BibTeX::Bibliography, nil] BibTeX bibliography
|
53
|
+
#
|
54
|
+
# @return [BibTeX::Bibliography] BibTeX bibliography
|
55
|
+
#
|
56
|
+
def build(bibtex = nil)
|
57
|
+
@item = BibTeX::Entry.new
|
58
|
+
ATTRS.each { |a| send("add_#{a}") }
|
59
|
+
bibtex ||= BibTeX::Bibliography.new
|
60
|
+
bibtex << @item
|
61
|
+
bibtex
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
#
|
67
|
+
# Add type to BibTeX item
|
68
|
+
#
|
69
|
+
def add_type
|
70
|
+
@item.type = bibtex_type
|
71
|
+
end
|
72
|
+
|
73
|
+
# @return [String] BibTeX type
|
74
|
+
def bibtex_type
|
75
|
+
case @bib.type
|
76
|
+
when "standard", nil then "misc"
|
77
|
+
else @bib.type
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
#
|
82
|
+
# Add ID to BibTeX item
|
83
|
+
#
|
84
|
+
def add_id
|
85
|
+
@item.key = @bib.id
|
86
|
+
end
|
87
|
+
|
88
|
+
#
|
89
|
+
# Add title to BibTeX item
|
90
|
+
#
|
91
|
+
def add_title
|
92
|
+
return unless @bib.title&.any?
|
93
|
+
|
94
|
+
title = @bib.title.find { |t| t.type == "main" } || @bib.title.first
|
95
|
+
return unless title
|
96
|
+
|
97
|
+
@item .title = title.content
|
98
|
+
end
|
99
|
+
|
100
|
+
#
|
101
|
+
# Add booktitle to BibTeX item
|
102
|
+
#
|
103
|
+
def add_booktitle # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity
|
104
|
+
return unless @bib.relation&.any?
|
105
|
+
|
106
|
+
included_in = @bib.relation.detect { |r| r.type == "includedIn" }
|
107
|
+
return unless included_in && included_in.bibitem.title&.any?
|
108
|
+
|
109
|
+
@item.booktitle = included_in.bibitem.title.first.content
|
110
|
+
end
|
111
|
+
|
112
|
+
#
|
113
|
+
# Add author to BibTeX item
|
114
|
+
#
|
115
|
+
def add_author
|
116
|
+
add_author_editor "author"
|
117
|
+
end
|
118
|
+
|
119
|
+
#
|
120
|
+
# Add editor to BibTeX item
|
121
|
+
#
|
122
|
+
def add_editor
|
123
|
+
add_author_editor "editor"
|
124
|
+
end
|
125
|
+
|
126
|
+
#
|
127
|
+
# Add author or editor to BibTeX item
|
128
|
+
#
|
129
|
+
# @param [String] type "author" or "editor"
|
130
|
+
#
|
131
|
+
def add_author_editor(type) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
|
132
|
+
retur unless @bib.contributor&.any?
|
133
|
+
|
134
|
+
contribs = @bib.contributor.select do |c|
|
135
|
+
c.person && c.role.any? { |e| e.type == type }
|
136
|
+
end.map &:person
|
137
|
+
|
138
|
+
return unless contribs.any?
|
139
|
+
|
140
|
+
@item.send "#{type}=", concat_names(contribs)
|
141
|
+
end
|
142
|
+
|
143
|
+
#
|
144
|
+
# Concatenate names of contributors
|
145
|
+
#
|
146
|
+
# @param [Array<Relaton::Bib::Person>] contribs contributors
|
147
|
+
#
|
148
|
+
# @return [String] concatenated names
|
149
|
+
#
|
150
|
+
def concat_names(contribs)
|
151
|
+
contribs.map do |p|
|
152
|
+
if p.name.surname
|
153
|
+
"#{p.name.surname.content}, #{p.name.forename.map(&:content).join(' ')}"
|
154
|
+
else
|
155
|
+
p.name.completename.content
|
156
|
+
end
|
157
|
+
end.join(" and ")
|
158
|
+
end
|
159
|
+
|
160
|
+
#
|
161
|
+
# Add series to BibTeX item
|
162
|
+
#
|
163
|
+
def add_series # rubocop:disable Metrics/AbcSize
|
164
|
+
return unless @bib.series
|
165
|
+
|
166
|
+
@bib.series.each do |s|
|
167
|
+
case s.type
|
168
|
+
when "journal"
|
169
|
+
@item.journal = s.title.first.content
|
170
|
+
@item.number = s.number if s.number
|
171
|
+
when nil then @item.series = s.title.first.content
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
#
|
177
|
+
# Add number to BibTeX item
|
178
|
+
#
|
179
|
+
def add_number
|
180
|
+
return unless %w[techreport manual].include? @bib.type
|
181
|
+
|
182
|
+
did = @bib.docidentifier.detect { |i| i.primary == true }
|
183
|
+
did ||= @bib.docidentifier.first
|
184
|
+
@item.number = did.content if did
|
185
|
+
end
|
186
|
+
|
187
|
+
#
|
188
|
+
# Add edition to BibTeX item
|
189
|
+
#
|
190
|
+
def add_edition
|
191
|
+
@item.edition = @bib.edition.content if @bib.edition
|
192
|
+
end
|
193
|
+
|
194
|
+
#
|
195
|
+
# Add contributor to BibTeX item
|
196
|
+
#
|
197
|
+
def add_contributor # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
|
198
|
+
@bib.contributor.each do |c|
|
199
|
+
rls = c.role.map(&:type)
|
200
|
+
if rls.include?("publisher") then @item.publisher = c.organization.name.first.content
|
201
|
+
elsif rls.include?("distributor")
|
202
|
+
case @bib.type
|
203
|
+
when "techreport" then @item.institution = c.organization.name.first.content
|
204
|
+
when "inproceedings", "conference", "manual", "proceedings"
|
205
|
+
@item.organization = c.organization.name.first.content
|
206
|
+
when "mastersthesis", "phdthesis" then @item.school = c.organization.name.first.content
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
#
|
213
|
+
# Add date to BibTeX item
|
214
|
+
#
|
215
|
+
def add_date
|
216
|
+
Relaton.array(@bib.date).each do |d|
|
217
|
+
case d.type
|
218
|
+
when "published"
|
219
|
+
year, month, = d.at.split("-")
|
220
|
+
@item.year = year
|
221
|
+
@item.month = month if month
|
222
|
+
when "accessed" then @item.urldate = d.at
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
#
|
228
|
+
# Add address to BibTeX item
|
229
|
+
#
|
230
|
+
def add_address # rubocop:disable Metrics/AbcSize
|
231
|
+
return unless @bib.place&.any?
|
232
|
+
|
233
|
+
reg = @bib.place[0].region[0].content if @bib.place[0].region.any?
|
234
|
+
addr = [@bib.place[0].formatted_place, @bib.place[0].city, reg]
|
235
|
+
@item.address = addr.compact.join(", ")
|
236
|
+
end
|
237
|
+
|
238
|
+
#
|
239
|
+
# Add note to BibTeX item
|
240
|
+
#
|
241
|
+
def add_note # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
|
242
|
+
Relaton.array(@bib.note).each do |n|
|
243
|
+
case n.type
|
244
|
+
when "annote" then @item.annote = n.content
|
245
|
+
when "howpublished" then @item.howpublished = n.content
|
246
|
+
when "comment" then @item.comment = n.content
|
247
|
+
when "tableOfContents" then @item.content = n.content
|
248
|
+
when nil then @item.note = n.content
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
#
|
254
|
+
# Add relation to BibTeX item
|
255
|
+
#
|
256
|
+
def add_relation # rubocop:disable Metrics/AbcSize
|
257
|
+
rel = Relaton.array(@bib.relation).detect { |r| r.type == "partOf" }
|
258
|
+
if rel && rel.bibitem.title&.any?
|
259
|
+
title_main = rel.bibitem.title.detect { |t| t.type == "main" }
|
260
|
+
@item.booktitle = title_main.content
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
#
|
265
|
+
# Add extent to BibTeX item
|
266
|
+
#
|
267
|
+
def add_extent # rubocop:disable Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
|
268
|
+
@bib.extent&.each do |extent|
|
269
|
+
extent.locality&.each { |loc| add_locality loc } ||
|
270
|
+
extent.locality_stack&.each { |locs| add_locality_stack locs }
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
def add_locality_stack(locs)
|
275
|
+
return unless locs
|
276
|
+
|
277
|
+
locs.locality.each { |loc| add_locality loc }
|
278
|
+
end
|
279
|
+
|
280
|
+
def add_locality(loc)
|
281
|
+
case loc.type
|
282
|
+
when "chapter" then @item.chapter = loc.reference_from
|
283
|
+
when "page"
|
284
|
+
value = [loc.reference_from]
|
285
|
+
value << loc.reference_to if loc.reference_to
|
286
|
+
@item.pages = value.join("--")
|
287
|
+
when "volume" then @item.volume = loc.reference_from
|
288
|
+
when "issue" then @item.issue = loc.reference_from
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
#
|
293
|
+
# Add classification to BibTeX item
|
294
|
+
#
|
295
|
+
def add_classification
|
296
|
+
@bib.classification&.each do |c|
|
297
|
+
case c.type
|
298
|
+
when "type" then @item["type"] = c.content
|
299
|
+
when "mendeley" then @item["mendeley-tags"] = c.content
|
300
|
+
end
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
#
|
305
|
+
# Add keywords to BibTeX item
|
306
|
+
#
|
307
|
+
def add_keyword
|
308
|
+
if @bib.keyword&.any?
|
309
|
+
@item.keywords = @bib.keyword.reduce([]) { |m, kw| m + kw.taxon.map(&:content) }.join(", ")
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
#
|
314
|
+
# Add docidentifier to BibTeX item
|
315
|
+
#
|
316
|
+
def add_docidentifier
|
317
|
+
@bib.docidentifier&.each do |i|
|
318
|
+
case i.type
|
319
|
+
when "isbn" then @item.isbn = i.content
|
320
|
+
when "lccn" then @item.lccn = i.content
|
321
|
+
when "issn" then @item.issn = i.content
|
322
|
+
end
|
323
|
+
end
|
324
|
+
end
|
325
|
+
|
326
|
+
#
|
327
|
+
# Add identifier to BibTeX item
|
328
|
+
#
|
329
|
+
def add_timestamp
|
330
|
+
@item.timestamp = @bib.fetched.to_s if @bib.fetched
|
331
|
+
end
|
332
|
+
|
333
|
+
#
|
334
|
+
# Add link to BibTeX item
|
335
|
+
#
|
336
|
+
def add_link # rubocop:disable Metrics/CyclomaticComplexity
|
337
|
+
@bib.source&.each do |l|
|
338
|
+
case l.type&.downcase
|
339
|
+
when "doi" then @item.doi = l.content
|
340
|
+
when "file" then @item.file2 = l.content
|
341
|
+
when "src" then @item.url = l.content
|
342
|
+
end
|
343
|
+
end
|
344
|
+
end
|
345
|
+
end
|
346
|
+
end
|
347
|
+
end
|
348
|
+
end
|
@@ -0,0 +1,297 @@
|
|
1
|
+
module Relaton
|
2
|
+
module Bib
|
3
|
+
module Renderer
|
4
|
+
module Rfc
|
5
|
+
def self.transform(item, include_keywords: true) # rubocop:disable Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
|
6
|
+
if item.docnumber&.match(/^BCP/) ||
|
7
|
+
(item.docidentifier.detect(&:primary) || item.docidentifier[0])&.content&.include?("BCP")
|
8
|
+
Refrencegroup.new(item, include_keywords: include_keywords).transform
|
9
|
+
else
|
10
|
+
Reference.new(item, include_keywords: include_keywords).transform
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
module Shared
|
15
|
+
def initialize(item, include_keywords: true)
|
16
|
+
@item = item
|
17
|
+
@include_keywords = include_keywords
|
18
|
+
end
|
19
|
+
|
20
|
+
def create_anchor
|
21
|
+
docid = @item.docidentifier.detect(&:primary) || @item.docidentifier[0]
|
22
|
+
return unless docid
|
23
|
+
|
24
|
+
docid.content.to_s.sub(/^(RFC|BCP|FYI|STD) /, '\1').sub(/^\w+\./, "")
|
25
|
+
end
|
26
|
+
|
27
|
+
def create_target
|
28
|
+
target = @item.source.detect { |l| l.type.casecmp("src").zero? } ||
|
29
|
+
@item.source.detect { |l| l.type.casecmp("doi").zero? }
|
30
|
+
return unless target
|
31
|
+
|
32
|
+
target.content.to_s
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class Refrencegroup
|
37
|
+
include Shared
|
38
|
+
|
39
|
+
def transform
|
40
|
+
reference = @item.relation&.each_with_object([]) do |rel, refs|
|
41
|
+
next unless rel.type == "includes"
|
42
|
+
|
43
|
+
refs << Reference.new(rel.bibitem, include_keywords: @include_keywords).transform
|
44
|
+
end
|
45
|
+
Rfcxml::V3::Referencegroup.new(
|
46
|
+
anchor: create_anchor,
|
47
|
+
target: create_target,
|
48
|
+
reference: reference,
|
49
|
+
)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
class Reference
|
54
|
+
include Shared
|
55
|
+
|
56
|
+
ORGNAMES = {
|
57
|
+
"IEEE" => "Institute of Electrical and Electronics Engineers",
|
58
|
+
"W3C" => "World Wide Web Consortium",
|
59
|
+
"3GPP" => "3rd Generation Partnership Project",
|
60
|
+
}.freeze
|
61
|
+
|
62
|
+
def transform
|
63
|
+
model = ::Rfcxml::V3::Reference.new
|
64
|
+
model.anchor = create_anchor
|
65
|
+
model.target = create_target
|
66
|
+
model.front = create_front
|
67
|
+
model.format = create_format
|
68
|
+
model
|
69
|
+
end
|
70
|
+
|
71
|
+
def create_front # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
|
72
|
+
front = ::Rfcxml::V3::Front.new
|
73
|
+
front.title = Rfcxml::V3::Title.new(content: @item.title[0].content)
|
74
|
+
front.series_info = create_seriesinfo
|
75
|
+
front.author = create_authors
|
76
|
+
front.date = create_date
|
77
|
+
front.workgroup = create_workgroup
|
78
|
+
front.keyword = create_keyword if @include_keywords
|
79
|
+
front.abstract = create_abstract
|
80
|
+
front
|
81
|
+
end
|
82
|
+
|
83
|
+
def create_seriesinfo
|
84
|
+
docidentifier_to_seresinfo + series_to_seriesinfo
|
85
|
+
end
|
86
|
+
|
87
|
+
def docidentifier_to_seresinfo
|
88
|
+
@item.docidentifier.each_with_object([]) do |di, si|
|
89
|
+
if di.type == "DOI" && di.scope != "trademark"
|
90
|
+
si << Rfcxml::V3::SeriesInfo.new(name: di.type, value: di.content)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def series_to_seriesinfo # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity
|
96
|
+
@item.series.select do |s|
|
97
|
+
s.title.reject { |t| t.content == "DOI" }.any?
|
98
|
+
end.uniq do |s|
|
99
|
+
s.title.find { |t| t.content != "DOI" }.content
|
100
|
+
end.each_with_object([]) do |s, si|
|
101
|
+
title = s.title.find { |t| t.content != "DOI" }
|
102
|
+
si << Rfcxml::V3::SeriesInfo.new(name: title.content, value: s.number)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def create_authors # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
|
107
|
+
@item.contributor.map do |contrib|
|
108
|
+
role = "editor" if contrib.role.detect { |r| r.type == "editor" }
|
109
|
+
Rfcxml::V3::Author.new(
|
110
|
+
role: role,
|
111
|
+
initials: person_initials(contrib.person),
|
112
|
+
surname: person_surname(contrib.person),
|
113
|
+
fullname: person_fullname(contrib.person),
|
114
|
+
organization: create_organization(contrib),
|
115
|
+
address: create_address(contrib),
|
116
|
+
)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def person_fullname(person) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
|
121
|
+
return unless person
|
122
|
+
|
123
|
+
if person.name.completename
|
124
|
+
person.name.completename.content
|
125
|
+
elsif person.name.forename.any?
|
126
|
+
parts = person.name.forename.map do |n|
|
127
|
+
n.content || n.initial
|
128
|
+
end
|
129
|
+
parts << person.name.surname.content if person.name.surname
|
130
|
+
parts.join(" ")
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def person_initials(person) # rubocop:disable Metrics/AbcSize
|
135
|
+
return unless person
|
136
|
+
|
137
|
+
if person.name.formatted_initials
|
138
|
+
person.name.formatted_initials.content
|
139
|
+
elsif person.name.forename.any?
|
140
|
+
person.name.forename.map { |f| "#{f.initial || f.content[0]}." }.join " "
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def person_surname(person)
|
145
|
+
return unless person
|
146
|
+
|
147
|
+
person.name.surname&.content
|
148
|
+
end
|
149
|
+
|
150
|
+
def create_organization(contrib, _role = []) # rubocop:disable Metrics/PerceivedComplexity,Metrics/CyclomaticComplexity,Metrics/AbcSize
|
151
|
+
org = contrib.organization || contrib.person && contrib.person.affiliation[0]&.organization
|
152
|
+
return unless org
|
153
|
+
|
154
|
+
abbrev = org.abbreviation&.content
|
155
|
+
orgname = org.name&.first&.content
|
156
|
+
orgname = if ORGNAMES.key?(abbrev) then abbrev
|
157
|
+
else ORGNAMES.key(orgname) || orgname || abbrev
|
158
|
+
end
|
159
|
+
Rfcxml::V3::Organization.new(content: orgname, abbrev: abbrev)
|
160
|
+
end
|
161
|
+
|
162
|
+
def create_address(contrib) # rubocop:disable Metrics/AbcSize
|
163
|
+
entity = contrib.person || contrib.organization
|
164
|
+
return unless entity.address.any? || entity.phone.any? || entity.email.any? || entity.uri.any?
|
165
|
+
|
166
|
+
Rfcxml::V3::Address.new(
|
167
|
+
postal: address_postal(entity),
|
168
|
+
phone: address_phone(entity),
|
169
|
+
email: address_email(entity),
|
170
|
+
uri: address_uri(entity),
|
171
|
+
)
|
172
|
+
end
|
173
|
+
|
174
|
+
def address_postal(entity)
|
175
|
+
args = address_postal_args(entity)
|
176
|
+
return unless args.values.any?(&:any?)
|
177
|
+
|
178
|
+
Rfcxml::V3::Postal.new(**args)
|
179
|
+
end
|
180
|
+
|
181
|
+
def address_postal_args(entity)
|
182
|
+
{
|
183
|
+
city: address_cities(entity),
|
184
|
+
code: address_postcodes(entity),
|
185
|
+
country: address_countries(entity),
|
186
|
+
region: address_states(entity),
|
187
|
+
street: address_streets(entity),
|
188
|
+
postal_line: address_postal_lines(entity),
|
189
|
+
}
|
190
|
+
end
|
191
|
+
|
192
|
+
def address_cities(entity)
|
193
|
+
entity.address.each_with_object([]) do |address, cities|
|
194
|
+
cities << Rfcxml::V3::City.new(content: address.city) if address.city
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
def address_postcodes(entity)
|
199
|
+
entity.address.each_with_object([]) do |address, codes|
|
200
|
+
codes << Rfcxml::V3::Code.new(content: address.postcode) if address.postcode
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
def address_countries(entity)
|
205
|
+
entity.address.each_with_object([]) do |address, countries|
|
206
|
+
countries << Rfcxml::V3::Country.new(content: address.country) if address.country
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
def address_states(entity)
|
211
|
+
entity.address.each_with_object([]) do |address, states|
|
212
|
+
states << Rfcxml::V3::Region.new(content: address.state) if address.state
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
def address_streets(entity)
|
217
|
+
entity.address.each_with_object([]) do |address, streets|
|
218
|
+
address.street.each do |street|
|
219
|
+
streets << Rfcxml::V3::Street.new(content: street)
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
def address_postal_lines(entity)
|
225
|
+
entity.address.each_with_object([]) do |address, plines|
|
226
|
+
plines << Rfcxml::V3::PostalLine.new(content: address.formatted_address) if address.formatted_address
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
def address_phone(entity)
|
231
|
+
return unless entity.phone.any?
|
232
|
+
|
233
|
+
Rfcxml::V3::Phone.new(content: entity.phone[0].content)
|
234
|
+
end
|
235
|
+
|
236
|
+
def address_email(entity)
|
237
|
+
entity.email.each_with_object([]) do |email, emails|
|
238
|
+
emails << Rfcxml::V3::Email.new(content: email)
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
def address_uri(entity)
|
243
|
+
return unless entity.uri.any?
|
244
|
+
|
245
|
+
Rfcxml::V3::Uri.new(content: entity.uri[0].content)
|
246
|
+
end
|
247
|
+
|
248
|
+
def create_date # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity
|
249
|
+
pub_date = @item.date.detect { |d| d.type == "published" }
|
250
|
+
return unless pub_date
|
251
|
+
|
252
|
+
args = {}
|
253
|
+
[pub_date.at, pub_date.from, pub_date.to].compact.each do |d|
|
254
|
+
year, month, day = d.split("-")
|
255
|
+
args[:year] ||= year
|
256
|
+
args[:month] ||= ::Date::MONTHNAMES[month.to_i]
|
257
|
+
args[:day] ||= day
|
258
|
+
end
|
259
|
+
Rfcxml::V3::Date.new(**args)
|
260
|
+
end
|
261
|
+
|
262
|
+
def create_workgroup
|
263
|
+
@item.ext&.editorialgroup&.technical_committee&.each do |tc|
|
264
|
+
Rfcxml::V3::Workgroup.new content: tc.content
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
def create_keyword
|
269
|
+
@item.keyword.inject([]) do |a, k|
|
270
|
+
a + k.taxon.map { |t| Rfcxml::V3::Keyword.new content: t.content }
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
def create_abstract
|
275
|
+
return unless @item.abstract.any?
|
276
|
+
|
277
|
+
Rfcxml::V3::Abstract.new t: [create_text]
|
278
|
+
end
|
279
|
+
|
280
|
+
def create_text
|
281
|
+
Rfcxml::V3::Text.new content: @item.abstract[0].content
|
282
|
+
end
|
283
|
+
|
284
|
+
def create_format
|
285
|
+
@item.source.reduce([]) do |a, l|
|
286
|
+
next a unless l.type.casecmp("TXT").zero? || l.type.casecmp("HTML").zero? ||
|
287
|
+
l.type.casecmp("PDF").zero? || l.type.casecmp("XML").zero? ||
|
288
|
+
l.type.casecmp("DOC").zero?
|
289
|
+
|
290
|
+
a << Rfcxml::V3::Format.new(type: l.type, target: l.content)
|
291
|
+
end
|
292
|
+
end
|
293
|
+
end
|
294
|
+
end
|
295
|
+
end
|
296
|
+
end
|
297
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Relaton
|
2
|
+
module Bib
|
3
|
+
module Util
|
4
|
+
extend self
|
5
|
+
|
6
|
+
PROGNAME = "relaton-bib".freeze
|
7
|
+
|
8
|
+
def method_missing(method_name, msg = nil, prog = nil, **opts, &block)
|
9
|
+
prog ||= self::PROGNAME
|
10
|
+
Relaton.logger_pool.send method_name, msg, prog, **opts, &block
|
11
|
+
end
|
12
|
+
|
13
|
+
def respond_to_missing?(method_name, include_private = false)
|
14
|
+
Relaton.logger_pool.respond_to?(method_name) || super
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|