relaton-bib 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +13 -0
- data/.rspec +3 -0
- data/.rubocop.yml +10 -0
- data/.travis.yml +7 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +57 -0
- data/LICENSE.txt +21 -0
- data/README.adoc +272 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/relaton_bib.rb +7 -0
- data/lib/relaton_bib/bib_item_locality.rb +46 -0
- data/lib/relaton_bib/bibliographic_date.rb +76 -0
- data/lib/relaton_bib/bibliographic_item.rb +343 -0
- data/lib/relaton_bib/classification.rb +22 -0
- data/lib/relaton_bib/contribution_info.rb +61 -0
- data/lib/relaton_bib/contributor.rb +121 -0
- data/lib/relaton_bib/copyright_association.rb +38 -0
- data/lib/relaton_bib/document_identifier.rb +26 -0
- data/lib/relaton_bib/document_relation.rb +49 -0
- data/lib/relaton_bib/document_relation_collection.rb +21 -0
- data/lib/relaton_bib/document_status.rb +24 -0
- data/lib/relaton_bib/formatted_ref.rb +11 -0
- data/lib/relaton_bib/formatted_string.rb +33 -0
- data/lib/relaton_bib/localized_string.rb +45 -0
- data/lib/relaton_bib/medium.rb +24 -0
- data/lib/relaton_bib/organization.rb +103 -0
- data/lib/relaton_bib/person.rb +131 -0
- data/lib/relaton_bib/series.rb +96 -0
- data/lib/relaton_bib/typed_title_string.rb +41 -0
- data/lib/relaton_bib/typed_uri.rb +20 -0
- data/lib/relaton_bib/validity.rb +31 -0
- data/lib/relaton_bib/version.rb +3 -0
- data/lib/relaton_bib/xml_parser.rb +289 -0
- data/relaton-bib.gemspec +34 -0
- metadata +192 -0
@@ -0,0 +1,46 @@
|
|
1
|
+
module RelatonBib
|
2
|
+
# class SpecificLocalityType
|
3
|
+
# SECTION = 'section'
|
4
|
+
# CLAUSE = 'clause'
|
5
|
+
# PART = 'part'
|
6
|
+
# PARAGRAPH = 'paragraph'
|
7
|
+
# CHAPTER = 'chapter'
|
8
|
+
# PAGE = 'page'
|
9
|
+
# WHOLE = 'whole'
|
10
|
+
# TABLE = 'table'
|
11
|
+
# ANNEX = 'annex'
|
12
|
+
# FIGURE = 'figure'
|
13
|
+
# NOTE = 'note'
|
14
|
+
# EXAMPLE = 'example'
|
15
|
+
# # generic String is allowed
|
16
|
+
# end
|
17
|
+
|
18
|
+
# Bibliographic item locality.
|
19
|
+
class BibItemLocality
|
20
|
+
# @return [RelatonBib::SpecificLocalityType]
|
21
|
+
attr_reader :type
|
22
|
+
|
23
|
+
# @return [RelatonBib::LocalizedString]
|
24
|
+
attr_reader :reference_from
|
25
|
+
|
26
|
+
# @return [RelatonBib::LocalizedString]
|
27
|
+
attr_reader :reference_to
|
28
|
+
|
29
|
+
# @param type [String]
|
30
|
+
# @param referenceFrom [String]
|
31
|
+
# @param referenceTo [String]
|
32
|
+
def initialize(type, reference_from, reference_to = nil)
|
33
|
+
@type = type
|
34
|
+
@reference_from = reference_from
|
35
|
+
@reference_to = reference_to
|
36
|
+
end
|
37
|
+
|
38
|
+
# @param builder [Nokogiri::XML::Builder]
|
39
|
+
def to_xml(builder)
|
40
|
+
builder.locality(type: type) do
|
41
|
+
builder.referenceFrom reference_from # { reference_from.to_xml(builder) }
|
42
|
+
builder.referenceTo reference_to if reference_to
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "time"
|
4
|
+
|
5
|
+
module RelatonBib
|
6
|
+
# Bibliographic date.
|
7
|
+
class BibliographicDate
|
8
|
+
TYPES = %w[published accessed created implemented obsoleted confirmed
|
9
|
+
updated issued].freeze
|
10
|
+
|
11
|
+
# @return [String]
|
12
|
+
attr_reader :type
|
13
|
+
|
14
|
+
# @return [Time]
|
15
|
+
attr_reader :from
|
16
|
+
|
17
|
+
# @return [Time]
|
18
|
+
attr_reader :to
|
19
|
+
|
20
|
+
# @return [Time]
|
21
|
+
attr_reader :on
|
22
|
+
|
23
|
+
# @param type [String] "published", "accessed", "created", "activated"
|
24
|
+
# @param from [String]
|
25
|
+
# @param to [String]
|
26
|
+
def initialize(type:, on: nil, from: nil, to: nil)
|
27
|
+
raise ArgumentError, "expected :on or :form argument" unless on || from
|
28
|
+
|
29
|
+
raise ArgumentError, %{Type "#{type}" is ivalid.} unless TYPES.include?(type)
|
30
|
+
|
31
|
+
@type = type
|
32
|
+
@on = parse_date on
|
33
|
+
@from = parse_date from
|
34
|
+
@to = parse_date to
|
35
|
+
end
|
36
|
+
|
37
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
|
38
|
+
# rubocop:disable Metrics/MethodLength, Metrics/PerceivedComplexity
|
39
|
+
|
40
|
+
# @param builder [Nokogiri::XML::Builder]
|
41
|
+
# @return [Nokogiri::XML::Builder]
|
42
|
+
def to_xml(builder, **opts)
|
43
|
+
builder.date(type: type) do
|
44
|
+
if on
|
45
|
+
date = opts[:full_date] ? on.strftime("%Y-%m") : on.year
|
46
|
+
builder.on(opts[:no_year] ? "--" : date)
|
47
|
+
elsif from
|
48
|
+
if opts[:full_date]
|
49
|
+
date_form = from.strftime("%Y-%m")
|
50
|
+
date_to = to.strftime("%Y-%m") if to
|
51
|
+
else
|
52
|
+
date_form = from.year
|
53
|
+
date_to = to.year if to
|
54
|
+
end
|
55
|
+
builder.from(opts[:no_year] ? "--" : date_form)
|
56
|
+
builder.to date_to if to
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity
|
61
|
+
# rubocop:enable Metrics/MethodLength, Metrics/PerceivedComplexity
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
# @params date [String] 'yyyy' or 'yyyy-mm'
|
66
|
+
def parse_date(date)
|
67
|
+
return unless date
|
68
|
+
|
69
|
+
if date =~ /^\d{4}$/
|
70
|
+
Time.strptime date, "%Y"
|
71
|
+
else
|
72
|
+
Time.strptime date, "%Y-%m"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,343 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "relaton_bib/typed_uri"
|
4
|
+
require "relaton_bib/document_identifier"
|
5
|
+
require "relaton_bib/copyright_association"
|
6
|
+
require "relaton_bib/formatted_string"
|
7
|
+
require "relaton_bib/contribution_info"
|
8
|
+
require "relaton_bib/bibliographic_date"
|
9
|
+
require "relaton_bib/series"
|
10
|
+
require "relaton_bib/document_status"
|
11
|
+
require "relaton_bib/organization"
|
12
|
+
require "relaton_bib/document_relation_collection"
|
13
|
+
require "relaton_bib/typed_title_string"
|
14
|
+
require "relaton_bib/formatted_ref"
|
15
|
+
require "relaton_bib/medium"
|
16
|
+
require "relaton_bib/classification"
|
17
|
+
require "relaton_bib/validity"
|
18
|
+
require "relaton_bib/document_relation"
|
19
|
+
require "relaton_bib/bib_item_locality"
|
20
|
+
require "relaton_bib/xml_parser"
|
21
|
+
|
22
|
+
|
23
|
+
module RelatonBib
|
24
|
+
# module BibItemType
|
25
|
+
# ARTICLE = 'article'
|
26
|
+
# BOOK = 'book'
|
27
|
+
# BOOKLET = 'booklet'
|
28
|
+
# CONFERENCE = 'conference'
|
29
|
+
# MANUAL = 'manual'
|
30
|
+
# PROCEEDINGS = 'proceedings'
|
31
|
+
# PRESENTATION = 'presentation'
|
32
|
+
# THESIS = 'thesis'
|
33
|
+
# TECHREPORT = 'techreport'
|
34
|
+
# STANDARD = 'standard'
|
35
|
+
# UNPUBLISHED = 'unpublished'
|
36
|
+
# end
|
37
|
+
|
38
|
+
# Bibliographic item
|
39
|
+
class BibliographicItem
|
40
|
+
class Version
|
41
|
+
# @return [String]
|
42
|
+
attr_reader :revision_date
|
43
|
+
|
44
|
+
# @return [Array<String>]
|
45
|
+
attr_reader :draft
|
46
|
+
|
47
|
+
# @oaram revision_date [String]
|
48
|
+
# @param draft [Array<String>]
|
49
|
+
def initialize(revision_date = nil, draft = [])
|
50
|
+
@revision_date = revision_date
|
51
|
+
@draft = draft
|
52
|
+
end
|
53
|
+
|
54
|
+
# @param builder [Nokogiri::XML::Builder]
|
55
|
+
def to_xml(builder)
|
56
|
+
builder.version do
|
57
|
+
builder.revision_date revision_date if revision_date
|
58
|
+
draft.each { |d| builder.draft d }
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
TYPES = %W[article book booklet conference manual proceedings presentation
|
64
|
+
thesis techreport standard unpublished map electronic\sresource
|
65
|
+
audiovisual film video broadcast graphic_work music patent
|
66
|
+
inbook incollection inproceedings journal].freeze
|
67
|
+
|
68
|
+
# @return [String]
|
69
|
+
attr_reader :id
|
70
|
+
|
71
|
+
# @return [Array<RelatonBib::TypedTitleString>]
|
72
|
+
attr_reader :title
|
73
|
+
|
74
|
+
# @return [Array<RelatonBib::TypedUri>]
|
75
|
+
attr_reader :link
|
76
|
+
|
77
|
+
# @return [String]
|
78
|
+
attr_reader :type
|
79
|
+
|
80
|
+
# @return [Array<RelatonBib::DocumentIdentifier>]
|
81
|
+
attr_reader :docidentifier
|
82
|
+
|
83
|
+
# @return [String] docnumber
|
84
|
+
attr_reader :docnumber
|
85
|
+
|
86
|
+
# @return [Array<RelatonBib::BibliographicDate>]
|
87
|
+
attr_reader :dates
|
88
|
+
|
89
|
+
# @return [Array<RelatonBib::ContributionInfo>]
|
90
|
+
attr_reader :contributors
|
91
|
+
|
92
|
+
# @return [String, NillClass]
|
93
|
+
attr_reader :edition
|
94
|
+
|
95
|
+
# @return [RelatonBib::BibliongraphicItem::Version]
|
96
|
+
attr_reader :version
|
97
|
+
|
98
|
+
# @return [Array<RelatonBib::FormattedString>, NilClass]
|
99
|
+
attr_reader :biblionote
|
100
|
+
|
101
|
+
# @return [Array<String>] language Iso639 code
|
102
|
+
attr_reader :language
|
103
|
+
|
104
|
+
# @return [Array<String>] script Iso15924 code
|
105
|
+
attr_reader :script
|
106
|
+
|
107
|
+
# @return [RelatonBib::FormattedRef]
|
108
|
+
attr_reader :formattedref
|
109
|
+
|
110
|
+
# @!attribute [r] abstract
|
111
|
+
# @return [Array<RelatonBib::FormattedString>]
|
112
|
+
|
113
|
+
# @return [RelatonBib::DocumentStatus]
|
114
|
+
attr_reader :status
|
115
|
+
|
116
|
+
# @return [RelatonBib::CopyrightAssociation]
|
117
|
+
attr_reader :copyright
|
118
|
+
|
119
|
+
# @return [RelatonBib::DocRelationCollection]
|
120
|
+
attr_reader :relations
|
121
|
+
|
122
|
+
# @return [Array<RelatonBib::Series>]
|
123
|
+
attr_reader :series
|
124
|
+
|
125
|
+
# @return [RelatonBib::Medium, NilClass]
|
126
|
+
attr_reader :medium
|
127
|
+
|
128
|
+
# @return [Array<String>]
|
129
|
+
attr_reader :place
|
130
|
+
|
131
|
+
# @return [Array<RelatonBib::BibItemLocality>]
|
132
|
+
attr_reader :extent
|
133
|
+
|
134
|
+
# @return [Array<Strig>]
|
135
|
+
attr_reader :accesslocation
|
136
|
+
|
137
|
+
# @return [Relaton::Classification, NilClass]
|
138
|
+
attr_reader :classification
|
139
|
+
|
140
|
+
# @return [RelatonBib:Validity, NilClass]
|
141
|
+
attr_reader :validity
|
142
|
+
|
143
|
+
# @return [Date]
|
144
|
+
attr_reader :fetched
|
145
|
+
|
146
|
+
# rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
147
|
+
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
148
|
+
|
149
|
+
# @param id [String, NilClass]
|
150
|
+
# @param title [Array<RelatonBib::TypedTitleString>]
|
151
|
+
# @param formattedref [RelatonBib::FormattedRef, NilClass]
|
152
|
+
# @param type [String, NilClass]
|
153
|
+
# @param docid [Array<RelatonBib::DocumentIdentifier>]
|
154
|
+
# @param docnumber [String, NilClass]
|
155
|
+
# @param language [Arra<String>]
|
156
|
+
# @param script [Array<String>]
|
157
|
+
# @param docstatus [RelatonBib::DocumentStatus, NilClass]
|
158
|
+
# @param edition [String, NilClass]
|
159
|
+
# @param version [RelatonBib::BibliographicItem::Version, NilClass]
|
160
|
+
# @param biblionote [Array<RelatonBib::FormattedStrong>]
|
161
|
+
# @param series [Array<RelatonBib::Series>]
|
162
|
+
# @param medium [RelatonBib::Medium, NilClas]
|
163
|
+
# @param place [Array<String>]
|
164
|
+
# @param extent [Array<Relaton::BibItemLocality>]
|
165
|
+
# @param accesslocation [Array<String>]
|
166
|
+
# @param classification [RelatonBib::Classification, NilClass]
|
167
|
+
# @param validity [RelatonBib:Validity, NilClass]
|
168
|
+
# @param fetched [Date, NilClass] default nil
|
169
|
+
#
|
170
|
+
# @param dates [Array<Hash>]
|
171
|
+
# @option dates [String] :type
|
172
|
+
# @option dates [String] :from
|
173
|
+
# @option dates [String] :to
|
174
|
+
#
|
175
|
+
# @param contributors [Array<Hash>]
|
176
|
+
# @option contributors [String] :type
|
177
|
+
# @option contributors [String] :from
|
178
|
+
# @option contributirs [String] :to
|
179
|
+
# @option contributors [String] :abbreviation
|
180
|
+
# @option contributors [Array<String>] :roles
|
181
|
+
#
|
182
|
+
# @param abstract [Array<Hash>]
|
183
|
+
# @option abstract [String] :content
|
184
|
+
# @option abstract [String] :language
|
185
|
+
# @option abstract [String] :script
|
186
|
+
# @option abstract [String] :type
|
187
|
+
#
|
188
|
+
# @param relations [Array<Hash>]
|
189
|
+
# @option relations [String] :type
|
190
|
+
# @option relations [RelatonBib::BibliographicItem] :bibitem
|
191
|
+
# @option relations [Array<RelatonBib::BibItemLocality>] :bib_locality
|
192
|
+
def initialize(**args)
|
193
|
+
if args[:type] && !TYPES.include?(args[:type])
|
194
|
+
raise ArgumentError, %{Type "#{args[:type]}" is invalid.}
|
195
|
+
end
|
196
|
+
|
197
|
+
@title = (args[:titles] || []).map do |t|
|
198
|
+
t.is_a?(Hash) ? TypedTitleString.new(t) : t
|
199
|
+
end
|
200
|
+
|
201
|
+
@dates = (args[:dates] || []).map do |d|
|
202
|
+
d.is_a?(Hash) ? BibliographicDate.new(d) : d
|
203
|
+
end
|
204
|
+
|
205
|
+
@contributors = (args[:contributors] || []).map do |c|
|
206
|
+
if c.is_a? Hash
|
207
|
+
e = c[:entity].is_a?(Hash) ? Organization.new(c[:entity]) : c[:entity]
|
208
|
+
ContributionInfo.new(entity: e, role: c[:roles])
|
209
|
+
else c
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
@abstract = (args[:abstract] || []).map do |a|
|
214
|
+
a.is_a?(Hash) ? FormattedString.new(a) : a
|
215
|
+
end
|
216
|
+
|
217
|
+
if args[:copyright]
|
218
|
+
@copyright = if args[:copyright].is_a?(Hash)
|
219
|
+
CopyrightAssociation.new args[:copyright]
|
220
|
+
else args[:copyright]
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
@id = args[:id]
|
225
|
+
@formattedref = args[:formattedref] if title.empty?
|
226
|
+
@type = args[:type]
|
227
|
+
@docidentifier = args[:docid] || []
|
228
|
+
@docnumber = args[:docnumber]
|
229
|
+
@edition = args[:edition]
|
230
|
+
@version = args[:version]
|
231
|
+
@biblionote = args.fetch :biblionote, []
|
232
|
+
@language = args.fetch :language, []
|
233
|
+
@script = args.fetch :script, []
|
234
|
+
@status = args[:docstatus]
|
235
|
+
@relations = DocRelationCollection.new(args[:relations] || [])
|
236
|
+
@link = args.fetch(:link, []).map { |s| s.is_a?(Hash) ? TypedUri.new(s) : s }
|
237
|
+
@series = args[:series]
|
238
|
+
@medium = args[:medium]
|
239
|
+
@place = args.fetch(:place, [])
|
240
|
+
@extent = args[:extent] || []
|
241
|
+
@accesslocation = args.fetch :accesslocation, []
|
242
|
+
@classification = args[:classification]
|
243
|
+
@validity = args[:validity]
|
244
|
+
@fetched = args.fetch :fetched, nil # , Date.today # we should pass the fetched arg from scrappers
|
245
|
+
end
|
246
|
+
# rubocop:enable Metrics/MethodLength, Metrics/AbcSize
|
247
|
+
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
248
|
+
|
249
|
+
# @param lang [String] language code Iso639
|
250
|
+
# @return [RelatonBib::FormattedString, Array<RelatonBib::FormattedString>]
|
251
|
+
def abstract(lang: nil)
|
252
|
+
if lang
|
253
|
+
@abstract.detect { |a| a.language.include? lang }
|
254
|
+
else
|
255
|
+
@abstract
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
def makeid(id, attribute)
|
260
|
+
return nil if attribute && !@id_attribute
|
261
|
+
|
262
|
+
id ||= @docidentifier.reject { |i| i.type == "DOI" }[0]
|
263
|
+
# contribs = publishers.map { |p| p&.entity&.abbreviation }.join '/'
|
264
|
+
# idstr = "#{contribs}#{delim}#{id.project_number}"
|
265
|
+
# idstr = id.project_number.to_s
|
266
|
+
idstr = id.id.gsub(/:/, "-")
|
267
|
+
# if id.part_number&.size&.positive? then idstr += "-#{id.part_number}"
|
268
|
+
idstr.strip
|
269
|
+
end
|
270
|
+
|
271
|
+
# @return [String]
|
272
|
+
def shortref(identifier, **opts)
|
273
|
+
pubdate = dates.select { |d| d.type == "published" }
|
274
|
+
year = if opts[:no_year] || pubdate.empty? then ""
|
275
|
+
else ":" + pubdate&.first&.on&.year.to_s
|
276
|
+
end
|
277
|
+
year += ": All Parts" if opts[:all_parts] || @all_parts
|
278
|
+
|
279
|
+
"#{makeid(identifier, false)}#{year}"
|
280
|
+
end
|
281
|
+
|
282
|
+
# @param builder [Nokogiri::XML::Builder, NillClass] (nil)
|
283
|
+
# @return [String]
|
284
|
+
def to_xml(builder = nil, root = "bibitem", &block)
|
285
|
+
if builder
|
286
|
+
render_xml builder, root, &block
|
287
|
+
else
|
288
|
+
Nokogiri::XML::Builder.new(encoding: "UTF-8") do |xml|
|
289
|
+
render_xml xml, root, &block
|
290
|
+
end.doc.root.to_xml
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
private
|
295
|
+
|
296
|
+
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
297
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
298
|
+
|
299
|
+
# @param builder [Nokogiri::XML::Builder]
|
300
|
+
# @return [String]
|
301
|
+
def render_xml(builder, root)
|
302
|
+
xml = builder.send(root) do
|
303
|
+
builder.fetched fetched if fetched
|
304
|
+
title.each { |t| builder.title { t.to_xml builder } }
|
305
|
+
formattedref.to_xml builder if formattedref
|
306
|
+
link.each { |s| s.to_xml builder }
|
307
|
+
docidentifier.each { |di| di.to_xml builder }
|
308
|
+
builder.docnumber docnumber if docnumber
|
309
|
+
dates.each { |d| d.to_xml builder, full_date: true }
|
310
|
+
contributors.each do |c|
|
311
|
+
builder.contributor do
|
312
|
+
c.role.each { |r| r.to_xml builder }
|
313
|
+
c.to_xml builder
|
314
|
+
end
|
315
|
+
end
|
316
|
+
builder.edition edition if edition
|
317
|
+
version.to_xml builder if version
|
318
|
+
biblionote.each { |n| builder.note { n.to_xml builder } }
|
319
|
+
language.each { |l| builder.language l }
|
320
|
+
script.each { |s| builder.script s }
|
321
|
+
abstract.each { |a| builder.abstract { a.to_xml(builder) } }
|
322
|
+
status.to_xml builder if status
|
323
|
+
copyright.to_xml builder if copyright
|
324
|
+
relations.each { |r| r.to_xml builder }
|
325
|
+
series.each { |s| s.to_xml builder } if series
|
326
|
+
medium.to_xml builder if medium
|
327
|
+
place.each { |pl| builder.place pl }
|
328
|
+
extent.each { |e| e.to_xml builder }
|
329
|
+
accesslocation.each { |al| builder.accesslocation al }
|
330
|
+
classification.to_xml builder if classification
|
331
|
+
validity.to_xml builder if validity
|
332
|
+
if block_given?
|
333
|
+
yield builder
|
334
|
+
end
|
335
|
+
end
|
336
|
+
xml[:id] = id if id
|
337
|
+
xml[:type] = type if type
|
338
|
+
xml
|
339
|
+
end
|
340
|
+
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
341
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
342
|
+
end
|
343
|
+
end
|