bibtex-ruby 3.0.1 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.

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