rdf 3.0.13 → 3.1.4
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 +46 -11
- data/VERSION +1 -1
- data/etc/doap.nt +74 -80
- data/lib/rdf.rb +32 -23
- data/lib/rdf/changeset.rb +87 -19
- data/lib/rdf/cli.rb +6 -6
- data/lib/rdf/format.rb +17 -10
- data/lib/rdf/mixin/enumerable.rb +3 -2
- data/lib/rdf/mixin/mutable.rb +5 -15
- data/lib/rdf/mixin/queryable.rb +12 -4
- data/lib/rdf/mixin/writable.rb +9 -14
- data/lib/rdf/model/dataset.rb +1 -1
- data/lib/rdf/model/graph.rb +5 -2
- data/lib/rdf/model/list.rb +5 -5
- data/lib/rdf/model/statement.rb +30 -7
- data/lib/rdf/model/uri.rb +42 -23
- data/lib/rdf/nquads.rb +6 -6
- data/lib/rdf/ntriples.rb +6 -4
- data/lib/rdf/ntriples/reader.rb +32 -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 +2 -2
- data/lib/rdf/util/logger.rb +7 -7
- 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 +43 -4
- data/lib/rdf/vocab/xsd.rb +203 -2
- data/lib/rdf/vocabulary.rb +108 -14
- data/lib/rdf/writer.rb +32 -10
- metadata +28 -27
data/lib/rdf/model/uri.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# coding: utf-8
|
2
|
-
require '
|
2
|
+
require 'cgi'
|
3
3
|
|
4
4
|
module RDF
|
5
5
|
##
|
@@ -141,8 +141,8 @@ module RDF
|
|
141
141
|
#
|
142
142
|
# (see #initialize)
|
143
143
|
# @return [RDF::URI] an immutable, frozen URI object
|
144
|
-
def self.intern(str, *args)
|
145
|
-
(cache[(str = str.to_s).to_sym] ||= self.new(str, *args)).freeze
|
144
|
+
def self.intern(str, *args, **options)
|
145
|
+
(cache[(str = str.to_s).to_sym] ||= self.new(str, *args, **options)).freeze
|
146
146
|
end
|
147
147
|
|
148
148
|
##
|
@@ -225,11 +225,9 @@ module RDF
|
|
225
225
|
@mutex = Mutex.new
|
226
226
|
uri = args.first
|
227
227
|
if uri
|
228
|
-
@value = uri.to_s
|
229
|
-
if @value.encoding != Encoding::UTF_8
|
230
|
-
|
231
|
-
@value.freeze
|
232
|
-
end
|
228
|
+
@value = uri.to_s.dup
|
229
|
+
@value.dup.force_encoding(Encoding::UTF_8) if @value.encoding != Encoding::UTF_8
|
230
|
+
@value.freeze
|
233
231
|
else
|
234
232
|
%w(
|
235
233
|
scheme
|
@@ -402,7 +400,7 @@ module RDF
|
|
402
400
|
# @example Joining two URIs
|
403
401
|
# RDF::URI.new('http://example.org/foo/bar').join('/foo')
|
404
402
|
# #=> RDF::URI('http://example.org/foo')
|
405
|
-
# @see <
|
403
|
+
# @see <https://github.com/ruby-rdf/rdf-spec/blob/master/lib/rdf/spec/uri.rb>
|
406
404
|
# @see <http://tools.ietf.org/html/rfc3986#section-5.2>
|
407
405
|
# @see RDF::URI#/
|
408
406
|
# @see RDF::URI#+
|
@@ -441,7 +439,7 @@ module RDF
|
|
441
439
|
end
|
442
440
|
|
443
441
|
# Return joined URI
|
444
|
-
RDF::URI.new(joined_parts)
|
442
|
+
RDF::URI.new(**joined_parts)
|
445
443
|
end
|
446
444
|
|
447
445
|
##
|
@@ -473,7 +471,7 @@ module RDF
|
|
473
471
|
# @see RDF::URI#+
|
474
472
|
# @see RDF::URI#join
|
475
473
|
# @see <http://tools.ietf.org/html/rfc3986#section-5.2>
|
476
|
-
# @see <
|
474
|
+
# @see <https://github.com/ruby-rdf/rdf-spec/blob/master/lib/rdf/spec/uri.rb>
|
477
475
|
# @example Building a HTTP URL
|
478
476
|
# RDF::URI.new('http://example.org') / 'jhacker' / 'foaf.ttl'
|
479
477
|
# #=> RDF::URI('http://example.org/jhacker/foaf.ttl')
|
@@ -509,7 +507,7 @@ module RDF
|
|
509
507
|
case fragment.to_s[0,1]
|
510
508
|
when '#'
|
511
509
|
# Base ending with '/', fragment beginning with '#'. The fragment wins, we use '#'.
|
512
|
-
res.path = res.path.to_s.sub
|
510
|
+
res.path = res.path.to_s.sub(/\/*$/, '')
|
513
511
|
# Add fragment
|
514
512
|
res.fragment = fragment.to_s.sub(/^#+/,'')
|
515
513
|
else
|
@@ -574,7 +572,7 @@ module RDF
|
|
574
572
|
self
|
575
573
|
else
|
576
574
|
RDF::URI.new(
|
577
|
-
object.merge(path: '/').
|
575
|
+
**object.merge(path: '/').
|
578
576
|
keep_if {|k, v| [:scheme, :authority, :path].include?(k)})
|
579
577
|
end
|
580
578
|
end
|
@@ -659,7 +657,7 @@ module RDF
|
|
659
657
|
#
|
660
658
|
# @return [RDF::URI]
|
661
659
|
def dup
|
662
|
-
self.class.new(
|
660
|
+
self.class.new(@value, **(@object || {}))
|
663
661
|
end
|
664
662
|
|
665
663
|
##
|
@@ -848,7 +846,7 @@ module RDF
|
|
848
846
|
parts[:user] = (user.dup.force_encoding(Encoding::UTF_8) if user)
|
849
847
|
parts[:password] = (password.dup.force_encoding(Encoding::UTF_8) if password)
|
850
848
|
parts[:host] = (host.dup.force_encoding(Encoding::UTF_8) if host)
|
851
|
-
parts[:port] = (
|
849
|
+
parts[:port] = (CGI.unescape(port).to_i if port)
|
852
850
|
parts[:path] = (path.to_s.dup.force_encoding(Encoding::UTF_8) unless path.empty?)
|
853
851
|
parts[:query] = (query[1..-1].dup.force_encoding(Encoding::UTF_8) if query)
|
854
852
|
parts[:fragment] = (fragment[1..-1].dup.force_encoding(Encoding::UTF_8) if fragment)
|
@@ -904,7 +902,7 @@ module RDF
|
|
904
902
|
# Normalized version of user
|
905
903
|
# @return [String]
|
906
904
|
def normalized_user
|
907
|
-
|
905
|
+
URI.encode(CGI.unescape(user), /[^#{IUNRESERVED}|#{SUB_DELIMS}]/) if user
|
908
906
|
end
|
909
907
|
|
910
908
|
##
|
@@ -930,7 +928,7 @@ module RDF
|
|
930
928
|
# Normalized version of password
|
931
929
|
# @return [String]
|
932
930
|
def normalized_password
|
933
|
-
|
931
|
+
URI.encode(CGI.unescape(password), /[^#{IUNRESERVED}|#{SUB_DELIMS}]/) if password
|
934
932
|
end
|
935
933
|
|
936
934
|
HOST_FROM_AUTHORITY_RE = /(?:[^@]+@)?([^:]+)(?::.*)?$/.freeze
|
@@ -939,7 +937,7 @@ module RDF
|
|
939
937
|
# @return [String]
|
940
938
|
def host
|
941
939
|
object.fetch(:host) do
|
942
|
-
@object[:host] = ($1 if HOST_FROM_AUTHORITY_RE.match(@object[:authority]))
|
940
|
+
@object[:host] = ($1 if @object[:authority] && HOST_FROM_AUTHORITY_RE.match(@object[:authority]))
|
943
941
|
end
|
944
942
|
end
|
945
943
|
|
@@ -967,7 +965,7 @@ module RDF
|
|
967
965
|
# @return [String]
|
968
966
|
def port
|
969
967
|
object.fetch(:port) do
|
970
|
-
@object[:port] = ($1 if PORT_FROM_AUTHORITY_RE.match(@object[:authority]))
|
968
|
+
@object[:port] = ($1 if @object[:authority] && PORT_FROM_AUTHORITY_RE.match(@object[:authority]))
|
971
969
|
end
|
972
970
|
end
|
973
971
|
|
@@ -1182,8 +1180,8 @@ module RDF
|
|
1182
1180
|
inject(return_type == Hash ? {} : []) do |memo,kv|
|
1183
1181
|
k,v = kv.to_s.split('=', 2)
|
1184
1182
|
next if k.to_s.empty?
|
1185
|
-
k =
|
1186
|
-
v =
|
1183
|
+
k = CGI.unescape(k)
|
1184
|
+
v = CGI.unescape(v) if v
|
1187
1185
|
if return_type == Hash
|
1188
1186
|
case memo[k]
|
1189
1187
|
when nil then memo[k] = v
|
@@ -1295,9 +1293,9 @@ module RDF
|
|
1295
1293
|
def normalize_segment(value, expr, downcase = false)
|
1296
1294
|
if value
|
1297
1295
|
value = value.dup.force_encoding(Encoding::UTF_8)
|
1298
|
-
decoded =
|
1296
|
+
decoded = CGI.unescape(value)
|
1299
1297
|
decoded.downcase! if downcase
|
1300
|
-
|
1298
|
+
URI.encode(decoded, /[^(?:#{expr})]/)
|
1301
1299
|
end
|
1302
1300
|
end
|
1303
1301
|
|
@@ -1316,6 +1314,27 @@ module RDF
|
|
1316
1314
|
""
|
1317
1315
|
end
|
1318
1316
|
end
|
1317
|
+
|
1318
|
+
# URI encode matching characters in value
|
1319
|
+
# From URI gem, as this is now generally deprecated
|
1320
|
+
def self.encode(str, expr)
|
1321
|
+
str.gsub(expr) do
|
1322
|
+
us = $&
|
1323
|
+
tmp = ''
|
1324
|
+
us.each_byte do |uc|
|
1325
|
+
tmp << sprintf('%%%02X', uc)
|
1326
|
+
end
|
1327
|
+
tmp
|
1328
|
+
end.force_encoding(Encoding::US_ASCII)
|
1329
|
+
end
|
1330
|
+
|
1331
|
+
# URI decode escape sequences in value
|
1332
|
+
# From URI gem, as this is now generally deprecated
|
1333
|
+
def self.decode(str)
|
1334
|
+
enc = str.encoding
|
1335
|
+
enc = Encoding::UTF_8 if enc == Encoding::US_ASCII
|
1336
|
+
str.gsub(PCT_ENCODED) { [$&[1, 2]].pack('H2').force_encoding(enc) }
|
1337
|
+
end
|
1319
1338
|
end
|
1320
1339
|
|
1321
1340
|
# RDF::IRI is a synonym for RDF::URI
|
data/lib/rdf/nquads.rb
CHANGED
@@ -69,9 +69,9 @@ module RDF
|
|
69
69
|
|
70
70
|
begin
|
71
71
|
unless blank? || read_comment
|
72
|
-
subject = read_uriref || read_node || fail_subject
|
72
|
+
subject = read_uriref || read_node || read_rdfstar || fail_subject
|
73
73
|
predicate = read_uriref(intern: true) || fail_predicate
|
74
|
-
object = read_uriref || read_node || read_literal || fail_object
|
74
|
+
object = read_uriref || read_node || read_literal || read_rdfstar || fail_object
|
75
75
|
graph_name = read_uriref || read_node
|
76
76
|
if validate? && !read_eos
|
77
77
|
log_error("Expected end of statement (found: #{current_line.inspect})", lineno: lineno, exception: RDF::ReaderError)
|
@@ -96,7 +96,7 @@ module RDF
|
|
96
96
|
# @param [RDF::Term] object
|
97
97
|
# @return [void]
|
98
98
|
def write_quad(subject, predicate, object, graph_name)
|
99
|
-
puts format_quad(subject, predicate, object, graph_name,
|
99
|
+
puts format_quad(subject, predicate, object, graph_name, **@options)
|
100
100
|
end
|
101
101
|
|
102
102
|
##
|
@@ -107,7 +107,7 @@ module RDF
|
|
107
107
|
# @return [String]
|
108
108
|
# @since 0.4.0
|
109
109
|
def format_statement(statement, **options)
|
110
|
-
format_quad(*statement.to_quad, options)
|
110
|
+
format_quad(*statement.to_quad, **options)
|
111
111
|
end
|
112
112
|
|
113
113
|
##
|
@@ -120,8 +120,8 @@ module RDF
|
|
120
120
|
# @param [Hash{Symbol => Object}] options = ({})
|
121
121
|
# @return [String]
|
122
122
|
def format_quad(subject, predicate, object, graph_name, **options)
|
123
|
-
s = "%s %s %s " % [subject, predicate, object].map { |value| format_term(value, options) }
|
124
|
-
s += format_term(graph_name, options) + " " if graph_name
|
123
|
+
s = "%s %s %s " % [subject, predicate, object].map { |value| format_term(value, **options) }
|
124
|
+
s += format_term(graph_name, **options) + " " if graph_name
|
125
125
|
s + "."
|
126
126
|
end
|
127
127
|
end # Writer
|
data/lib/rdf/ntriples.rb
CHANGED
@@ -15,15 +15,17 @@ module RDF
|
|
15
15
|
#
|
16
16
|
# <https://rubygems.org/gems/rdf> <http://purl.org/dc/terms/title> "rdf" .
|
17
17
|
#
|
18
|
-
#
|
19
|
-
#
|
18
|
+
# ## RDFStar (RDF*)
|
19
|
+
#
|
20
|
+
# Supports statements as resources using `<<s p o>>`.
|
21
|
+
#
|
22
|
+
# ## Installation
|
20
23
|
#
|
21
24
|
# This is the only RDF serialization format that is directly supported by
|
22
25
|
# RDF.rb. Support for other formats is available in the form of add-on
|
23
26
|
# gems, e.g. 'rdf-xml' or 'rdf-json'.
|
24
27
|
#
|
25
|
-
# Documentation
|
26
|
-
# -------------
|
28
|
+
# ## Documentation
|
27
29
|
#
|
28
30
|
# * {RDF::NTriples::Format}
|
29
31
|
# * {RDF::NTriples::Reader}
|
data/lib/rdf/ntriples/reader.rb
CHANGED
@@ -1,4 +1,7 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'strscan'
|
4
|
+
|
2
5
|
module RDF::NTriples
|
3
6
|
##
|
4
7
|
# N-Triples parser.
|
@@ -25,6 +28,10 @@ module RDF::NTriples
|
|
25
28
|
# end
|
26
29
|
# end
|
27
30
|
#
|
31
|
+
# ** RDFStar (RDF*)
|
32
|
+
#
|
33
|
+
# Supports statements as resources using `<<s p o>>`.
|
34
|
+
#
|
28
35
|
# @see http://www.w3.org/TR/rdf-testcases/#ntriples
|
29
36
|
# @see http://www.w3.org/TR/n-triples/
|
30
37
|
class Reader < RDF::Reader
|
@@ -70,6 +77,10 @@ module RDF::NTriples
|
|
70
77
|
# 22
|
71
78
|
STRING_LITERAL_QUOTE = /"((?:[^\"\\\n\r]|#{ECHAR}|#{UCHAR})*)"/.freeze
|
72
79
|
|
80
|
+
# RDF*
|
81
|
+
ST_START = /^<</.freeze
|
82
|
+
ST_END = /^\s*>>/.freeze
|
83
|
+
|
73
84
|
# @see http://www.w3.org/TR/rdf-testcases/#ntrip_grammar
|
74
85
|
COMMENT = /^#\s*(.*)$/.freeze
|
75
86
|
NODEID = /^#{BLANK_NODE_LABEL}/.freeze
|
@@ -96,7 +107,7 @@ module RDF::NTriples
|
|
96
107
|
def self.unserialize(input, **options)
|
97
108
|
case input
|
98
109
|
when nil then nil
|
99
|
-
else self.new(input,
|
110
|
+
else self.new(input, logger: [], **options).read_value
|
100
111
|
end
|
101
112
|
end
|
102
113
|
|
@@ -104,20 +115,20 @@ module RDF::NTriples
|
|
104
115
|
# (see unserialize)
|
105
116
|
# @return [RDF::Resource]
|
106
117
|
def self.parse_subject(input, **options)
|
107
|
-
parse_uri(input, options) || parse_node(input, options)
|
118
|
+
parse_uri(input, **options) || parse_node(input, **options)
|
108
119
|
end
|
109
120
|
|
110
121
|
##
|
111
122
|
# (see unserialize)
|
112
123
|
# @return [RDF::URI]
|
113
|
-
def self.parse_predicate(input,
|
124
|
+
def self.parse_predicate(input, **options)
|
114
125
|
parse_uri(input, intern: true)
|
115
126
|
end
|
116
127
|
|
117
128
|
##
|
118
129
|
# (see unserialize)
|
119
130
|
def self.parse_object(input, **options)
|
120
|
-
parse_uri(input, options) || parse_node(input, options) || parse_literal(input, options)
|
131
|
+
parse_uri(input, **options) || parse_node(input, **options) || parse_literal(input, **options)
|
121
132
|
end
|
122
133
|
|
123
134
|
##
|
@@ -202,7 +213,7 @@ module RDF::NTriples
|
|
202
213
|
begin
|
203
214
|
read_statement
|
204
215
|
rescue RDF::ReaderError
|
205
|
-
value = read_uriref || read_node || read_literal
|
216
|
+
value = read_uriref || read_node || read_literal || read_rdfstar
|
206
217
|
log_recover
|
207
218
|
value
|
208
219
|
end
|
@@ -218,9 +229,9 @@ module RDF::NTriples
|
|
218
229
|
|
219
230
|
begin
|
220
231
|
unless blank? || read_comment
|
221
|
-
subject = read_uriref || read_node || fail_subject
|
232
|
+
subject = read_uriref || read_node || read_rdfstar || fail_subject
|
222
233
|
predicate = read_uriref(intern: true) || fail_predicate
|
223
|
-
object = read_uriref || read_node || read_literal || fail_object
|
234
|
+
object = read_uriref || read_node || read_literal || read_rdfstar || fail_object
|
224
235
|
|
225
236
|
if validate? && !read_eos
|
226
237
|
log_error("Expected end of statement (found: #{current_line.inspect})", lineno: lineno, exception: RDF::ReaderError)
|
@@ -234,6 +245,20 @@ module RDF::NTriples
|
|
234
245
|
end
|
235
246
|
end
|
236
247
|
|
248
|
+
##
|
249
|
+
# @return [RDF::Statement]
|
250
|
+
def read_rdfstar
|
251
|
+
if @options[:rdfstar] && match(ST_START)
|
252
|
+
subject = read_uriref || read_node || read_rdfstar || fail_subject
|
253
|
+
predicate = read_uriref(intern: true) || fail_predicate
|
254
|
+
object = read_uriref || read_node || read_literal || read_rdfstar || fail_object
|
255
|
+
if !match(ST_END)
|
256
|
+
log_error("Expected end of statement (found: #{current_line.inspect})", lineno: lineno, exception: RDF::ReaderError)
|
257
|
+
end
|
258
|
+
RDF::Statement.new(subject, predicate, object)
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
237
262
|
##
|
238
263
|
# @return [Boolean]
|
239
264
|
# @see http://www.w3.org/TR/rdf-testcases/#ntrip_grammar (comment)
|
data/lib/rdf/ntriples/writer.rb
CHANGED
@@ -208,7 +208,7 @@ module RDF::NTriples
|
|
208
208
|
# @param [RDF::Term] object
|
209
209
|
# @return [void]
|
210
210
|
def write_triple(subject, predicate, object)
|
211
|
-
puts format_triple(subject, predicate, object,
|
211
|
+
puts format_triple(subject, predicate, object, **@options)
|
212
212
|
end
|
213
213
|
|
214
214
|
##
|
@@ -221,6 +221,15 @@ module RDF::NTriples
|
|
221
221
|
format_triple(*statement.to_triple, **options)
|
222
222
|
end
|
223
223
|
|
224
|
+
##
|
225
|
+
# Returns the N-Triples representation of an RDF* reified statement.
|
226
|
+
#
|
227
|
+
# @param [RDF::Statement] statement
|
228
|
+
# @param [Hash{Symbol => Object}] options ({})
|
229
|
+
# @return [String]
|
230
|
+
def format_rdfstar(statement, **options)
|
231
|
+
"<<%s %s %s>>" % statement.to_a.map { |value| format_term(value, **options) }
|
232
|
+
end
|
224
233
|
##
|
225
234
|
# Returns the N-Triples representation of a triple.
|
226
235
|
#
|
data/lib/rdf/query.rb
CHANGED
@@ -90,7 +90,7 @@ module RDF
|
|
90
90
|
# the resulting solution sequence
|
91
91
|
# @see RDF::Query#execute
|
92
92
|
def self.execute(queryable, patterns = {}, options = {}, &block)
|
93
|
-
self.new(patterns, options, &block).execute(queryable, options)
|
93
|
+
self.new(patterns, **options, &block).execute(queryable, **options)
|
94
94
|
end
|
95
95
|
|
96
96
|
##
|
@@ -134,6 +134,12 @@ module RDF
|
|
134
134
|
# @return [Hash]
|
135
135
|
attr_reader :options
|
136
136
|
|
137
|
+
##
|
138
|
+
# Scope the query to named graphs matching value
|
139
|
+
#
|
140
|
+
# @return [RDF::Resource, RDF::Query::Variable, false] graph_name
|
141
|
+
attr_accessor :graph_name
|
142
|
+
|
137
143
|
##
|
138
144
|
# Initializes a new basic graph pattern query.
|
139
145
|
#
|
@@ -180,6 +186,7 @@ module RDF
|
|
180
186
|
@options = options.dup
|
181
187
|
@solutions = Query::Solutions(solutions)
|
182
188
|
graph_name = name if graph_name.nil?
|
189
|
+
@graph_name = graph_name
|
183
190
|
|
184
191
|
patterns << @options if patterns.empty?
|
185
192
|
|
@@ -189,8 +196,6 @@ module RDF
|
|
189
196
|
else patterns
|
190
197
|
end
|
191
198
|
|
192
|
-
self.graph_name = graph_name
|
193
|
-
|
194
199
|
if block_given?
|
195
200
|
case block.arity
|
196
201
|
when 1 then block.call(self)
|
@@ -223,7 +228,7 @@ module RDF
|
|
223
228
|
# whether this is an optional pattern
|
224
229
|
# @return [void] self
|
225
230
|
def pattern(pattern, **options)
|
226
|
-
@patterns << Pattern.from(pattern, options)
|
231
|
+
@patterns << Pattern.from(pattern, **options)
|
227
232
|
self
|
228
233
|
end
|
229
234
|
|
@@ -235,7 +240,7 @@ module RDF
|
|
235
240
|
# @return [RDF::Query] a copy of `self`
|
236
241
|
# @since 0.3.0
|
237
242
|
def optimize(**options)
|
238
|
-
self.dup.optimize!(options)
|
243
|
+
self.dup.optimize!(**options)
|
239
244
|
end
|
240
245
|
|
241
246
|
##
|
@@ -284,6 +289,8 @@ module RDF
|
|
284
289
|
# any additional keyword options
|
285
290
|
# @option options [Hash{Symbol => RDF::Term}] bindings
|
286
291
|
# optional variable bindings to use
|
292
|
+
# @option options [Boolean] :optimize
|
293
|
+
# Optimize query before execution.
|
287
294
|
# @option options [RDF::Query::Solutions] solutions
|
288
295
|
# optional initial solutions for chained queries
|
289
296
|
# @yield [solution]
|
@@ -294,9 +301,7 @@ module RDF
|
|
294
301
|
# the resulting solution sequence
|
295
302
|
# @see http://www.holygoat.co.uk/blog/entry/2005-10-25-1
|
296
303
|
# @see http://www.w3.org/TR/sparql11-query/#emptyGroupPattern
|
297
|
-
def execute(queryable, solutions: Solution.new, graph_name: nil, name: nil, **options, &block)
|
298
|
-
options = {bindings: {}}.merge(options)
|
299
|
-
|
304
|
+
def execute(queryable, bindings: {}, solutions: Solution.new, graph_name: nil, name: nil, **options, &block)
|
300
305
|
# Use provided solutions to allow for query chaining
|
301
306
|
# Otherwise, a quick empty solution simplifies the logic below; no special case for
|
302
307
|
# the first pattern
|
@@ -308,17 +313,17 @@ module RDF
|
|
308
313
|
return @solutions
|
309
314
|
end
|
310
315
|
|
316
|
+
self.optimize! if options[:optimize]
|
311
317
|
patterns = @patterns
|
312
318
|
graph_name = name if graph_name.nil?
|
313
|
-
graph_name =
|
314
|
-
options[:graph_name] = graph_name unless graph_name.nil?
|
319
|
+
@graph_name = graph_name unless graph_name.nil?
|
315
320
|
|
316
321
|
# Add graph_name to pattern, if necessary
|
317
|
-
unless graph_name.nil?
|
322
|
+
unless @graph_name.nil?
|
318
323
|
if patterns.empty?
|
319
|
-
patterns = [Pattern.new(nil, nil, nil, graph_name: graph_name)]
|
324
|
+
patterns = [Pattern.new(nil, nil, nil, graph_name: @graph_name)]
|
320
325
|
else
|
321
|
-
apply_graph_name(graph_name)
|
326
|
+
apply_graph_name(@graph_name)
|
322
327
|
end
|
323
328
|
end
|
324
329
|
|
@@ -326,15 +331,15 @@ module RDF
|
|
326
331
|
|
327
332
|
old_solutions, @solutions = @solutions, Query::Solutions()
|
328
333
|
|
329
|
-
|
334
|
+
bindings.each_key do |variable|
|
330
335
|
if pattern.variables.include?(variable)
|
331
336
|
unbound_solutions, old_solutions = old_solutions, Query::Solutions()
|
332
|
-
|
337
|
+
bindings[variable].each do |binding|
|
333
338
|
unbound_solutions.each do |solution|
|
334
339
|
old_solutions << solution.merge(variable => binding)
|
335
340
|
end
|
336
341
|
end
|
337
|
-
|
342
|
+
bindings.delete(variable)
|
338
343
|
end
|
339
344
|
end
|
340
345
|
|
@@ -407,38 +412,26 @@ module RDF
|
|
407
412
|
# Is this query scoped to a named graph?
|
408
413
|
# @return [Boolean]
|
409
414
|
def named?
|
410
|
-
!!
|
415
|
+
!!graph_name
|
411
416
|
end
|
412
417
|
|
413
418
|
# Is this query scoped to the default graph?
|
414
419
|
# @return [Boolean]
|
415
420
|
def default?
|
416
|
-
|
421
|
+
graph_name == false
|
417
422
|
end
|
418
423
|
|
419
424
|
# Is this query unscoped? This indicates that it can return results from
|
420
425
|
# either a named graph or the default graph.
|
421
426
|
# @return [Boolean]
|
422
427
|
def unnamed?
|
423
|
-
|
424
|
-
end
|
425
|
-
|
426
|
-
# Scope the query to named graphs matching value
|
427
|
-
# @param [RDF::IRI, RDF::Query::Variable] value
|
428
|
-
# @return [RDF::IRI, RDF::Query::Variable]
|
429
|
-
def graph_name=(value)
|
430
|
-
options[:graph_name] = value
|
431
|
-
end
|
432
|
-
|
433
|
-
# Scope of this query, if any
|
434
|
-
# @return [RDF::IRI, RDF::Query::Variable]
|
435
|
-
def graph_name
|
436
|
-
options[:graph_name]
|
428
|
+
graph_name.nil?
|
437
429
|
end
|
438
430
|
|
439
431
|
# Apply the graph name specified (or configured) to all patterns that have no graph name
|
440
432
|
# @param [RDF::IRI, RDF::Query::Variable] graph_name (self.graph_name)
|
441
|
-
def apply_graph_name(graph_name =
|
433
|
+
def apply_graph_name(graph_name = nil)
|
434
|
+
graph_name ||= self.graph_name
|
442
435
|
patterns.each {|pattern| pattern.graph_name = graph_name if pattern.graph_name.nil?} unless graph_name.nil?
|
443
436
|
end
|
444
437
|
|
@@ -515,8 +508,7 @@ module RDF
|
|
515
508
|
# @return [RDF::Query]
|
516
509
|
def dup
|
517
510
|
patterns = @patterns.map {|p| p.dup}
|
518
|
-
patterns
|
519
|
-
Query.new(*patterns)
|
511
|
+
Query.new(patterns, graph_name: graph_name, solutions: @solutions.dup, **options)
|
520
512
|
end
|
521
513
|
|
522
514
|
##
|