bibtex-ruby 3.0.1 → 3.1.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.

Potentially problematic release.


This version of bibtex-ruby might be problematic. Click here for more details.

@@ -0,0 +1,44 @@
1
+ require 'rexml/document'
2
+
3
+ class BibTeX::Entry::BibTeXMLConverter
4
+ def self.convert(bibtex, options = {})
5
+ new(bibtex, options).convert!
6
+ end
7
+
8
+ def initialize(bibtex, options = {})
9
+ @bibtex = bibtex
10
+ @options = options
11
+ end
12
+
13
+ def convert!
14
+ xml = REXML::Element.new('bibtex:entry')
15
+ xml.attributes['id'] = bibtex.key
16
+
17
+ fields
18
+
19
+ xml.add_element(entry)
20
+ xml
21
+ end
22
+
23
+ def fields
24
+ bibtex.fields.each do |key, value|
25
+ field = REXML::Element.new("bibtex:#{key}")
26
+
27
+ if options[:extended] && value.name?
28
+ value.each { |n| entry.add_element(n.to_xml) }
29
+ else
30
+ field.text = value.to_s(options)
31
+ end
32
+
33
+ entry.add_element(field)
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ attr_reader :bibtex, :options
40
+
41
+ def entry
42
+ @entry ||= REXML::Element.new("bibtex:#{bibtex.type}")
43
+ end
44
+ end
@@ -0,0 +1,110 @@
1
+ class BibTeX::Entry::CiteProcConverter
2
+ CSL_FILTER = Hash.new { |h, k| k }.merge(Hash[*%w{
3
+ date issued
4
+ isbn ISBN
5
+ booktitle container-title
6
+ journal container-title
7
+ series collection-title
8
+ address publisher-place
9
+ pages page
10
+ number issue
11
+ url URL
12
+ doi DOI
13
+ year issued
14
+ type genre
15
+ }.map(&:intern)]).freeze
16
+
17
+ CSL_FIELDS = %w{
18
+ abstract annote archive archive_location archive-place
19
+ authority call-number chapter-number citation-label citation-number
20
+ collection-title container-title DOI edition event event-place
21
+ first-reference-note-number genre ISBN issue jurisdiction keyword locator
22
+ medium note number number-of-pages number-of-volumes original-publisher
23
+ original-publisher-place original-title page page-first publisher
24
+ publisher-place references section status title URL version volume
25
+ year-suffix accessed container event-date issued original-date
26
+ author editor translator recipient interviewer publisher composer
27
+ original-publisher original-author container-author collection-editor
28
+ }.map(&:intern).freeze
29
+
30
+ CSL_TYPES = Hash.new { |h, k| k }.merge(Hash[*%w{
31
+ booklet pamphlet
32
+ conference paper-conference
33
+ inbook chapter
34
+ incollection chapter
35
+ inproceedings paper-conference
36
+ manual book
37
+ mastersthesis thesis
38
+ misc article
39
+ phdthesis thesis
40
+ proceedings paper-conference
41
+ techreport report
42
+ unpublished manuscript
43
+ article article-journal
44
+ }.map(&:intern)]).freeze
45
+
46
+ def self.convert(bibtex, options = {})
47
+ new(bibtex, options).convert!
48
+ end
49
+
50
+ def initialize(bibtex, options = {})
51
+ @bibtex = bibtex
52
+ @options = { quotes: [] }.merge(options)
53
+ end
54
+
55
+ def convert!
56
+ bibtex.parse_names
57
+ bibtex.parse_month
58
+
59
+ bibtex.each_pair do |key, value|
60
+ hash[CSL_FILTER[key].to_s] = value.to_citeproc(options) unless BibTeX::Entry::DATE_FIELDS.include?(key)
61
+ end
62
+
63
+ methods = self.class.instance_methods(false) - [:convert!]
64
+ methods.each { |m| send(m) }
65
+
66
+ hash
67
+ end
68
+
69
+ def date
70
+ return unless bibtex.field?(:year)
71
+
72
+ case bibtex[:year].to_s
73
+ when /^\d+$/
74
+ parts = [bibtex[:year].to_s]
75
+
76
+ if bibtex.field?(:month)
77
+ parts.push BibTeX::Entry::MONTHS.find_index(bibtex[:month].to_s.intern)
78
+ parts[1] = parts[1] + 1 unless parts[1].nil?
79
+ end
80
+
81
+ hash['issued'] = { 'date-parts' => [parts.compact.map(&:to_i)] }
82
+ else
83
+ hash['issued'] = { 'literal' => bibtex[:year].to_s }
84
+ end
85
+ end
86
+
87
+ def key
88
+ hash['id'] = bibtex.key.to_s
89
+ end
90
+
91
+ def type
92
+ hash['type'] = CSL_TYPES[bibtex.type].to_s
93
+
94
+ return if hash.key?('genre')
95
+ case bibtex.type
96
+ when :mastersthesis
97
+ hash['genre'] = "Master's thesis"
98
+ when :phdthesis
99
+ hash['genre'] = 'PhD thesis'
100
+ end
101
+ end
102
+
103
+ private
104
+
105
+ attr_reader :bibtex, :options
106
+
107
+ def hash
108
+ @hash ||= {}
109
+ end
110
+ end
@@ -0,0 +1,543 @@
1
+ require 'uri/common'
2
+
3
+ class BibTeX::Entry::RDFConverter
4
+ DEFAULT_REMOVE_FROM_FALLBACK = %w(
5
+ date-modified
6
+ bdsk-file-1
7
+ bdsk-file-2
8
+ bdsk-file-3
9
+ ).map(&:intern).freeze
10
+
11
+ BIBO_TYPES = Hash[*%w{
12
+ article Article
13
+ book Book
14
+ booklet Book
15
+ collection Collection
16
+ conference AcademicArticle
17
+ inbook BookSection
18
+ incollection BookSection
19
+ inproceedings AcademicArticle
20
+ journal Journal
21
+ manual Manual
22
+ mastersthesis Thesis
23
+ online Website
24
+ patent Patent
25
+ periodical Periodical
26
+ phdthesis Thesis
27
+ proceedings Proceedings
28
+ standard Standard
29
+ techreport Report
30
+ thesis Thesis
31
+ unpublished Manuscript
32
+ }.map(&:intern)].freeze
33
+
34
+ # converts a BibTeX entry to RDF
35
+ # @return [RDF::Graph] the RDF graph of this entry
36
+ def self.convert(bibtex, graph = RDF::Graph.new, agent = {})
37
+ new(bibtex, graph, agent).convert!
38
+ end
39
+
40
+ # @param [BibTeX::Entry] the entry to convert
41
+ def initialize(bibtex, graph = RDF::Graph.new, agent = {})
42
+ @bibtex = bibtex
43
+ @graph = graph
44
+ @agent = agent
45
+ end
46
+
47
+ # @return [RDF::Graph] the RDF graph of this entry
48
+ def convert!
49
+ bibtex.parse_names
50
+ bibtex.parse_month
51
+
52
+ unless uri_in_graph?(entry)
53
+ methods = self.class.instance_methods(false) - [:convert!]
54
+ methods.each { |m| send(m) }
55
+ run_fallback
56
+ end
57
+
58
+ graph
59
+ end
60
+
61
+ def abstract
62
+ return unless bibtex.field?(:abstract)
63
+ remove_from_fallback(:abstract)
64
+
65
+ graph << [entry, RDF::DC.abstract, bibtex[:abstract].to_s]
66
+ graph << [entry, bibo[:abstract], bibtex[:abstract].to_s]
67
+ end
68
+
69
+ def author
70
+ return unless bibtex.field?(:author)
71
+ remove_from_fallback(:author)
72
+
73
+ seq = RDF::Node.new
74
+
75
+ graph << [seq, RDF.type, RDF[:Seq]]
76
+ graph << [entry, bibo[:authorList], seq]
77
+
78
+ bibtex[:author].each do |name|
79
+ node = agent(name) { create_agent(name, :Person) }
80
+
81
+ graph << [entry, RDF::DC.creator, node]
82
+ graph << [seq, RDF.li, node]
83
+ end
84
+ end
85
+
86
+ def booktitle
87
+ return unless bibtex.field?(:booktitle)
88
+ remove_from_fallback(:booktitle)
89
+ return if bibtex.has_parent? &&
90
+ bibtex.parent[:title] == bibtex[:booktitle]
91
+ return if bibtex.has_parent? &&
92
+ bibtex.parent[:booktitle] == bibtex[:booktitle]
93
+ return if bibtex.has_parent? &&
94
+ bibtex.parent[:isbn] == bibtex[:isbn]
95
+ return if bibtex[:title] == bibtex[:booktitle]
96
+
97
+ series = RDF::Node.new
98
+ graph << [series, RDF.type, bibo[:Document]]
99
+ graph << [series, RDF::DC.title, bibtex[:booktitle].to_s]
100
+
101
+ graph << [entry, RDF::DC.isPartOf, series]
102
+ end
103
+
104
+ def chapter
105
+ return unless bibtex.field?(:chapter)
106
+ remove_from_fallback(:chapter)
107
+
108
+ graph << [entry, bibo[:chapter], bibtex[:chapter].to_s]
109
+ end
110
+
111
+ def children
112
+ return unless bibtex.has_children?
113
+
114
+ bibtex.children.each do |child|
115
+ child_id = RDF::URI.new(child.identifier)
116
+ BibTeX::Entry::RDFConverter.new(child, graph, agent).convert! unless uri_in_graph?(child_id)
117
+ graph << [entry, RDF::DC.hasPart, child_id]
118
+ end
119
+ end
120
+
121
+ def copyright
122
+ return unless bibtex.field?(:copyright)
123
+ remove_from_fallback(:copyright)
124
+
125
+ graph << [entry, RDF::DC.rightsHolder, bibtex[:copyright].to_s]
126
+ end
127
+
128
+ def date_added
129
+ return unless bibtex.field?(:'date-added')
130
+ remove_from_fallback(:'date-added')
131
+
132
+ graph << [entry, RDF::DC.created, bibtex[:'date-added'].to_s]
133
+ end
134
+
135
+ def doi
136
+ return unless bibtex.field?(:doi)
137
+ remove_from_fallback(:doi)
138
+
139
+ graph << [entry, bibo[:doi], bibtex[:doi].to_s]
140
+ graph << [entry, RDF::DC.identifier, "doi:#{bibtex[:doi].to_s}"]
141
+ end
142
+
143
+ def edition
144
+ return unless bibtex.field?(:edition)
145
+ remove_from_fallback(:edition)
146
+
147
+ graph << [entry, bibo[:edition], bibtex[:edition].to_s]
148
+ end
149
+
150
+ def editor
151
+ return unless bibtex.field?(:editor)
152
+ remove_from_fallback(:editor)
153
+
154
+ seq = RDF::Node.new
155
+
156
+ graph << [seq, RDF.type, RDF[:Seq]]
157
+ graph << [entry, bibo[:editorList], seq]
158
+
159
+ bibtex[:editor].each do |name|
160
+ node = agent(name) { create_agent(name, :Person) }
161
+
162
+ graph << [entry, bibo.name, node]
163
+ graph << [seq, RDF.li, node]
164
+ end
165
+ end
166
+
167
+ def fallback_default
168
+ remove_from_fallback(*DEFAULT_REMOVE_FROM_FALLBACK)
169
+ end
170
+
171
+ def howpublished
172
+ return unless bibtex.field?(:howpublished)
173
+ return unless bibtex[:howpublished] =~ /^#{URI.regexp}$/
174
+ remove_from_fallback(:howpublished)
175
+
176
+ graph << [entry, RDF::DC.URI, bibtex[:howpublished].to_s]
177
+ graph << [entry, bibo[:uri], bibtex[:howpublished].to_s]
178
+ end
179
+
180
+ def institution
181
+ return unless bibtex.field?(:institution)
182
+ remove_from_fallback(:institution)
183
+
184
+ org = agent(bibtex[:institution].to_s) { create_agent(bibtex[:institution].to_s, :Organization) }
185
+
186
+ graph << [entry, RDF::DC.contributor, org]
187
+ end
188
+
189
+ def isbn
190
+ return unless bibtex.field?(:isbn)
191
+ remove_from_fallback(:isbn)
192
+
193
+ graph << [entry, bibo[:isbn], bibtex[:isbn].to_s]
194
+
195
+ if bibtex.contained?
196
+ graph << [entry, RDF::DC.isPartOf, "urn:isbn:#{bibtex[:isbn].to_s}"]
197
+ else
198
+ graph << [entry, RDF::DC.identifier, "urn:isbn:#{bibtex[:isbn].to_s}"]
199
+ end
200
+ end
201
+
202
+ def issn
203
+ return unless bibtex.field?(:issn)
204
+ remove_from_fallback(:issn)
205
+
206
+ graph << [entry, bibo[:issn], bibtex[:issn].to_s]
207
+ if bibtex.contained?
208
+ graph << [entry, RDF::DC.isPartOf, "urn:issn:#{bibtex[:issn].to_s}"]
209
+ else
210
+ graph << [entry, RDF::DC.identifier, "urn:issn:#{bibtex[:issn].to_s}"]
211
+ end
212
+ end
213
+
214
+ def journal_dc_source
215
+ return unless bibtex.field?(:journal)
216
+ remove_from_fallback(:journal)
217
+
218
+ source = []
219
+ source << bibtex[:journal].to_s
220
+ source << "Vol. #{bibtex[:volume].to_s}" if bibtex.field?(:volume)
221
+ source << "No. #{bibtex[:number].to_s}" if bibtex.field?(:number)
222
+ pagination = bibtex[:pagination] || 'pp.'
223
+ source << "#{pagination.to_s} #{bibtex[:pages].to_s}" if bibtex.field?(:pages)
224
+ graph << [entry, RDF::DC.source, source.join(', ')]
225
+ end
226
+
227
+ def journal_dc_part_of
228
+ return unless bibtex.field?(:journal)
229
+ return if bibtex.has_parent? && bibtex.parent[:title] == bibtex[:journal]
230
+ return if bibtex.has_parent? && bibtex.parent[:issn] == bibtex[:issn]
231
+
232
+ journal = RDF::Node.new
233
+ graph << [journal, RDF.type, bibo[:Journal]]
234
+ graph << [journal, RDF::DC.title, bibtex[:journal].to_s]
235
+
236
+ graph << [entry, RDF::DC.isPartOf, journal]
237
+ end
238
+
239
+ def key
240
+ graph << [entry, RDF::DC.identifier, "urn:bibtex:#{bibtex.key}"]
241
+ end
242
+
243
+ def keywords
244
+ return unless bibtex.field?(:keywords)
245
+ remove_from_fallback(:keywords)
246
+
247
+ bibtex[:keywords].to_s.split(/\s*,\s*/).each do |keyword|
248
+ graph << [entry, RDF::DC.subject, keyword]
249
+ end
250
+ end
251
+
252
+ def language
253
+ return unless bibtex.field?(:language)
254
+ remove_from_fallback(:language)
255
+
256
+ bibtex[:language] = 'german' if bibtex[:language] == 'ngerman'
257
+
258
+ graph << [entry, RDF::DC.language, bibtex[:language].to_s]
259
+ end
260
+
261
+ def location
262
+ return unless bibtex.field?(:location)
263
+ remove_from_fallback(:location)
264
+
265
+ graph << [entry, RDF::DC.Location, bibtex[:location].to_s]
266
+ if [:proceedings, :inproceedings, :conference].include?(bibtex.type)
267
+ event = RDF::Vocabulary.new('http://purl.org/NET/c4dm/event.owl')
268
+ graph << [entry, event[:place], org]
269
+ end
270
+ end
271
+
272
+ def lccn
273
+ return unless bibtex.field?(:lccn)
274
+ remove_from_fallback(:lccn)
275
+
276
+ graph << [entry, bibo[:lccn], bibtex[:lccn].to_s]
277
+ end
278
+
279
+ def note
280
+ return unless bibtex.field?(:note)
281
+ remove_from_fallback(:note)
282
+
283
+ pub = RDF::Node.new
284
+ graph << [pub, RDF.type, bibo[:Note]]
285
+ graph << [pub, bibo[:content], bibtex[:note]]
286
+
287
+ graph << [entry, bibo[:annotates], pub]
288
+ end
289
+
290
+ def number
291
+ return unless bibtex.field?(:number)
292
+ remove_from_fallback(:number)
293
+
294
+ case bibtex.type
295
+ when :techreport || :manual || :unpublished
296
+ graph << [entry, bibo[:number], bibtex[:number].to_s]
297
+ else
298
+ graph << [entry, bibo[:issue], bibtex[:number].to_s]
299
+ end
300
+ end
301
+
302
+ def organization
303
+ return unless bibtex.field?(:organization)
304
+ remove_from_fallback(:organization)
305
+
306
+ org = agent(bibtex[:organization].to_s) { create_agent(bibtex[:organization].to_s, :Organization) }
307
+
308
+ graph << [entry, RDF::DC.contributor, org]
309
+ graph << [entry, bibo[:organizer], org] if [:proceedings, :inproceedings, :conference].include?(bibtex.type)
310
+ end
311
+
312
+ def pages
313
+ return unless bibtex.field?(:pages)
314
+ remove_from_fallback(:pages)
315
+
316
+ if bibtex[:pages].to_s =~ /^\s*(\d+)\s*-+\s*(\d+)\s*$/
317
+ graph << [entry, bibo[:pageStart], Regexp.last_match[1]]
318
+ graph << [entry, bibo[:pageEnd], Regexp.last_match[2]]
319
+ else
320
+ graph << [entry, bibo[:pages], bibtex[:pages].to_s]
321
+ end
322
+ end
323
+
324
+ def pagetotal
325
+ return unless bibtex.field?(:pagetotal)
326
+ remove_from_fallback(:pagetotal)
327
+
328
+ graph << [entry, bibo[:numPages], bibtex[:pagetotal].to_s]
329
+ end
330
+
331
+ def parent
332
+ return unless bibtex.has_parent?
333
+ remove_from_fallback(:crossref)
334
+
335
+ parent_id = RDF::URI.new(bibtex.parent.identifier)
336
+ BibTeX::Entry::RDFConverter.new(bibtex.parent, graph, agent).convert! unless uri_in_graph?(parent_id)
337
+ graph << [entry, RDF::DC.isPartOf, parent_id]
338
+ end
339
+
340
+ def publisher
341
+ return unless bibtex.field?(:publisher) || bibtex.field?(:organization) || bibtex.field?(:school)
342
+ remove_from_fallback(:publisher, :address)
343
+
344
+ org =
345
+ case
346
+ when bibtex.field?(:publisher)
347
+ agent(bibtex[:publisher].to_s) { create_agent(bibtex[:publisher].to_s, :Organization) }
348
+ when bibtex.field?(:organization)
349
+ agent(bibtex[:organization].to_s) { create_agent(bibtex[:organization].to_s, :Organization) }
350
+ when bibtex.field?(:school)
351
+ agent(bibtex[:school].to_s) { create_agent(bibtex[:school].to_s, :Organization) }
352
+ end
353
+
354
+ if bibtex.field?(:address)
355
+ address = RDF::Vocabulary.new('http://schemas.talis.com/2005/address/schema#')
356
+ graph << [org, address[:localityName], bibtex[:address]]
357
+ end
358
+
359
+ graph << [entry, RDF::DC.publisher, org]
360
+ graph << [entry, bibo[:publisher], org]
361
+ end
362
+
363
+ def school
364
+ return unless bibtex.field?(:school)
365
+ remove_from_fallback(:school)
366
+
367
+ org = agent(bibtex[:school].to_s) { create_agent(bibtex[:school].to_s, :Organization) }
368
+
369
+ graph << [entry, RDF::DC.contributor, org]
370
+ end
371
+
372
+ def series
373
+ return unless bibtex.field?(:series)
374
+ remove_from_fallback(:series)
375
+ return if bibtex.has_parent? && bibtex.parent[:title] == bibtex[:series]
376
+ return if bibtex.has_parent? && bibtex.parent[:series] == bibtex[:series]
377
+ return if bibtex.has_parent? && bibtex.parent[:issn] == bibtex[:issn]
378
+
379
+ series = RDF::Node.new
380
+ graph << [series, RDF.type, bibo[:MultiVolumeBook]]
381
+ graph << [series, RDF::DC.title, bibtex[:series].to_s]
382
+
383
+ graph << [entry, RDF::DC.isPartOf, series]
384
+ end
385
+
386
+ def thesis_degree
387
+ return unless bibo_class == :Thesis
388
+
389
+ degree =
390
+ case bibtex.type
391
+ # ms = masters degree in science
392
+ # Only ma and ms available. We simply chose one.
393
+ when :mastersthesis then bibo['degrees/ms']
394
+ when :phdthesis then bibo['degrees/phd']
395
+ end
396
+
397
+ degree =
398
+ case bibtex[:type]
399
+ when 'mathesis' then bibo['degrees/ma']
400
+ when 'phdthesis' then bibo['degrees/phd']
401
+ when /Bachelor['s]{0,2} Thesis/i then "Bachelor's Thesis"
402
+ when /Diplomarbeit/i then bibo['degrees/ms']
403
+ when /Magisterarbeit/i then bibo['degrees/ma']
404
+ else degree
405
+ end
406
+
407
+ graph << [entry, bibo[:degree], degree] unless degree.nil?
408
+ end
409
+
410
+ def title
411
+ return unless bibtex.field?(:title)
412
+ remove_from_fallback(:title)
413
+
414
+ title = [bibtex[:title].to_s, bibtex[:subtitle].to_s].join(': ')
415
+ graph << [entry, RDF::DC.title, title]
416
+ graph << [entry, bibo[:shortTitle], bibtex[:title].to_s] if bibtex.field?(:subtitle)
417
+ end
418
+
419
+ def translator
420
+ return unless bibtex.field?(:translator)
421
+ remove_from_fallback(:translator)
422
+
423
+ node = agent(bibtex[:translator].to_s) do
424
+ create_agent(bibtex[:translator].to_s, :Person)
425
+ end
426
+
427
+ graph << [entry, RDF::DC.contributor, node]
428
+ graph << [entry, bibo[:translator], node]
429
+ end
430
+
431
+ def type
432
+ graph << [entry, RDF.type, bibo_class]
433
+
434
+ case bibtex.type
435
+ when :proceedings, :journal
436
+ graph << [entry, RDF::DC.type, 'Collection']
437
+ else
438
+ graph << [entry, RDF::DC.type, 'Text']
439
+ end
440
+ end
441
+
442
+ def url
443
+ return unless bibtex.field?(:url)
444
+ remove_from_fallback(:url)
445
+
446
+ graph << [entry, RDF::DC.URI, bibtex[:url].to_s]
447
+ graph << [entry, bibo[:uri], bibtex[:url].to_s]
448
+ end
449
+
450
+ def volume
451
+ return unless bibtex.field?(:volume)
452
+ remove_from_fallback(:volume)
453
+
454
+ graph << [entry, bibo[:volume], bibtex[:volume].to_s]
455
+ end
456
+
457
+ def volumes
458
+ return unless bibtex.field?(:volumes)
459
+ remove_from_fallback(:volumes)
460
+
461
+ graph << [entry, bibo[:numVolumes], bibtex[:volumes].to_s]
462
+ end
463
+
464
+ def year
465
+ return unless bibtex.field?(:year)
466
+ remove_from_fallback(:year, :month)
467
+
468
+ year = bibtex[:year].to_s
469
+ if bibtex.field?(:month)
470
+ month = BibTeX::Entry::MONTHS.find_index(bibtex[:month].to_s.intern)
471
+ month += 1 unless month.nil?
472
+ end
473
+ date = [year, month].join('-')
474
+
475
+ graph << [entry, RDF::DC.issued, date]
476
+ end
477
+
478
+ private
479
+
480
+ attr_reader :bibtex, :graph
481
+
482
+ def bibo
483
+ @bibo ||= RDF::Vocabulary.new('http://purl.org/ontology/bibo/')
484
+ end
485
+
486
+ def bibo_class
487
+ BIBO_TYPES[bibtex[:type]] || BIBO_TYPES[bibtex.type] || :Document
488
+ end
489
+
490
+ def entry
491
+ @entry ||= RDF::URI.new(bibtex.identifier)
492
+ end
493
+
494
+ def agent(key = nil, &block)
495
+ if key.nil?
496
+ @agent
497
+ else
498
+ key = key.respond_to?(:to_hash) ? key.to_hash : key
499
+ @agent[key] ||= yield
500
+ end
501
+ end
502
+
503
+ def create_agent(name, type)
504
+ node = RDF::Node.new
505
+
506
+ graph << [node, RDF.type, RDF::FOAF[type]]
507
+ graph << [node, RDF::FOAF.name, name.to_s]
508
+
509
+ if name.is_a?(BibTeX::Name)
510
+ [:given, :family, :prefix, :suffix].each do |part|
511
+ value = name.send(part)
512
+ graph << [node, bibo["#{part}Name"], value.to_s] unless value.nil?
513
+ end
514
+ end
515
+
516
+ node
517
+ end
518
+
519
+ def uri_in_graph?(uri)
520
+ solutions = RDF::Query.execute(graph) do
521
+ pattern [uri, nil, nil]
522
+ end
523
+
524
+ solutions.size > 0
525
+ end
526
+
527
+ def fallback
528
+ @fallback ||= bibtex.fields.keys
529
+ end
530
+
531
+ def remove_from_fallback(*fields)
532
+ fields.each { |field| fallback.delete(field) }
533
+ end
534
+
535
+ def run_fallback
536
+ return if fallback.empty?
537
+
538
+ ml = RDF::Vocabulary.new('http://bibtexml.sf.net/')
539
+ fallback.each do |field|
540
+ graph << [entry, ml[field], bibtex[field]]
541
+ end
542
+ end
543
+ end