relaton-bib 0.4.1 → 0.5.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.
@@ -0,0 +1,236 @@
1
+ require "bibtex"
2
+ require "iso639"
3
+
4
+ module RelatonBib
5
+ class BibtexParser
6
+ class << self
7
+ # @param bibtex [String]
8
+ # @return [Hash{String=>RelatonBib::BibliographicItem}]
9
+ def from_bibtex(bibtex)
10
+ BibTeX.parse(bibtex).reduce({}) do |h, bt|
11
+ h[bt.key] = BibliographicItem.new(
12
+ id: bt.key,
13
+ docid: fetch_docid(bt),
14
+ fetched: fetch_fetched(bt),
15
+ type: fetch_type(bt),
16
+ title: fetch_title(bt),
17
+ contributor: fetch_contributor(bt),
18
+ date: fetch_date(bt),
19
+ place: fetch_place(bt),
20
+ biblionote: fetch_note(bt),
21
+ relation: fetch_relation(bt),
22
+ extent: fetch_extent(bt),
23
+ edition: bt["edition"]&.to_s,
24
+ series: fetch_series(bt),
25
+ link: fetch_link(bt),
26
+ language: fetch_language(bt),
27
+ classification: fetch_classification(bt)
28
+ )
29
+ h
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ # @param bibtex [BibTeX::Entry]
36
+ # @return [Array<RelatonBib::DocumentIdentifier>]
37
+ def fetch_docid(bibtex)
38
+ docid = []
39
+ docid << DocumentIdentifier.new(id: bibtex.isbn.to_s, type: "isbn") if bibtex["isbn"]
40
+ docid << DocumentIdentifier.new(id: bibtex.lccn.to_s, type: "lccn") if bibtex["lccn"]
41
+ docid << DocumentIdentifier.new(id: bibtex.issn.to_s, type: "issn") if bibtex["issn"]
42
+ docid
43
+ end
44
+
45
+ # @param bibtex [BibTeX::Entry]
46
+ # @return [String, NilClass]
47
+ def fetch_fetched(bibtex)
48
+ Date.parse(bibtex.timestamp.to_s) if bibtex["timestamp"]
49
+ end
50
+
51
+ # @param bibtex [BibTeX::Entry]
52
+ # @return [String]
53
+ def fetch_type(bibtex)
54
+ case bibtex.type
55
+ when :mastersthesis, :phdthesis then "thesis"
56
+ when :conference then "inproceedings"
57
+ when :misc then "standard"
58
+ else bibtex.type.to_s
59
+ end
60
+ end
61
+
62
+ # @param bibtex [BibTeX::Entry]
63
+ # @return [Array<Hash>]
64
+ def fetch_place(bibtex)
65
+ bibtex["address"] ? [bibtex.address.to_s] : []
66
+ end
67
+
68
+ # @param bibtex [BibTeX::Entry]
69
+ # @return [Array<Hash>]
70
+ def fetch_title(bibtex)
71
+ title = []
72
+ title << { type: "main", content: bibtex.title.to_s } if bibtex["title"]
73
+ title << { type: "main", content: bibtex.subtitle.to_s } if bibtex["subtitle"]
74
+ title
75
+ end
76
+
77
+ # @param bibtex [BibTeX::Entry]
78
+ # @return [Array<Hash>]
79
+ def fetch_contributor(bibtex)
80
+ contributor = []
81
+ fetch_person(bibtex["author"]).each do |entity|
82
+ contributor << { entity: entity, role: [{ type: "author" }] }
83
+ end
84
+
85
+ fetch_person(bibtex["editor"]).each do |entity|
86
+ contributor << { entity: entity, role: [{ type: "editor" }] }
87
+ end
88
+
89
+ if bibtex["publisher"]
90
+ contributor << { entity: { name: bibtex.publisher.to_s }, role: [{ type: "publisher" }] }
91
+ end
92
+
93
+ if bibtex["institution"]
94
+ contributor << {
95
+ entity: { name: bibtex.institution.to_s },
96
+ role: [{ type: "distributor", description: ["sponsor"] }]
97
+ }
98
+ end
99
+
100
+ if bibtex["organization"]
101
+ contributor << {
102
+ entity: { name: bibtex.organization.to_s },
103
+ role: [{ type: "distributor", description: ["sponsor"] }]
104
+ }
105
+ end
106
+
107
+ if bibtex["school"]
108
+ contributor << {
109
+ entity: { name: bibtex.school.to_s },
110
+ role: [{ type: "distributor", description: ["sponsor"] }]
111
+ }
112
+ end
113
+ contributor
114
+ end
115
+
116
+ # @param bibtex [BibTeX::Entry]
117
+ # @return [Array<RelatonBib::Person>]
118
+ def fetch_person(person)
119
+ return [] unless person
120
+
121
+ person.map do |name|
122
+ parts = name.split ", "
123
+ surname = LocalizedString.new parts.first
124
+ fname = parts.size > 1 ? parts[1].split : []
125
+ forename = fname.map { |fn| LocalizedString.new fn }
126
+ Person.new name: FullName.new(surname: surname, forename: forename)
127
+ end
128
+ end
129
+
130
+ # @param bibtex [BibTeX::Entry]
131
+ # @return [Array<Hash>]
132
+ def fetch_date(bibtex)
133
+ date = []
134
+ if bibtex["year"]
135
+ on = Date.new(bibtex.year.to_i, bibtex["month_numeric"]&.to_i || 1).to_s
136
+ date << { type: "published", on: on }
137
+ end
138
+
139
+ if bibtex["urldate"]
140
+ date << { type: "accessed", on: Date.parse(bibtex.urldate.to_s).to_s }
141
+ end
142
+
143
+ date
144
+ end
145
+
146
+ # @param bibtex [BibTeX::Entry]
147
+ # @return [Array<RelatonBib::BiblioNote>]
148
+ def fetch_note(bibtex)
149
+ note = []
150
+ note << BiblioNote.new(type: "annote", content: bibtex.annote.to_s) if bibtex["annote"]
151
+
152
+ if bibtex["howpublished"]
153
+ note << BiblioNote.new(type: "howpublished", content: bibtex.howpublished.to_s)
154
+ end
155
+
156
+ note << BiblioNote.new(type: "comment", content: bibtex.comment.to_s) if bibtex["comment"]
157
+ note << BiblioNote.new(content: bibtex.note.to_s) if bibtex["note"]
158
+ note << BiblioNote.new(type: "tableOfContents", content: bibtex["content"]) if bibtex["content"]
159
+ note
160
+ end
161
+
162
+ # @param bibtex [BibTeX::Entry]
163
+ # @return [Array<Hash>]
164
+ def fetch_relation(bibtex)
165
+ return [] unless bibtex["booktitle"]
166
+
167
+ title = TypedTitleString.new(type: "main", content: bibtex.booktitle.to_s)
168
+ [{ type: "partOf", bibitem: BibliographicItem.new(title: [title]) }]
169
+ end
170
+
171
+ # @param bibtex [BibTeX::Entry]
172
+ # @return [Array<RelatonBib::BibItemLocality>]
173
+ def fetch_extent(bibtex)
174
+ extent = []
175
+ extent << BibItemLocality.new("chapter", bibtex.chapter.to_s) if bibtex["chapter"]
176
+
177
+ if bibtex["pages"]
178
+ from, to = bibtex.pages.to_s.split "-"
179
+ extent << BibItemLocality.new("page", from, to)
180
+ end
181
+
182
+ extent << BibItemLocality.new("volume", bibtex.volume.to_s) if bibtex["volume"]
183
+ extent
184
+ end
185
+
186
+ # @param bibtex [BibTeX::Entry]
187
+ # @return [Array<RelatonBib::Series>]
188
+ def fetch_series(bibtex)
189
+ series = []
190
+ if bibtex["journal"]
191
+ series << Series.new(
192
+ type: "journal",
193
+ title: TypedTitleString.new(content: bibtex.journal.to_s),
194
+ number: bibtex["number"]&.to_s
195
+ )
196
+ end
197
+
198
+ if bibtex["series"]
199
+ title = TypedTitleString.new content: bibtex.series.to_s
200
+ series << Series.new(title: title)
201
+ end
202
+ series
203
+ end
204
+
205
+ # @param bibtex [BibTeX::Entry]
206
+ # @return [Array<RelatonBib::TypedUri>]
207
+ def fetch_link(bibtex)
208
+ link = []
209
+ link << TypedUri.new(type: "src", content: bibtex.url.to_s) if bibtex["url"]
210
+ link << TypedUri.new(type: "doi", content: bibtex.doi.to_s) if bibtex["doi"]
211
+ link << TypedUri.new(type: "file", content: bibtex.file2.to_s) if bibtex["file2"]
212
+ link
213
+ end
214
+
215
+ # @param bibtex [BibTeX::Entry]
216
+ # @return [Array<String>]
217
+ def fetch_language(bibtex)
218
+ return [] unless bibtex["language"]
219
+
220
+ [Iso639[bibtex.language.to_s].alpha2]
221
+ end
222
+
223
+ # @param bibtex [BibTeX::Entry]
224
+ # @return [RelatonBib::Classification, NilClass]
225
+ def fetch_classification(bibtex)
226
+ cls = []
227
+ cls << Classification.new(type: "type", value: bibtex["type"].to_s) if bibtex["type"]
228
+ cls << Classification.new(type: "keyword", value: bibtex.keywords.to_s) if bibtex["keywords"]
229
+ if bibtex["mendeley-tags"]
230
+ cls << Classification.new(type: "mendeley", value: bibtex["mendeley-tags"].to_s)
231
+ end
232
+ cls
233
+ end
234
+ end
235
+ end
236
+ end
@@ -22,7 +22,7 @@ module RelatonBib
22
22
  # @param description [Array<String>]
