rdf 3.0.11 → 3.1.2
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.
- checksums.yaml +4 -4
- data/AUTHORS +1 -1
- data/README.md +127 -95
- data/UNLICENSE +1 -1
- data/VERSION +1 -1
- data/etc/doap.nt +79 -85
- data/lib/rdf.rb +35 -23
- data/lib/rdf/changeset.rb +80 -19
- data/lib/rdf/cli.rb +7 -7
- data/lib/rdf/format.rb +17 -10
- data/lib/rdf/mixin/enumerable.rb +4 -3
- data/lib/rdf/mixin/mutable.rb +5 -15
- data/lib/rdf/mixin/queryable.rb +12 -4
- data/lib/rdf/mixin/transactable.rb +2 -2
- data/lib/rdf/mixin/writable.rb +9 -14
- data/lib/rdf/model/dataset.rb +1 -1
- data/lib/rdf/model/graph.rb +7 -4
- data/lib/rdf/model/list.rb +5 -5
- data/lib/rdf/model/literal.rb +3 -3
- data/lib/rdf/model/statement.rb +32 -9
- data/lib/rdf/model/uri.rb +53 -32
- data/lib/rdf/nquads.rb +6 -6
- data/lib/rdf/ntriples.rb +7 -5
- data/lib/rdf/ntriples/reader.rb +29 -7
- data/lib/rdf/ntriples/writer.rb +10 -1
- data/lib/rdf/query.rb +27 -35
- data/lib/rdf/query/hash_pattern_normalizer.rb +14 -12
- data/lib/rdf/query/pattern.rb +51 -18
- data/lib/rdf/query/solution.rb +20 -1
- data/lib/rdf/query/solutions.rb +15 -5
- data/lib/rdf/query/variable.rb +17 -5
- data/lib/rdf/reader.rb +76 -25
- data/lib/rdf/repository.rb +32 -18
- data/lib/rdf/transaction.rb +1 -1
- data/lib/rdf/util.rb +6 -5
- data/lib/rdf/util/cache.rb +2 -2
- data/lib/rdf/util/coercions.rb +60 -0
- data/lib/rdf/util/file.rb +20 -10
- data/lib/rdf/util/logger.rb +6 -6
- data/lib/rdf/util/uuid.rb +4 -4
- data/lib/rdf/vocab/owl.rb +401 -86
- data/lib/rdf/vocab/rdfs.rb +81 -18
- data/lib/rdf/vocab/rdfv.rb +147 -1
- data/lib/rdf/vocab/writer.rb +41 -3
- data/lib/rdf/vocab/xsd.rb +203 -2
- data/lib/rdf/vocabulary.rb +73 -15
- data/lib/rdf/writer.rb +33 -11
- metadata +34 -28
data/lib/rdf/query/solution.rb
CHANGED
@@ -195,12 +195,31 @@ class RDF::Query
|
|
195
195
|
# Merges the bindings from the given `other` query solution into this
|
196
196
|
# one, overwriting any existing ones having the same name.
|
197
197
|
#
|
198
|
+
# ## RDFStar (RDF*)
|
199
|
+
#
|
200
|
+
# If merging a binding for a statement to a pattern,
|
201
|
+
# merge their embedded solutions.
|
202
|
+
#
|
198
203
|
# @param [RDF::Query::Solution, #to_h] other
|
199
204
|
# another query solution or hash bindings
|
200
205
|
# @return [void] self
|
201
206
|
# @since 0.3.0
|
202
207
|
def merge!(other)
|
203
|
-
@bindings.merge!(other.to_h)
|
208
|
+
@bindings.merge!(other.to_h) do |key, v1, v2|
|
209
|
+
# Don't merge a pattern over a statement
|
210
|
+
# This happens because JOIN does a reverse merge,
|
211
|
+
# and a pattern is set in v2.
|
212
|
+
v2.is_a?(Pattern) ? v1 : v2
|
213
|
+
end
|
214
|
+
# Merge bindings from patterns
|
215
|
+
embedded_solutions = []
|
216
|
+
@bindings.each do |k, v|
|
217
|
+
if v.is_a?(Pattern) && other[k].is_a?(RDF::Statement)
|
218
|
+
embedded_solutions << v.solution(other[k])
|
219
|
+
end
|
220
|
+
end
|
221
|
+
# Merge embedded solutions
|
222
|
+
embedded_solutions.each {|soln| merge!(soln)}
|
204
223
|
self
|
205
224
|
end
|
206
225
|
|
data/lib/rdf/query/solutions.rb
CHANGED
@@ -66,13 +66,15 @@ module RDF; class Query
|
|
66
66
|
#
|
67
67
|
# @return [Array<Symbol>]
|
68
68
|
def variable_names
|
69
|
-
|
70
|
-
|
71
|
-
|
69
|
+
@variable_names ||= begin
|
70
|
+
variables = self.inject({}) do |result, solution|
|
71
|
+
solution.each_name do |name|
|
72
|
+
result[name] ||= true
|
73
|
+
end
|
74
|
+
result
|
72
75
|
end
|
73
|
-
|
76
|
+
variables.keys
|
74
77
|
end
|
75
|
-
variables.keys
|
76
78
|
end
|
77
79
|
|
78
80
|
##
|
@@ -136,6 +138,7 @@ module RDF; class Query
|
|
136
138
|
# @yieldreturn [Boolean]
|
137
139
|
# @return [self]
|
138
140
|
def filter(criteria = {})
|
141
|
+
@variable_names = nil
|
139
142
|
if block_given?
|
140
143
|
self.reject! do |solution|
|
141
144
|
!yield(solution.is_a?(Solution) ? solution : Solution.new(solution))
|
@@ -223,6 +226,13 @@ module RDF; class Query
|
|
223
226
|
solution.bindings.delete_if { |k, v| !variables.include?(k.to_sym) }
|
224
227
|
end
|
225
228
|
end
|
229
|
+
|
230
|
+
# Make sure variable_names are ordered by projected variables
|
231
|
+
projected_vars, vars = variables.map(&:to_sym), variable_names
|
232
|
+
vars = variable_names
|
233
|
+
|
234
|
+
# Maintain projected order, and add any non-projected variables
|
235
|
+
@variable_names = (projected_vars & vars) + (vars - projected_vars)
|
226
236
|
self
|
227
237
|
end
|
228
238
|
alias_method :select, :project
|
data/lib/rdf/query/variable.rb
CHANGED
@@ -157,12 +157,24 @@ class RDF::Query
|
|
157
157
|
##
|
158
158
|
# Rebinds this variable to the given `value`.
|
159
159
|
#
|
160
|
-
# @
|
161
|
-
#
|
160
|
+
# @overload bind(value)
|
161
|
+
# @param [RDF::Query::Solution] value
|
162
|
+
# @return [self] the bound variable
|
163
|
+
#
|
164
|
+
# @overload bind(value)
|
165
|
+
# @param [RDF::Term] value
|
166
|
+
# @return [RDF::Term] the previous value, if any.
|
162
167
|
def bind(value)
|
163
|
-
|
164
|
-
|
165
|
-
|
168
|
+
if value.is_a?(RDF::Query::Solution)
|
169
|
+
self.value = value.to_h.fetch(name, self.value)
|
170
|
+
self
|
171
|
+
else
|
172
|
+
warn "[DEPRECATION] RDF::Query::Variable#bind should be used with a solution, not a term.\n" +
|
173
|
+
"Called from #{Gem.location_of_caller.join(':')}"
|
174
|
+
old_value = self.value
|
175
|
+
self.value = value
|
176
|
+
old_value
|
177
|
+
end
|
166
178
|
end
|
167
179
|
alias_method :bind!, :bind
|
168
180
|
|
data/lib/rdf/reader.rb
CHANGED
@@ -88,9 +88,15 @@ module RDF
|
|
88
88
|
# @yieldreturn [String] another way to provide a sample, allows lazy for retrieving the sample.
|
89
89
|
#
|
90
90
|
# @return [Class]
|
91
|
-
def self.for(
|
92
|
-
|
93
|
-
|
91
|
+
def self.for(*arg, &block)
|
92
|
+
case arg.length
|
93
|
+
when 0 then arg = nil
|
94
|
+
when 1 then arg = arg.first
|
95
|
+
else
|
96
|
+
raise ArgumentError, "Format.for accepts zero or one argument, got #{arg.length}."
|
97
|
+
end
|
98
|
+
arg = arg.merge(has_reader: true) if arg.is_a?(Hash)
|
99
|
+
if format = self.format || Format.for(arg, &block)
|
94
100
|
format.reader
|
95
101
|
end
|
96
102
|
end
|
@@ -115,6 +121,12 @@ module RDF
|
|
115
121
|
# @return [Array<RDF::CLI::Option>]
|
116
122
|
def self.options
|
117
123
|
[
|
124
|
+
RDF::CLI::Option.new(
|
125
|
+
symbol: :base_uri,
|
126
|
+
control: :url,
|
127
|
+
datatype: RDF::URI,
|
128
|
+
on: ["--uri URI"],
|
129
|
+
description: "Base URI of input file, defaults to the filename.") {|arg| RDF::URI(arg)},
|
118
130
|
RDF::CLI::Option.new(
|
119
131
|
symbol: :canonicalize,
|
120
132
|
datatype: TrueClass,
|
@@ -147,11 +159,11 @@ module RDF
|
|
147
159
|
end
|
148
160
|
end,
|
149
161
|
RDF::CLI::Option.new(
|
150
|
-
symbol: :
|
151
|
-
control: :
|
152
|
-
datatype:
|
153
|
-
on: ["--
|
154
|
-
description: "
|
162
|
+
symbol: :rdfstar,
|
163
|
+
control: :select,
|
164
|
+
datatype: [:PG, :SA],
|
165
|
+
on: ["--rdf-star MODE"],
|
166
|
+
description: "Parse RDF*, either in Property Graph mode (PG) or Separate Assertions mode (SA).") {|arg| arg.to_sym},
|
155
167
|
RDF::CLI::Option.new(
|
156
168
|
symbol: :validate,
|
157
169
|
datatype: TrueClass,
|
@@ -206,7 +218,7 @@ module RDF
|
|
206
218
|
headers['Accept'] ||= (self.format.accept_type + %w(*/*;q=0.1)).join(", ")
|
207
219
|
end
|
208
220
|
|
209
|
-
Util::File.open_file(filename, options) do |file|
|
221
|
+
Util::File.open_file(filename, **options) do |file|
|
210
222
|
format_options = options.dup
|
211
223
|
format_options[:content_type] ||= file.content_type if
|
212
224
|
file.respond_to?(:content_type) &&
|
@@ -229,7 +241,7 @@ module RDF
|
|
229
241
|
options[:filename] ||= filename
|
230
242
|
|
231
243
|
if reader
|
232
|
-
reader.new(file, options, &block)
|
244
|
+
reader.new(file, **options, &block)
|
233
245
|
else
|
234
246
|
raise FormatError, "unknown RDF format: #{format_options.inspect}#{"\nThis may be resolved with a require of the 'linkeddata' gem." unless Object.const_defined?(:LinkedData)}"
|
235
247
|
end
|
@@ -255,42 +267,48 @@ module RDF
|
|
255
267
|
#
|
256
268
|
# @param [IO, File, String] input
|
257
269
|
# the input stream to read
|
258
|
-
# @param [
|
259
|
-
# the
|
260
|
-
#
|
261
|
-
# whether to validate the parsed statements and values
|
270
|
+
# @param [#to_s] base_uri (nil)
|
271
|
+
# the base URI to use when resolving relative URIs (not supported by
|
272
|
+
# all readers)
|
262
273
|
# @param [Boolean] canonicalize (false)
|
263
274
|
# whether to canonicalize parsed literals
|
275
|
+
# @param [Encoding] encoding (Encoding::UTF_8)
|
276
|
+
# the encoding of the input stream
|
264
277
|
# @param [Boolean] intern (true)
|
265
278
|
# whether to intern all parsed URIs
|
279
|
+
# @param [:PG, :SA] rdfstar (nil)
|
280
|
+
# support parsing RDF* statement resources.
|
281
|
+
# If `:PG`, referenced statements are also emitted.
|
282
|
+
# If `:SA`, referenced statements are not emitted.
|
266
283
|
# @param [Hash] prefixes (Hash.new)
|
267
284
|
# the prefix mappings to use (not supported by all readers)
|
268
|
-
# @param [#to_s] base_uri (nil)
|
269
|
-
# the base URI to use when resolving relative URIs (not supported by
|
270
|
-
# all readers)
|
271
285
|
# @param [Hash{Symbol => Object}] options
|
272
286
|
# any additional options
|
287
|
+
# @param [Boolean] validate (false)
|
288
|
+
# whether to validate the parsed statements and values
|
273
289
|
# @yield [reader] `self`
|
274
290
|
# @yieldparam [RDF::Reader] reader
|
275
291
|
# @yieldreturn [void] ignored
|
276
292
|
def initialize(input = $stdin,
|
277
|
-
|
278
|
-
validate: false,
|
293
|
+
base_uri: nil,
|
279
294
|
canonicalize: false,
|
295
|
+
encoding: Encoding::UTF_8,
|
280
296
|
intern: true,
|
281
297
|
prefixes: Hash.new,
|
282
|
-
|
298
|
+
rdfstar: nil,
|
299
|
+
validate: false,
|
283
300
|
**options,
|
284
301
|
&block)
|
285
302
|
|
286
303
|
base_uri ||= input.base_uri if input.respond_to?(:base_uri)
|
287
304
|
@options = options.merge({
|
288
|
-
|
289
|
-
validate: validate,
|
305
|
+
base_uri: base_uri,
|
290
306
|
canonicalize: canonicalize,
|
307
|
+
encoding: encoding,
|
291
308
|
intern: intern,
|
292
309
|
prefixes: prefixes,
|
293
|
-
|
310
|
+
rdfstar: rdfstar,
|
311
|
+
validate: validate
|
294
312
|
})
|
295
313
|
|
296
314
|
@input = case input
|
@@ -383,6 +401,9 @@ module RDF
|
|
383
401
|
# Statements are yielded in the order that they are read from the input
|
384
402
|
# stream.
|
385
403
|
#
|
404
|
+
# If the `rdfstar` option is `:PG` and triples include
|
405
|
+
# embedded statements, they are also enumerated.
|
406
|
+
#
|
386
407
|
# @overload each_statement
|
387
408
|
# @yield [statement]
|
388
409
|
# each statement
|
@@ -399,7 +420,11 @@ module RDF
|
|
399
420
|
def each_statement(&block)
|
400
421
|
if block_given?
|
401
422
|
begin
|
402
|
-
loop
|
423
|
+
loop do
|
424
|
+
st = read_statement
|
425
|
+
block.call(st)
|
426
|
+
each_pg_statement(st, &block) if options[:rdfstar] == :PG
|
427
|
+
end
|
403
428
|
rescue EOFError
|
404
429
|
rewind rescue nil
|
405
430
|
end
|
@@ -416,6 +441,9 @@ module RDF
|
|
416
441
|
# Triples are yielded in the order that they are read from the input
|
417
442
|
# stream.
|
418
443
|
#
|
444
|
+
# If the `rdfstar` option is `:PG` and triples include
|
445
|
+
# embedded statements, they are also enumerated.
|
446
|
+
#
|
419
447
|
# @overload each_triple
|
420
448
|
# @yield [subject, predicate, object]
|
421
449
|
# each triple
|
@@ -433,7 +461,14 @@ module RDF
|
|
433
461
|
def each_triple(&block)
|
434
462
|
if block_given?
|
435
463
|
begin
|
436
|
-
loop
|
464
|
+
loop do
|
465
|
+
triple = read_triple
|
466
|
+
block.call(*triple)
|
467
|
+
if options[:rdfstar] == :PG
|
468
|
+
block.call(*triple[0].to_a) if triple[0].is_a?(Statement)
|
469
|
+
block.call(*triple[2].to_a) if triple[2].is_a?(Statement)
|
470
|
+
end
|
471
|
+
end
|
437
472
|
rescue EOFError
|
438
473
|
rewind rescue nil
|
439
474
|
end
|
@@ -544,6 +579,22 @@ module RDF
|
|
544
579
|
log_error("Expected object (found: #{current_line.inspect})", lineno: lineno, exception: RDF::ReaderError)
|
545
580
|
end
|
546
581
|
|
582
|
+
##
|
583
|
+
# Recursively emit embedded statements in Property Graph mode
|
584
|
+
#
|
585
|
+
# @param [RDF::Statement] statement
|
586
|
+
def each_pg_statement(statement, &block)
|
587
|
+
if statement.subject.is_a?(Statement)
|
588
|
+
block.call(statement.subject)
|
589
|
+
each_pg_statement(statement.subject, &block)
|
590
|
+
end
|
591
|
+
|
592
|
+
if statement.object.is_a?(Statement)
|
593
|
+
block.call(statement.object)
|
594
|
+
each_pg_statement(statement.object, &block)
|
595
|
+
end
|
596
|
+
end
|
597
|
+
|
547
598
|
public
|
548
599
|
##
|
549
600
|
# Returns the encoding of the input stream.
|
data/lib/rdf/repository.rb
CHANGED
@@ -119,9 +119,9 @@ module RDF
|
|
119
119
|
# @yieldparam [Repository]
|
120
120
|
# @return [void]
|
121
121
|
def self.load(urls, **options, &block)
|
122
|
-
self.new(options) do |repository|
|
122
|
+
self.new(**options) do |repository|
|
123
123
|
Array(urls).each do |url|
|
124
|
-
repository.load(url, options)
|
124
|
+
repository.load(url, **options)
|
125
125
|
end
|
126
126
|
|
127
127
|
if block_given?
|
@@ -182,6 +182,7 @@ module RDF
|
|
182
182
|
when :validity then @options.fetch(:with_validity, true)
|
183
183
|
when :literal_equality then true
|
184
184
|
when :atomic_write then false
|
185
|
+
when :rdfstar then false
|
185
186
|
when :snapshots then false
|
186
187
|
else false
|
187
188
|
end
|
@@ -266,6 +267,7 @@ module RDF
|
|
266
267
|
when :validity then @options.fetch(:with_validity, true)
|
267
268
|
when :literal_equality then true
|
268
269
|
when :atomic_write then true
|
270
|
+
when :rdfstar then true
|
269
271
|
when :snapshots then true
|
270
272
|
else false
|
271
273
|
end
|
@@ -340,7 +342,14 @@ module RDF
|
|
340
342
|
# @see Mutable#apply_changeset
|
341
343
|
def apply_changeset(changeset)
|
342
344
|
data = @data
|
343
|
-
changeset.deletes.each
|
345
|
+
changeset.deletes.each do |del|
|
346
|
+
if del.constant?
|
347
|
+
data = delete_from(data, del)
|
348
|
+
else
|
349
|
+
# we need this condition to handle wildcard statements
|
350
|
+
query_pattern(del) { |stmt| data = delete_from(data, stmt) }
|
351
|
+
end
|
352
|
+
end
|
344
353
|
changeset.inserts.each { |ins| data = insert_to(data, ins) }
|
345
354
|
@data = data
|
346
355
|
end
|
@@ -388,20 +397,25 @@ module RDF
|
|
388
397
|
graph_name.eql?(c)
|
389
398
|
|
390
399
|
ss = if subject.nil? || subject.is_a?(RDF::Query::Variable)
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
400
|
+
ss
|
401
|
+
elsif subject.is_a?(RDF::Query::Pattern)
|
402
|
+
# Match subjects which are statements matching this pattern
|
403
|
+
ss.keys.select {|s| s.statement? && subject.eql?(s)}.inject({}) do |memo, st|
|
404
|
+
memo.merge(st => ss[st])
|
405
|
+
end
|
406
|
+
elsif ss.has_key?(subject)
|
407
|
+
{ subject => ss[subject] }
|
408
|
+
else
|
409
|
+
[]
|
410
|
+
end
|
397
411
|
ss.each do |s, ps|
|
398
412
|
ps = if predicate.nil? || predicate.is_a?(RDF::Query::Variable)
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
413
|
+
ps
|
414
|
+
elsif ps.has_key?(predicate)
|
415
|
+
{ predicate => ps[predicate] }
|
416
|
+
else
|
417
|
+
[]
|
418
|
+
end
|
405
419
|
ps.each do |p, os|
|
406
420
|
os.each do |o, object_options|
|
407
421
|
next unless object.nil? || object.eql?(o)
|
@@ -411,7 +425,7 @@ module RDF
|
|
411
425
|
end
|
412
426
|
end
|
413
427
|
else
|
414
|
-
enum_for(:query_pattern, pattern, options)
|
428
|
+
enum_for(:query_pattern, pattern, **options)
|
415
429
|
end
|
416
430
|
end
|
417
431
|
|
@@ -512,8 +526,8 @@ module RDF
|
|
512
526
|
class SerializedTransaction < Transaction
|
513
527
|
##
|
514
528
|
# @see Transaction#initialize
|
515
|
-
def initialize(*)
|
516
|
-
super
|
529
|
+
def initialize(*args, **options, &block)
|
530
|
+
super(*args, **options, &block)
|
517
531
|
@base_snapshot = @snapshot
|
518
532
|
end
|
519
533
|
|
data/lib/rdf/transaction.rb
CHANGED
@@ -24,7 +24,7 @@ module RDF
|
|
24
24
|
# repository = RDF::Repository.new
|
25
25
|
#
|
26
26
|
# RDF::Transaction.begin(repository) do |tx|
|
27
|
-
# tx.query(predicate: RDF::Vocab::DOAP.developer) do |statement|
|
27
|
+
# tx.query({predicate: RDF::Vocab::DOAP.developer}) do |statement|
|
28
28
|
# puts statement.inspect
|
29
29
|
# end
|
30
30
|
# end
|
data/lib/rdf/util.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
module RDF; module Util
|
2
|
-
autoload :Aliasing,
|
3
|
-
autoload :Cache,
|
4
|
-
autoload :File,
|
5
|
-
autoload :Logger,
|
6
|
-
autoload :UUID,
|
2
|
+
autoload :Aliasing, 'rdf/util/aliasing'
|
3
|
+
autoload :Cache, 'rdf/util/cache'
|
4
|
+
autoload :File, 'rdf/util/file'
|
5
|
+
autoload :Logger, 'rdf/util/logger'
|
6
|
+
autoload :UUID, 'rdf/util/uuid'
|
7
|
+
autoload :Coercions, 'rdf/util/coercions'
|
7
8
|
end; end
|
data/lib/rdf/util/cache.rb
CHANGED
@@ -9,8 +9,8 @@ module RDF; module Util
|
|
9
9
|
#
|
10
10
|
# While this cache is something of an internal implementation detail of
|
11
11
|
# RDF.rb, some external libraries do currently make use of it as well,
|
12
|
-
# including [SPARQL](
|
13
|
-
# [Spira](
|
12
|
+
# including [SPARQL](https://github.com/ruby-rdf/sparql/) and
|
13
|
+
# [Spira](https://github.com/ruby-rdf/spira). Do be sure to include any changes
|
14
14
|
# here in the RDF.rb changelog.
|
15
15
|
#
|
16
16
|
# @see RDF::URI.intern
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
module RDF
|
3
|
+
module Util
|
4
|
+
module Coercions
|
5
|
+
# This is a provisional module intended to house input
|
6
|
+
# coercions. Currently the only coercion is a statement
|
7
|
+
# preprocessor that is used in e.g. {RDF::Writable#insert} and
|
8
|
+
# {RDF::Mutable#delete}.
|
9
|
+
|
10
|
+
protected
|
11
|
+
|
12
|
+
##
|
13
|
+
# Coerce an array of arguments into {RDF::Statement}, or
|
14
|
+
# {RDF::Enumerable} and then yield to a block. Note that this
|
15
|
+
# code was amalgamated from that which was sandwiched around
|
16
|
+
# both {RDF::Writable#insert_statements} and
|
17
|
+
# {RDF::Mutable#delete_statements}. The parameters `query` and
|
18
|
+
# `constant` are therefore present to handle the conditions
|
19
|
+
# where the statements contain wildcards and what to do about
|
20
|
+
# them.
|
21
|
+
#
|
22
|
+
# @example
|
23
|
+
# coerce_statements(statements) { |value| do_something(value) }
|
24
|
+
#
|
25
|
+
# @param statements [#map] The arbitrary-ish input to be manipulated
|
26
|
+
# @param query [false, true] Whether to call `query` before the block
|
27
|
+
# (as expected by {Mutable#delete_statements})
|
28
|
+
# @param constant [false, true] Whether to test if the statements
|
29
|
+
# are constant (as expected by {Mutable#delete_statements})
|
30
|
+
# @yield [RDF::Statement, RDF::Enumerable]
|
31
|
+
# @return statements
|
32
|
+
def coerce_statements(statements, query: false, constant: false, &block)
|
33
|
+
raise ArgumentError, 'expecting a block' unless block_given?
|
34
|
+
|
35
|
+
statements = statements.map do |value|
|
36
|
+
case
|
37
|
+
when value.respond_to?(:each_statement)
|
38
|
+
block.call(value)
|
39
|
+
nil
|
40
|
+
when (statement = Statement.from(value)) &&
|
41
|
+
(!constant || statement.constant?)
|
42
|
+
statement
|
43
|
+
when query
|
44
|
+
# XXX note that this only makes sense when the module is include()d
|
45
|
+
block.call(self.query(value))
|
46
|
+
nil
|
47
|
+
else
|
48
|
+
raise ArgumentError, "Not a valid statement: #{value.inspect}"
|
49
|
+
end
|
50
|
+
end.compact
|
51
|
+
|
52
|
+
block.call(statements) unless statements.empty?
|
53
|
+
|
54
|
+
# eh might as well return these
|
55
|
+
statements
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|