relaton-bib 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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