23
23
  def initialize(**args)
24
24
  if args[:type] && !TYPES.include?(args[:type])
25
- raise ArgumentError, %{Type "#{type}" is invalid.}
25
+ warn %{[relaton-bib] Contributor's type "#{args[:type]}" is invalid.}
26
26
  end
27
27
 
28
28
  @type = args[:type]
@@ -84,7 +84,9 @@ module RelatonBib
84
84
  def place_hash_to_bib(ret)
85
85
  return unless ret[:place]
86
86
 
87
- ret[:place] = array(ret[:place])
87
+ ret[:place] = array(ret[:place]).map do |pl|
88
+ pl.is_a?(String) ? Place.new(name: pl) : Place.new(pl)
89
+ end
88
90
  end
89
91
 
90
92
  def accesslocation_hash_to_bib(ret)
@@ -130,10 +132,14 @@ module RelatonBib
130
132
 
131
133
  ret[:biblionote] = array(ret[:biblionote])
132
134
  (ret[:biblionote])&.each_with_index do |n, i|
133
- ret[:biblionote][i] = BiblioNote.new(
134
- content: n[:content], type: n[:type], language: n[:language],
135
- script: n[:script], format: n[:format]
136
- )
135
+ ret[:biblionote][i] = if n.is_a?(String)
136
+ BiblioNote.new content: n
137
+ else
138
+ BiblioNote.new(
139
+ content: n[:content], type: n[:type], language: n[:language],
140
+ script: n[:script], format: n[:format]
141
+ )
142
+ end
137
143
  end
138
144
  end
139
145
 
@@ -308,7 +314,7 @@ module RelatonBib
308
314
  # ret[:classification][i] = RelatonBib::Classification.new(c)
309
315
  # end
310
316
  if ret[:classification]
311
- ret[:classification] = Classification.new(ret[:classification])
317
+ ret[:classification] = array(ret[:classification]).map { |cls| Classification.new cls }
312
318
  end
313
319
  end
314
320
 
@@ -0,0 +1,37 @@
1
+ module RelatonBib
2
+ class Place
3
+ # @return [String]
4
+ attr_reader :name
5
+
6
+ # @return [String, NilClass]
7
+ attr_reader :uri, :region
8
+
9
+ # @param name [String]
10
+ # @param uri [String, NilClass]
11
+ # @param region [String, NilClass]
12
+ def initialize(name:, uri: nil, region: nil)
13
+ @name = name
14
+ @uri = uri
15
+ @region = region
16
+ end
17
+
18
+ # @param builder [Nologiri::XML::Builder]
19
+ def to_xml(builder)
20
+ xml = builder.place name
21
+ xml[:uri] = uri if uri
22
+ xml[:region] = region if region
23
+ end
24
+
25
+ # @return [Hash]
26
+ def to_hash
27
+ if uri || region
28
+ hash = { name: name }
29
+ hash["uri"] = uri if uri
30
+ hash["region"] = region if region
31
+ hash
32
+ else
33
+ name
34
+ end
35
+ end
36
+ end
37
+ end
@@ -55,7 +55,7 @@ module RelatonBib
55
55
  end
56
56
 
57
57
  if args[:type] && !TYPES.include?(args[:type])
58
- raise ArgumentError, "invalid argument `type`"
58
+ warn "[relaton-bib] Series type is invalid: #{args[:type]}"
59
59
  end
60
60
 
61
61
  @type = args[:type] # if %w[main alt].include? args[:type]
@@ -67,7 +67,7 @@ module RelatonBib
67
67
  @from = args[:from]
68
68
  @to = args[:to]
69
69
  @number = args[:number]
70
- @partnumber = args[:partnumber]
70
+ @partnumber = args[:partnumber]
71
71
  end
72
72
  # rubocop:enable Metrics/MethodLength
73
73
 
@@ -17,7 +17,7 @@ module RelatonBib
17
17
  # @param script [String]
18
18
  def initialize(**args)
19
19
  if args[:type] && !TITLE_TYPES.include?(args[:type])
20
- raise ArgumentError, %{The type #{args[:type]} is invalid.}
20
+ warn %{[relaton-bib] title type "#{args[:type]}" is invalid.}
21
21
  end
22
22
 
23
23
  unless args[:title] || args[:content]
@@ -1,3 +1,3 @@
1
1
  module RelatonBib
2
- VERSION = "0.4.1".freeze
2
+ VERSION = "0.5.0".freeze
3
3
  end
@@ -38,7 +38,7 @@ module RelatonBib
38
38
  relation: fetch_relations(bibitem),
39
39
  series: fetch_series(bibitem),
40
40
  medium: fetch_medium(bibitem),
41
- place: bibitem.xpath("./place").map(&:text),
41
+ place: fetch_place(bibitem),
42
42
  extent: fetch_extent(bibitem),
43
43
  accesslocation: bibitem.xpath("./accesslocation").map(&:text),
44
44
  classification: fetch_classification(bibitem),
@@ -56,6 +56,12 @@ module RelatonBib
56
56
  RelatonBib::BibliographicItem::Version.new revision_date, draft
57
57
  end
58
58
 
59
+ def fetch_place(item)
60
+ item.xpath("./place").map do |pl|
61
+ Place.new(name: pl.text, uri: pl[:uri], region: pl[:region])
62
+ end
63
+ end
64
+
59
65
  def fetch_note(item)
60
66
  item.xpath("./note").map do |n|
61
67
  BiblioNote.new(
@@ -113,10 +119,9 @@ module RelatonBib
113
119
  end
114
120
 
115
121
  def fetch_classification(item)
116
- cls = item.at "classification"
117
- return unless cls
118
-
119
- Classification.new type: cls[:type], value: cls.text
122
+ item.xpath("classification").map do |cls|
123
+ Classification.new type: cls[:type], value: cls.text
124
+ end
120
125
  end
121
126
 
122
127
  def fetch_validity(item)
data/relaton-bib.gemspec CHANGED
@@ -23,7 +23,6 @@ Gem::Specification.new do |spec|
23
23
  spec.require_paths = ["lib"]
24
24
  spec.required_ruby_version = Gem::Requirement.new(">= 2.4.0")
25
25
 
26
- spec.add_development_dependency "bundler", "~> 2.0"
27
26
  spec.add_development_dependency "debase"
28
27
  spec.add_development_dependency "equivalent-xml", "~> 0.6"
29
28
  spec.add_development_dependency "rake", "~> 10.0"
@@ -34,5 +33,7 @@ Gem::Specification.new do |spec|
34
33
  spec.add_development_dependency "byebug"
35
34
 
36
35
  spec.add_dependency "addressable"
36
+ spec.add_dependency "bibtex-ruby"
37
+ spec.add_dependency "iso639"
37
38
  spec.add_dependency "nokogiri"
38
39
  end
metadata CHANGED
@@ -1,29 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: relaton-bib
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-12-16 00:00:00.000000000 Z
11
+ date: 2020-01-11 00:00:00.000000000 Z
12
12
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: bundler
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: '2.0'
20
- type: :development
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: '2.0'
27
13
  - !ruby/object:Gem::Dependency
28
14
  name: debase
29
15
  requirement: !ruby/object:Gem::Requirement
@@ -150,6 +136,34 @@ dependencies:
150
136
  - - ">="
151
137
  - !ruby/object:Gem::Version
152
138
  version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: bibtex-ruby
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :runtime
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: iso639
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :runtime
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
153
167
  - !ruby/object:Gem::Dependency
154
168
  name: nokogiri
155
169
  requirement: !ruby/object:Gem::Requirement
@@ -184,6 +198,7 @@ files:
184
198
  - README.adoc
185
199
  - Rakefile
186
200
  - bin/console
201
+ - bin/rspec
187
202
  - bin/setup
188
203
  - docs/hash.adoc
189
204
  - lib/relaton_bib.rb
@@ -192,6 +207,7 @@ files:
192
207
  - lib/relaton_bib/biblio_version.rb
193
208
  - lib/relaton_bib/bibliographic_date.rb
194
209
  - lib/relaton_bib/bibliographic_item.rb
210
+ - lib/relaton_bib/bibtex_parser.rb
195
211
  - lib/relaton_bib/classification.rb
196
212
  - lib/relaton_bib/contribution_info.rb
197
213
  - lib/relaton_bib/contributor.rb
@@ -210,6 +226,7 @@ files:
210
226
  - lib/relaton_bib/medium.rb
211
227
  - lib/relaton_bib/organization.rb
212
228
  - lib/relaton_bib/person.rb
229
+ - lib/relaton_bib/place.rb
213
230
  - lib/relaton_bib/series.rb
214
231
  - lib/relaton_bib/typed_title_string.rb
215
232
  - lib/relaton_bib/typed_uri.rb