rdf 1.99.1 → 2.0.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/{README → README.md} +9 -44
- data/VERSION +1 -1
- data/bin/rdf +1 -1
- data/lib/rdf.rb +40 -49
- data/lib/rdf/changeset.rb +161 -0
- data/lib/rdf/cli.rb +195 -33
- data/lib/rdf/cli/vocab-loader.rb +13 -3
- data/lib/rdf/format.rb +44 -26
- data/lib/rdf/mixin/enumerable.rb +133 -97
- data/lib/rdf/mixin/enumerator.rb +8 -0
- data/lib/rdf/mixin/indexable.rb +1 -1
- data/lib/rdf/mixin/mutable.rb +101 -22
- data/lib/rdf/mixin/queryable.rb +21 -32
- data/lib/rdf/mixin/transactable.rb +94 -0
- data/lib/rdf/mixin/writable.rb +12 -3
- data/lib/rdf/model/dataset.rb +48 -0
- data/lib/rdf/model/graph.rb +73 -43
- data/lib/rdf/model/list.rb +61 -33
- data/lib/rdf/model/literal.rb +20 -19
- data/lib/rdf/model/literal/double.rb +20 -4
- data/lib/rdf/model/literal/numeric.rb +15 -13
- data/lib/rdf/model/node.rb +15 -16
- data/lib/rdf/model/statement.rb +1 -43
- data/lib/rdf/model/term.rb +10 -8
- data/lib/rdf/model/uri.rb +35 -34
- data/lib/rdf/model/value.rb +1 -1
- data/lib/rdf/nquads.rb +2 -11
- data/lib/rdf/ntriples.rb +1 -1
- data/lib/rdf/ntriples/reader.rb +33 -46
- data/lib/rdf/ntriples/writer.rb +42 -5
- data/lib/rdf/query.rb +6 -40
- data/lib/rdf/query/pattern.rb +4 -17
- data/lib/rdf/query/solutions.rb +6 -6
- data/lib/rdf/reader.rb +65 -14
- data/lib/rdf/repository.rb +365 -229
- data/lib/rdf/transaction.rb +211 -84
- data/lib/rdf/util.rb +1 -0
- data/lib/rdf/util/cache.rb +5 -5
- data/lib/rdf/util/file.rb +12 -9
- data/lib/rdf/util/logger.rb +272 -0
- data/lib/rdf/version.rb +2 -2
- data/lib/rdf/vocab/owl.rb +82 -77
- data/lib/rdf/vocab/rdfs.rb +22 -17
- data/lib/rdf/vocab/xsd.rb +5 -0
- data/lib/rdf/vocabulary.rb +50 -56
- data/lib/rdf/writer.rb +104 -52
- metadata +45 -90
- data/lib/rdf/mixin/inferable.rb +0 -5
- data/lib/rdf/vocab/cc.rb +0 -128
- data/lib/rdf/vocab/cert.rb +0 -245
- data/lib/rdf/vocab/dc.rb +0 -948
- data/lib/rdf/vocab/dc11.rb +0 -167
- data/lib/rdf/vocab/dcat.rb +0 -214
- data/lib/rdf/vocab/doap.rb +0 -337
- data/lib/rdf/vocab/exif.rb +0 -941
- data/lib/rdf/vocab/foaf.rb +0 -614
- data/lib/rdf/vocab/geo.rb +0 -157
- data/lib/rdf/vocab/gr.rb +0 -1501
- data/lib/rdf/vocab/ht.rb +0 -236
- data/lib/rdf/vocab/ical.rb +0 -528
- data/lib/rdf/vocab/ma.rb +0 -513
- data/lib/rdf/vocab/mo.rb +0 -2412
- data/lib/rdf/vocab/og.rb +0 -222
- data/lib/rdf/vocab/ogc.rb +0 -58
- data/lib/rdf/vocab/prov.rb +0 -1550
- data/lib/rdf/vocab/rsa.rb +0 -72
- data/lib/rdf/vocab/rss.rb +0 -66
- data/lib/rdf/vocab/schema.rb +0 -10569
- data/lib/rdf/vocab/sioc.rb +0 -669
- data/lib/rdf/vocab/skos.rb +0 -238
- data/lib/rdf/vocab/skosxl.rb +0 -57
- data/lib/rdf/vocab/v.rb +0 -383
- data/lib/rdf/vocab/vcard.rb +0 -841
- data/lib/rdf/vocab/vmd.rb +0 -383
- data/lib/rdf/vocab/void.rb +0 -186
- data/lib/rdf/vocab/vs.rb +0 -28
- data/lib/rdf/vocab/wdrs.rb +0 -134
- data/lib/rdf/vocab/wot.rb +0 -167
- data/lib/rdf/vocab/xhtml.rb +0 -8
- data/lib/rdf/vocab/xhv.rb +0 -505
data/lib/rdf/vocab/rdfs.rb
CHANGED
@@ -1,45 +1,50 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
+
# frozen_string_literal: true
|
2
3
|
# This file generated automatically using vocab-fetch from http://www.w3.org/2000/01/rdf-schema#
|
3
4
|
require 'rdf'
|
4
5
|
module RDF
|
6
|
+
# @!parse
|
7
|
+
# # Vocabulary for <http://www.w3.org/2000/01/rdf-schema#>
|
8
|
+
# class RDFS < RDF::StrictVocabulary
|
9
|
+
# end
|
5
10
|
class RDFS < RDF::StrictVocabulary("http://www.w3.org/2000/01/rdf-schema#")
|
6
11
|
|
7
12
|
# Class definitions
|
8
13
|
term :Class,
|
9
14
|
comment: %(The class of classes.).freeze,
|
10
15
|
label: "Class".freeze,
|
11
|
-
"rdfs:isDefinedBy" => %(rdfs:).freeze,
|
16
|
+
:"rdfs:isDefinedBy" => %(rdfs:).freeze,
|
12
17
|
subClassOf: "rdfs:Resource".freeze,
|
13
18
|
type: "rdfs:Class".freeze
|
14
19
|
term :Container,
|
15
20
|
comment: %(The class of RDF containers.).freeze,
|
16
21
|
label: "Container".freeze,
|
17
|
-
"rdfs:isDefinedBy" => %(rdfs:).freeze,
|
22
|
+
:"rdfs:isDefinedBy" => %(rdfs:).freeze,
|
18
23
|
subClassOf: "rdfs:Resource".freeze,
|
19
24
|
type: "rdfs:Class".freeze
|
20
25
|
term :ContainerMembershipProperty,
|
21
26
|
comment: %(The class of container membership properties, rdf:_1, rdf:_2, ...,
|
22
27
|
all of which are sub-properties of 'member'.).freeze,
|
23
28
|
label: "ContainerMembershipProperty".freeze,
|
24
|
-
"rdfs:isDefinedBy" => %(rdfs:).freeze,
|
29
|
+
:"rdfs:isDefinedBy" => %(rdfs:).freeze,
|
25
30
|
subClassOf: "rdf:Property".freeze,
|
26
31
|
type: "rdfs:Class".freeze
|
27
32
|
term :Datatype,
|
28
33
|
comment: %(The class of RDF datatypes.).freeze,
|
29
34
|
label: "Datatype".freeze,
|
30
|
-
"rdfs:isDefinedBy" => %(rdfs:).freeze,
|
35
|
+
:"rdfs:isDefinedBy" => %(rdfs:).freeze,
|
31
36
|
subClassOf: "rdfs:Class".freeze,
|
32
37
|
type: "rdfs:Class".freeze
|
33
38
|
term :Literal,
|
34
39
|
comment: %(The class of literal values, eg. textual strings and integers.).freeze,
|
35
40
|
label: "Literal".freeze,
|
36
|
-
"rdfs:isDefinedBy" => %(rdfs:).freeze,
|
41
|
+
:"rdfs:isDefinedBy" => %(rdfs:).freeze,
|
37
42
|
subClassOf: "rdfs:Resource".freeze,
|
38
43
|
type: "rdfs:Class".freeze
|
39
44
|
term :Resource,
|
40
45
|
comment: %(The class resource, everything.).freeze,
|
41
46
|
label: "Resource".freeze,
|
42
|
-
"rdfs:isDefinedBy" => %(rdfs:).freeze,
|
47
|
+
:"rdfs:isDefinedBy" => %(rdfs:).freeze,
|
43
48
|
type: "rdfs:Class".freeze
|
44
49
|
|
45
50
|
# Property definitions
|
@@ -48,21 +53,21 @@ module RDF
|
|
48
53
|
domain: "rdfs:Resource".freeze,
|
49
54
|
label: "comment".freeze,
|
50
55
|
range: "rdfs:Literal".freeze,
|
51
|
-
"rdfs:isDefinedBy" => %(rdfs:).freeze,
|
56
|
+
:"rdfs:isDefinedBy" => %(rdfs:).freeze,
|
52
57
|
type: "rdf:Property".freeze
|
53
58
|
property :domain,
|
54
59
|
comment: %(A domain of the subject property.).freeze,
|
55
60
|
domain: "rdf:Property".freeze,
|
56
61
|
label: "domain".freeze,
|
57
62
|
range: "rdfs:Class".freeze,
|
58
|
-
"rdfs:isDefinedBy" => %(rdfs:).freeze,
|
63
|
+
:"rdfs:isDefinedBy" => %(rdfs:).freeze,
|
59
64
|
type: "rdf:Property".freeze
|
60
65
|
property :isDefinedBy,
|
61
66
|
comment: %(The defininition of the subject resource.).freeze,
|
62
67
|
domain: "rdfs:Resource".freeze,
|
63
68
|
label: "isDefinedBy".freeze,
|
64
69
|
range: "rdfs:Resource".freeze,
|
65
|
-
"rdfs:isDefinedBy" => %(rdfs:).freeze,
|
70
|
+
:"rdfs:isDefinedBy" => %(rdfs:).freeze,
|
66
71
|
subPropertyOf: "rdfs:seeAlso".freeze,
|
67
72
|
type: "rdf:Property".freeze
|
68
73
|
property :label,
|
@@ -70,49 +75,49 @@ module RDF
|
|
70
75
|
domain: "rdfs:Resource".freeze,
|
71
76
|
label: "label".freeze,
|
72
77
|
range: "rdfs:Literal".freeze,
|
73
|
-
"rdfs:isDefinedBy" => %(rdfs:).freeze,
|
78
|
+
:"rdfs:isDefinedBy" => %(rdfs:).freeze,
|
74
79
|
type: "rdf:Property".freeze
|
75
80
|
property :member,
|
76
81
|
comment: %(A member of the subject resource.).freeze,
|
77
82
|
domain: "rdfs:Resource".freeze,
|
78
83
|
label: "member".freeze,
|
79
84
|
range: "rdfs:Resource".freeze,
|
80
|
-
"rdfs:isDefinedBy" => %(rdfs:).freeze,
|
85
|
+
:"rdfs:isDefinedBy" => %(rdfs:).freeze,
|
81
86
|
type: "rdf:Property".freeze
|
82
87
|
property :range,
|
83
88
|
comment: %(A range of the subject property.).freeze,
|
84
89
|
domain: "rdf:Property".freeze,
|
85
90
|
label: "range".freeze,
|
86
91
|
range: "rdfs:Class".freeze,
|
87
|
-
"rdfs:isDefinedBy" => %(rdfs:).freeze,
|
92
|
+
:"rdfs:isDefinedBy" => %(rdfs:).freeze,
|
88
93
|
type: "rdf:Property".freeze
|
89
94
|
property :seeAlso,
|
90
95
|
comment: %(Further information about the subject resource.).freeze,
|
91
96
|
domain: "rdfs:Resource".freeze,
|
92
97
|
label: "seeAlso".freeze,
|
93
98
|
range: "rdfs:Resource".freeze,
|
94
|
-
"rdfs:isDefinedBy" => %(rdfs:).freeze,
|
99
|
+
:"rdfs:isDefinedBy" => %(rdfs:).freeze,
|
95
100
|
type: "rdf:Property".freeze
|
96
101
|
property :subClassOf,
|
97
102
|
comment: %(The subject is a subclass of a class.).freeze,
|
98
103
|
domain: "rdfs:Class".freeze,
|
99
104
|
label: "subClassOf".freeze,
|
100
105
|
range: "rdfs:Class".freeze,
|
101
|
-
"rdfs:isDefinedBy" => %(rdfs:).freeze,
|
106
|
+
:"rdfs:isDefinedBy" => %(rdfs:).freeze,
|
102
107
|
type: "rdf:Property".freeze
|
103
108
|
property :subPropertyOf,
|
104
109
|
comment: %(The subject is a subproperty of a property.).freeze,
|
105
110
|
domain: "rdf:Property".freeze,
|
106
111
|
label: "subPropertyOf".freeze,
|
107
112
|
range: "rdf:Property".freeze,
|
108
|
-
"rdfs:isDefinedBy" => %(rdfs:).freeze,
|
113
|
+
:"rdfs:isDefinedBy" => %(rdfs:).freeze,
|
109
114
|
type: "rdf:Property".freeze
|
110
115
|
|
111
116
|
# Extra definitions
|
112
117
|
term :"",
|
113
|
-
"dc11:title" => %(The RDF Schema vocabulary \(RDFS\)).freeze,
|
118
|
+
:"dc11:title" => %(The RDF Schema vocabulary \(RDFS\)).freeze,
|
114
119
|
label: "".freeze,
|
115
|
-
"rdfs:seeAlso" => %(http://www.w3.org/2000/01/rdf-schema-more).freeze,
|
120
|
+
:"rdfs:seeAlso" => %(http://www.w3.org/2000/01/rdf-schema-more).freeze,
|
116
121
|
type: "owl:Ontology".freeze
|
117
122
|
end
|
118
123
|
end
|
data/lib/rdf/vocab/xsd.rb
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
+
# frozen_string_literal: true
|
2
3
|
# This file generated automatically using vocab-fetch from etc/xsd.ttl
|
3
4
|
require 'rdf'
|
4
5
|
module RDF
|
6
|
+
# @!parse
|
7
|
+
# # Vocabulary for <http://www.w3.org/2001/XMLSchema#>
|
8
|
+
# class XSD < RDF::Vocabulary
|
9
|
+
# end
|
5
10
|
class XSD < RDF::Vocabulary("http://www.w3.org/2001/XMLSchema#")
|
6
11
|
|
7
12
|
# Datatype definitions
|
data/lib/rdf/vocabulary.rb
CHANGED
@@ -201,7 +201,7 @@ module RDF
|
|
201
201
|
# @return [Array<RDF::Vocabulary>]
|
202
202
|
def imports
|
203
203
|
@imports ||= begin
|
204
|
-
Array(self[""].attributes["owl:imports"]).map {|pn|find(expand_pname(pn)) rescue nil}.compact
|
204
|
+
Array(self[""].attributes[:"owl:imports"]).map {|pn|find(expand_pname(pn)) rescue nil}.compact
|
205
205
|
rescue KeyError
|
206
206
|
[]
|
207
207
|
end
|
@@ -217,22 +217,6 @@ module RDF
|
|
217
217
|
end
|
218
218
|
end
|
219
219
|
|
220
|
-
##
|
221
|
-
# @return [String] The label for the named property
|
222
|
-
# @deprecated Use {RDF::Vocabulary::Term#label} instead.
|
223
|
-
def label_for(name)
|
224
|
-
warn "[DEPRECATION] `Vocabulary.label_for is deprecated. Please use Vocabulary::Term#label instead. Called from #{Gem.location_of_caller.join(':')}"
|
225
|
-
self[name].label || ''
|
226
|
-
end
|
227
|
-
|
228
|
-
##
|
229
|
-
# @return [String] The comment for the named property
|
230
|
-
# @deprecated Use {RDF::Vocabulary::Term#comment} instead.
|
231
|
-
def comment_for(name)
|
232
|
-
warn "[DEPRECATION] `Vocabulary.comment_for is deprecated. Please use Vocabulary::Term#comment instead. Called from #{Gem.location_of_caller.join(':')}"
|
233
|
-
self[name].comment || ''
|
234
|
-
end
|
235
|
-
|
236
220
|
##
|
237
221
|
# Returns the base URI for this vocabulary class.
|
238
222
|
#
|
@@ -256,6 +240,7 @@ module RDF
|
|
256
240
|
end
|
257
241
|
end
|
258
242
|
alias_method :to_enum, :enum_for
|
243
|
+
|
259
244
|
##
|
260
245
|
# Enumerate each statement constructed from the defined vocabulary terms
|
261
246
|
#
|
@@ -280,42 +265,52 @@ module RDF
|
|
280
265
|
##
|
281
266
|
# Load a vocabulary, optionally from a separate location.
|
282
267
|
#
|
283
|
-
# @param [URI, #to_s]
|
284
|
-
# @param [
|
285
|
-
# @option options [String] class_name
|
268
|
+
# @param [URI, #to_s] url
|
269
|
+
# @param [String] class_name
|
286
270
|
# The class_name associated with the vocabulary, used for creating the class name of the vocabulary. This will create a new class named with a top-level constant based on `class_name`.
|
287
|
-
# @
|
271
|
+
# @param [URI, #to_s] location
|
288
272
|
# Location from which to load the vocabulary, if not from `uri`.
|
289
|
-
# @
|
273
|
+
# @param [Array<Symbol>, Hash{Symbol => Hash}] extra
|
290
274
|
# Extra terms to add to the vocabulary. In the first form, it is an array of symbols, for which terms are created. In the second, it is a Hash mapping symbols to property attributes, as described in {RDF::Vocabulary.property}.
|
275
|
+
# @param [String] patch
|
276
|
+
# A patch to run on the graph after loading. Requires the `ld-patch` gem to be available.
|
291
277
|
# @return [RDF::Vocabulary] the loaded vocabulary
|
292
|
-
def load(
|
293
|
-
source =
|
294
|
-
class_name = options[:class_name]
|
278
|
+
def load(url, class_name: nil, location: nil, extra: nil, patch: nil)
|
279
|
+
source = location || url
|
295
280
|
vocab = if class_name
|
296
|
-
Object.const_set(class_name, Class.new(self.create(
|
281
|
+
Object.const_set(class_name, Class.new(self.create(url)))
|
297
282
|
else
|
298
|
-
Class.new(self.create(
|
283
|
+
Class.new(self.create(url))
|
299
284
|
end
|
300
285
|
|
301
|
-
graph = RDF::
|
286
|
+
graph = RDF::Repository.load(source)
|
287
|
+
|
288
|
+
if patch
|
289
|
+
begin
|
290
|
+
require 'ld/patch'
|
291
|
+
operator = LD::Patch.parse(patch)
|
292
|
+
graph.query(operator)
|
293
|
+
rescue LoadError
|
294
|
+
raise ArgumentError, "patching vocabulary requires the ld-patch gem"
|
295
|
+
end
|
296
|
+
end
|
302
297
|
term_defs = {}
|
303
298
|
graph.each do |statement|
|
304
|
-
next unless statement.subject.uri? && statement.subject.start_with?(
|
305
|
-
name = statement.subject.to_s[
|
299
|
+
next unless statement.subject.uri? && statement.subject.start_with?(url)
|
300
|
+
name = statement.subject.to_s[url.to_s.length..-1]
|
306
301
|
term = (term_defs[name.to_sym] ||= {})
|
307
302
|
key = case statement.predicate
|
308
|
-
when RDF.type
|
309
|
-
when RDF::RDFS.subClassOf
|
310
|
-
when RDF::RDFS.subPropertyOf
|
311
|
-
when RDF::RDFS.range
|
312
|
-
when RDF::RDFS.domain
|
313
|
-
when RDF::RDFS.comment
|
314
|
-
when RDF::RDFS.label
|
315
|
-
when RDF::
|
316
|
-
when RDF::
|
317
|
-
when RDF::
|
318
|
-
else
|
303
|
+
when RDF.type then :type
|
304
|
+
when RDF::RDFS.subClassOf then :subClassOf
|
305
|
+
when RDF::RDFS.subPropertyOf then :subPropertyOf
|
306
|
+
when RDF::RDFS.range then :range
|
307
|
+
when RDF::RDFS.domain then :domain
|
308
|
+
when RDF::RDFS.comment then :comment
|
309
|
+
when RDF::RDFS.label then :label
|
310
|
+
when RDF::URI("http://schema.org/inverseOf") then :inverseOf
|
311
|
+
when RDF::URI("http://schema.org/domainIncludes") then :domainIncludes
|
312
|
+
when RDF::URI("http://schema.org/rangeIncludes") then :rangeIncludes
|
313
|
+
else statement.predicate.pname
|
319
314
|
end
|
320
315
|
|
321
316
|
value = if statement.object.uri?
|
@@ -328,11 +323,11 @@ module RDF
|
|
328
323
|
end
|
329
324
|
|
330
325
|
# Create extra terms
|
331
|
-
term_defs = case
|
326
|
+
term_defs = case extra
|
332
327
|
when Array
|
333
|
-
|
328
|
+
extra.inject({}) {|memo, s| memo[s.to_sym] = {label: s.to_s}; memo}.merge(term_defs)
|
334
329
|
when Hash
|
335
|
-
|
330
|
+
extra.merge(term_defs)
|
336
331
|
else
|
337
332
|
term_defs
|
338
333
|
end
|
@@ -545,8 +540,7 @@ module RDF
|
|
545
540
|
# @option options [String, #to_s] :fragment The fragment component.
|
546
541
|
# @option options [Hash{Symbol,Resource => Term, #to_s}] :attributes
|
547
542
|
# Attributes of this vocabulary term, used for finding `label` and `comment` and to serialize the term back to RDF
|
548
|
-
def initialize(*args)
|
549
|
-
options = args.last.is_a?(Hash) ? args.last : {}
|
543
|
+
def initialize(*args, **options)
|
550
544
|
@attributes = options.fetch(:attributes)
|
551
545
|
super
|
552
546
|
end
|
@@ -612,8 +606,6 @@ module RDF
|
|
612
606
|
# @yieldparam [RDF::Statement]
|
613
607
|
def each_statement
|
614
608
|
attributes.reject {|p| p == :vocab}.each do |prop, values|
|
615
|
-
prop = RDF::Vocabulary.expand_pname(prop) unless prop.is_a?(Symbol)
|
616
|
-
next unless prop
|
617
609
|
Array(values).each do |value|
|
618
610
|
begin
|
619
611
|
case prop
|
@@ -633,21 +625,23 @@ module RDF
|
|
633
625
|
prop = RDFS.range
|
634
626
|
value = RDF::Vocabulary.expand_pname(value)
|
635
627
|
when :inverseOf
|
636
|
-
prop = RDF::
|
628
|
+
prop = RDF::URI("http://schema.org/inverseOf")
|
637
629
|
value = RDF::Vocabulary.expand_pname(value)
|
638
630
|
when :domainIncludes
|
639
|
-
prop = RDF::
|
631
|
+
prop = RDF::URI("http://schema.org/domainIncludes")
|
640
632
|
value = RDF::Vocabulary.expand_pname(value)
|
641
633
|
when :rangeIncludes
|
642
|
-
prop = RDF::
|
634
|
+
prop = RDF::URI("http://schema.org/rangeIncludes")
|
643
635
|
value = RDF::Vocabulary.expand_pname(value)
|
644
636
|
when :label
|
645
637
|
prop = RDFS.label
|
646
638
|
when :comment
|
647
639
|
prop = RDFS.comment
|
648
640
|
else
|
649
|
-
|
650
|
-
|
641
|
+
prop = RDF::Vocabulary.expand_pname(prop.to_s)
|
642
|
+
next unless prop
|
643
|
+
v = RDF::Vocabulary.expand_pname(value.to_s)
|
644
|
+
value = v.valid? ? v : RDF::Literal(value.to_s)
|
651
645
|
end
|
652
646
|
yield RDF::Statement(self, prop, value)
|
653
647
|
rescue KeyError
|
@@ -683,13 +677,13 @@ module RDF
|
|
683
677
|
@attributes.has_key?(method) || super
|
684
678
|
end
|
685
679
|
|
686
|
-
# Accessor for `domainIncludes`
|
680
|
+
# Accessor for `schema:domainIncludes`
|
687
681
|
# @return [RDF::URI]
|
688
682
|
def domain_includes
|
689
683
|
Array(@attributes[:domainIncludes]).map {|v| RDF::Vocabulary.expand_pname(v)}
|
690
684
|
end
|
691
685
|
|
692
|
-
# Accessor for `rangeIncludes`
|
686
|
+
# Accessor for `schema:rangeIncludes`
|
693
687
|
# @return [RDF::URI]
|
694
688
|
def range_includes
|
695
689
|
Array(@attributes[:rangeIncludes]).map {|v| RDF::Vocabulary.expand_pname(v)}
|
@@ -735,7 +729,7 @@ module RDF
|
|
735
729
|
# @raise [KeyError] if property not defined in vocabulary
|
736
730
|
def [](name)
|
737
731
|
props.fetch(name.to_sym)
|
738
|
-
rescue KeyError
|
732
|
+
rescue KeyError
|
739
733
|
raise KeyError, "#{name} not found in vocabulary #{self.__name__}"
|
740
734
|
end
|
741
735
|
end
|
data/lib/rdf/writer.rb
CHANGED
@@ -33,12 +33,24 @@ module RDF
|
|
33
33
|
# end
|
34
34
|
# end
|
35
35
|
#
|
36
|
+
# @example Detecting invalid output
|
37
|
+
# logger = Logger.new([])
|
38
|
+
# RDF::Writer.for(:ntriples).buffer(logger: logger) do |writer|
|
39
|
+
# statement = RDF::Statement.new(
|
40
|
+
# RDF::URI("http://rubygems.org/gems/rdf"),
|
41
|
+
# RDF::URI("http://purl.org/dc/terms/creator"),
|
42
|
+
# nil)
|
43
|
+
# writer << statement
|
44
|
+
# end # => RDF::WriterError
|
45
|
+
# logger.empty? => false
|
46
|
+
#
|
36
47
|
# @abstract
|
37
48
|
# @see RDF::Format
|
38
49
|
# @see RDF::Reader
|
39
50
|
class Writer
|
40
51
|
extend ::Enumerable
|
41
52
|
extend RDF::Util::Aliasing::LateBound
|
53
|
+
include RDF::Util::Logger
|
42
54
|
include RDF::Writable
|
43
55
|
|
44
56
|
##
|
@@ -99,6 +111,40 @@ module RDF
|
|
99
111
|
end
|
100
112
|
end
|
101
113
|
|
114
|
+
##
|
115
|
+
# Options suitable for automatic Writer provisioning.
|
116
|
+
# @return [Array<RDF::CLI::Option>]
|
117
|
+
def self.options
|
118
|
+
[
|
119
|
+
RDF::CLI::Option.new(
|
120
|
+
symbol: :canonicalize,
|
121
|
+
datatype: TrueClass,
|
122
|
+
on: ["--canonicalize"],
|
123
|
+
description: "Canonicalize input/output.") {true},
|
124
|
+
RDF::CLI::Option.new(
|
125
|
+
symbol: :encoding,
|
126
|
+
datatype: Encoding,
|
127
|
+
on: ["--encoding ENCODING"],
|
128
|
+
description: "The encoding of the input stream.") {|arg| Encoding.find arg},
|
129
|
+
RDF::CLI::Option.new(
|
130
|
+
symbol: :prefixes,
|
131
|
+
datatype: Hash,
|
132
|
+
multiple: true,
|
133
|
+
on: ["--prefixes PREFIX,PREFIX"],
|
134
|
+
description: "A comma-separated list of prefix:uri pairs.") do |arg|
|
135
|
+
arg.split(',').inject({}) do |memo, pfxuri|
|
136
|
+
pfx,uri = pfxuri.split(':', 2)
|
137
|
+
memo.merge(pfx.to_sym => RDF::URI(uri))
|
138
|
+
end
|
139
|
+
end,
|
140
|
+
RDF::CLI::Option.new(
|
141
|
+
symbol: :unique_bnodes,
|
142
|
+
datatype: TrueClass,
|
143
|
+
on: ["--unique-bnodes"],
|
144
|
+
description: "Use unique Node identifiers.") {true},
|
145
|
+
]
|
146
|
+
end
|
147
|
+
|
102
148
|
class << self
|
103
149
|
alias_method :format_class, :format
|
104
150
|
end
|
@@ -212,7 +258,7 @@ module RDF
|
|
212
258
|
# @yieldreturn [void]
|
213
259
|
def initialize(output = $stdout, options = {}, &block)
|
214
260
|
@output, @options = output, options.dup
|
215
|
-
@nodes, @node_id = {}, 0
|
261
|
+
@nodes, @node_id, @node_id_map = {}, 0, {}
|
216
262
|
|
217
263
|
if block_given?
|
218
264
|
write_prologue
|
@@ -329,7 +375,7 @@ module RDF
|
|
329
375
|
##
|
330
376
|
# Flushes the underlying output buffer.
|
331
377
|
#
|
332
|
-
# @return [
|
378
|
+
# @return [self]
|
333
379
|
def flush
|
334
380
|
@output.flush if @output.respond_to?(:flush)
|
335
381
|
self
|
@@ -337,66 +383,82 @@ module RDF
|
|
337
383
|
alias_method :flush!, :flush
|
338
384
|
|
339
385
|
##
|
340
|
-
# @return [
|
386
|
+
# @return [self]
|
341
387
|
# @abstract
|
342
388
|
def write_prologue
|
343
389
|
self
|
344
390
|
end
|
345
391
|
|
346
392
|
##
|
347
|
-
# @return [
|
393
|
+
# @return [self]
|
394
|
+
# @raise [RDF::WriterError] if errors logged during processing.
|
348
395
|
# @abstract
|
349
396
|
def write_epilogue
|
397
|
+
if log_statistics[:error]
|
398
|
+
raise RDF::WriterError, "Errors found during processing"
|
399
|
+
end
|
350
400
|
self
|
351
401
|
end
|
352
402
|
|
353
403
|
##
|
354
404
|
# @param [String] text
|
355
|
-
# @return [
|
405
|
+
# @return [self]
|
356
406
|
# @abstract
|
357
407
|
def write_comment(text)
|
358
408
|
self
|
359
409
|
end
|
360
410
|
|
361
411
|
##
|
362
|
-
#
|
363
|
-
#
|
364
|
-
#
|
365
|
-
|
366
|
-
warn "[DEPRECATION] `Writer#graph_write is deprecated. Please use RDF::Writable#insert instead. Called from #{Gem.location_of_caller.join(':')}"
|
367
|
-
graph.each_triple { |*triple| write_triple(*triple) }
|
368
|
-
self
|
369
|
-
end
|
370
|
-
|
371
|
-
##
|
372
|
-
# @param [Array<RDF::Statement>] statements
|
373
|
-
# @return [void] `self`
|
374
|
-
# @deprecated Use {RDF::Writable#insert} instead.
|
375
|
-
def write_statements(*statements)
|
376
|
-
warn "[DEPRECATION] `Writer#write_statements is deprecated. Please use RDF::Writable#insert instead. Called from #{Gem.location_of_caller.join(':')}"
|
377
|
-
statements.each { |statement| write_statement(statement) }
|
378
|
-
self
|
379
|
-
end
|
380
|
-
|
381
|
-
##
|
412
|
+
# Add a statement to the writer. This will check to ensure that the statement is complete (no nil terms) and is valid, if the `:validation` option is set.
|
413
|
+
#
|
414
|
+
# Additionally, it will de-duplicate BNode terms sharing a common identifier.
|
415
|
+
#
|
382
416
|
# @param [RDF::Statement] statement
|
383
|
-
# @return [
|
384
|
-
# @
|
417
|
+
# @return [self]
|
418
|
+
# @note logs error if attempting to write an invalid {RDF::Statement} or if canonicalizing a statement which cannot be canonicalized.
|
385
419
|
def write_statement(statement)
|
386
420
|
statement = statement.canonicalize! if canonicalize?
|
387
|
-
|
388
|
-
|
389
|
-
|
421
|
+
|
422
|
+
# Make sure BNodes in statement use unique identifiers
|
423
|
+
if statement.node?
|
424
|
+
terms = statement.to_quad.map do |term|
|
425
|
+
if term.is_a?(RDF::Node)
|
426
|
+
term = term.original while term.original
|
427
|
+
@nodes[term] ||= begin
|
428
|
+
# Account for duplicated nodes
|
429
|
+
@node_id_map[term.to_s] ||= term
|
430
|
+
if !@node_id_map[term.to_s].equal?(term)
|
431
|
+
# Rename node
|
432
|
+
term.make_unique!
|
433
|
+
@node_id_map[term.to_s] = term
|
434
|
+
end
|
435
|
+
end
|
436
|
+
else
|
437
|
+
term
|
438
|
+
end
|
439
|
+
end
|
440
|
+
statement = RDF::Statement.from(statement.to_quad)
|
441
|
+
end
|
442
|
+
|
443
|
+
if statement.incomplete?
|
444
|
+
log_error "Statement #{statement.inspect} is incomplete"
|
445
|
+
elsif validate? && statement.invalid?
|
446
|
+
log_error "Statement #{statement.inspect} is invalid"
|
447
|
+
elsif respond_to?(:write_quad)
|
448
|
+
write_quad(*statement.to_quad)
|
449
|
+
else
|
450
|
+
write_triple(*statement.to_triple)
|
451
|
+
end
|
390
452
|
self
|
391
453
|
rescue ArgumentError => e
|
392
|
-
|
454
|
+
log_error e.message
|
393
455
|
end
|
394
456
|
alias_method :insert_statement, :write_statement # support the RDF::Writable interface
|
395
457
|
|
396
458
|
##
|
397
459
|
# @param [Array<Array(RDF::Resource, RDF::URI, RDF::Term)>] triples
|
398
|
-
# @return [
|
399
|
-
# @
|
460
|
+
# @return [self]
|
461
|
+
# @note logs error if attempting to write an invalid {RDF::Statement} or if canonicalizing a statement which cannot be canonicalized.
|
400
462
|
def write_triples(*triples)
|
401
463
|
triples.each { |triple| write_triple(*triple) }
|
402
464
|
self
|
@@ -406,9 +468,9 @@ module RDF
|
|
406
468
|
# @param [RDF::Resource] subject
|
407
469
|
# @param [RDF::URI] predicate
|
408
470
|
# @param [RDF::Term] object
|
409
|
-
# @return [
|
471
|
+
# @return [self]
|
410
472
|
# @raise [NotImplementedError] unless implemented in subclass
|
411
|
-
# @
|
473
|
+
# @note logs error if attempting to write an invalid {RDF::Statement} or if canonicalizing a statement which cannot be canonicalized.
|
412
474
|
# @abstract
|
413
475
|
def write_triple(subject, predicate, object)
|
414
476
|
raise NotImplementedError.new("#{self.class}#write_triple") # override in subclasses
|
@@ -429,16 +491,6 @@ module RDF
|
|
429
491
|
end
|
430
492
|
end
|
431
493
|
|
432
|
-
##
|
433
|
-
# @param [RDF::Term] term
|
434
|
-
# @return [String]
|
435
|
-
# @since 0.3.0
|
436
|
-
# @deprecated Use {#format_term} instead
|
437
|
-
def format_value(term, options = {})
|
438
|
-
warn "[DEPRECATION] Writer#format_value is being replaced with Writer#format_term in RDF.rb 2.0. Called from #{Gem.location_of_caller.join(':')}"
|
439
|
-
format_term(term, options)
|
440
|
-
end
|
441
|
-
|
442
494
|
##
|
443
495
|
# @param [RDF::Node] value
|
444
496
|
# @param [Hash{Symbol => Object}] options = ({})
|
@@ -490,16 +542,16 @@ module RDF
|
|
490
542
|
end
|
491
543
|
|
492
544
|
##
|
493
|
-
# @param [RDF::Resource]
|
545
|
+
# @param [RDF::Resource] term
|
494
546
|
# @return [String]
|
495
|
-
def uri_for(
|
547
|
+
def uri_for(term)
|
496
548
|
case
|
497
|
-
when
|
498
|
-
@nodes[
|
499
|
-
when
|
500
|
-
|
549
|
+
when term.is_a?(RDF::Node)
|
550
|
+
@nodes[term] ||= term.to_base
|
551
|
+
when term.respond_to?(:to_uri)
|
552
|
+
term.to_uri.to_s
|
501
553
|
else
|
502
|
-
|
554
|
+
term.to_s
|
503
555
|
end
|
504
556
|
end
|
505
557
|
|