rdf 3.1.5 → 3.1.10
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/README.md +27 -15
- data/VERSION +1 -1
- data/lib/rdf.rb +24 -0
- data/lib/rdf/cli.rb +38 -10
- data/lib/rdf/mixin/enumerable.rb +46 -28
- data/lib/rdf/mixin/mutable.rb +1 -1
- data/lib/rdf/model/dataset.rb +1 -1
- data/lib/rdf/model/graph.rb +14 -7
- data/lib/rdf/model/list.rb +44 -19
- data/lib/rdf/model/literal.rb +15 -14
- data/lib/rdf/model/literal/date.rb +5 -3
- data/lib/rdf/model/literal/datetime.rb +11 -7
- data/lib/rdf/model/literal/decimal.rb +12 -6
- data/lib/rdf/model/literal/double.rb +8 -8
- data/lib/rdf/model/literal/numeric.rb +34 -0
- data/lib/rdf/model/literal/time.rb +7 -5
- data/lib/rdf/model/node.rb +2 -6
- data/lib/rdf/model/statement.rb +36 -23
- data/lib/rdf/model/term.rb +8 -0
- data/lib/rdf/model/uri.rb +27 -19
- data/lib/rdf/nquads.rb +2 -2
- data/lib/rdf/ntriples/reader.rb +6 -6
- data/lib/rdf/ntriples/writer.rb +3 -3
- data/lib/rdf/query.rb +8 -1
- data/lib/rdf/query/pattern.rb +32 -38
- data/lib/rdf/query/solution.rb +8 -6
- data/lib/rdf/query/solutions.rb +5 -3
- data/lib/rdf/query/variable.rb +12 -1
- data/lib/rdf/reader.rb +6 -19
- data/lib/rdf/repository.rb +34 -25
- data/lib/rdf/transaction.rb +9 -3
- data/lib/rdf/util/cache.rb +10 -6
- data/lib/rdf/util/logger.rb +1 -1
- data/lib/rdf/vocab/writer.rb +1 -1
- data/lib/rdf/vocabulary.rb +4 -4
- data/lib/rdf/writer.rb +2 -2
- metadata +12 -12
@@ -42,7 +42,7 @@ module RDF; class Literal
|
|
42
42
|
# @see http://www.w3.org/TR/xmlschema11-2/#time
|
43
43
|
def canonicalize!
|
44
44
|
if self.valid?
|
45
|
-
@string = if
|
45
|
+
@string = if timezone?
|
46
46
|
@object.new_offset.new_offset.strftime(FORMAT[0..-4] + 'Z').sub('.000', '')
|
47
47
|
else
|
48
48
|
@object.strftime(FORMAT[0..-4]).sub('.000', '')
|
@@ -57,7 +57,7 @@ module RDF; class Literal
|
|
57
57
|
# @return [RDF::Literal]
|
58
58
|
# @see http://www.w3.org/TR/sparql11-query/#func-tz
|
59
59
|
def tz
|
60
|
-
zone =
|
60
|
+
zone = timezone? ? object.zone : ""
|
61
61
|
zone = "Z" if zone == "+00:00"
|
62
62
|
RDF::Literal(zone)
|
63
63
|
end
|
@@ -79,11 +79,13 @@ module RDF; class Literal
|
|
79
79
|
#
|
80
80
|
# @return [Boolean]
|
81
81
|
# @since 1.1.6
|
82
|
-
def
|
82
|
+
def timezone?
|
83
83
|
md = self.to_s.match(GRAMMAR)
|
84
84
|
md && !!md[2]
|
85
85
|
end
|
86
|
-
alias_method :
|
86
|
+
alias_method :tz?, :timezone?
|
87
|
+
alias_method :has_tz?, :timezone?
|
88
|
+
alias_method :has_timezone?, :timezone?
|
87
89
|
|
88
90
|
##
|
89
91
|
# Returns the value as a string.
|
@@ -101,7 +103,7 @@ module RDF; class Literal
|
|
101
103
|
# @since 1.1.6
|
102
104
|
def humanize(lang = :en)
|
103
105
|
t = object.strftime("%r")
|
104
|
-
if
|
106
|
+
if timezone?
|
105
107
|
t += if self.tz == 'Z'
|
106
108
|
" UTC"
|
107
109
|
else
|
data/lib/rdf/model/node.rb
CHANGED
@@ -13,18 +13,14 @@ module RDF
|
|
13
13
|
include RDF::Resource
|
14
14
|
|
15
15
|
##
|
16
|
-
#
|
17
|
-
# cached in memory at any one time.
|
16
|
+
# Cache size may be set through {RDF.config} using `node_cache_size`.
|
18
17
|
#
|
19
18
|
# @note caching interned nodes means that two different invocations using the same symbol will result in the same node, which may not be appropriate depending on the graph from which it is used. RDF requires that bnodes with the same label are, in fact, different bnodes, unless they are used within the same document.
|
20
|
-
CACHE_SIZE = -1 # unlimited by default
|
21
|
-
|
22
|
-
##
|
23
19
|
# @return [RDF::Util::Cache]
|
24
20
|
# @private
|
25
21
|
def self.cache
|
26
22
|
require 'rdf/util/cache' unless defined?(::RDF::Util::Cache)
|
27
|
-
@cache ||= RDF::Util::Cache.new(
|
23
|
+
@cache ||= RDF::Util::Cache.new(RDF.config.node_cache_size)
|
28
24
|
end
|
29
25
|
|
30
26
|
##
|
data/lib/rdf/model/statement.rb
CHANGED
@@ -96,7 +96,7 @@ module RDF
|
|
96
96
|
@predicate = predicate
|
97
97
|
@object = object
|
98
98
|
end
|
99
|
-
@id = @options.delete(:id) if @options.
|
99
|
+
@id = @options.delete(:id) if @options.key?(:id)
|
100
100
|
@graph_name = @options.delete(:graph_name)
|
101
101
|
initialize!
|
102
102
|
end
|
@@ -149,10 +149,10 @@ module RDF
|
|
149
149
|
#
|
150
150
|
# @return [Boolean]
|
151
151
|
def variable?
|
152
|
-
!(
|
153
|
-
|
154
|
-
|
155
|
-
(
|
152
|
+
!(subject? && subject.constant? &&
|
153
|
+
predicate? && predicate.constant? &&
|
154
|
+
object? && object.constant? &&
|
155
|
+
(graph? ? graph_name.constant? : true))
|
156
156
|
end
|
157
157
|
|
158
158
|
##
|
@@ -172,10 +172,10 @@ module RDF
|
|
172
172
|
##
|
173
173
|
# @return [Boolean]
|
174
174
|
def valid?
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
(
|
175
|
+
subject? && subject.resource? && subject.valid? &&
|
176
|
+
predicate? && predicate.uri? && predicate.valid? &&
|
177
|
+
object? && object.term? && object.valid? &&
|
178
|
+
(graph? ? (graph_name.resource? && graph_name.valid?) : true)
|
179
179
|
end
|
180
180
|
|
181
181
|
##
|
@@ -216,31 +216,37 @@ module RDF
|
|
216
216
|
|
217
217
|
##
|
218
218
|
# @return [Boolean]
|
219
|
-
def
|
219
|
+
def graph?
|
220
220
|
!!graph_name
|
221
221
|
end
|
222
|
-
alias_method :
|
222
|
+
alias_method :name?, :graph?
|
223
|
+
alias_method :has_graph?, :graph?
|
224
|
+
alias_method :has_name?, :graph?
|
223
225
|
|
224
226
|
##
|
225
227
|
# @return [Boolean]
|
226
|
-
def
|
228
|
+
def subject?
|
227
229
|
!!subject
|
228
230
|
end
|
231
|
+
alias_method :has_subject?, :subject?
|
229
232
|
|
230
233
|
##
|
231
234
|
# @return [Boolean]
|
232
|
-
def
|
235
|
+
def predicate?
|
233
236
|
!!predicate
|
234
237
|
end
|
238
|
+
alias_method :has_predicate?, :predicate?
|
235
239
|
|
236
240
|
##
|
237
241
|
# @return [Boolean]
|
238
|
-
def
|
242
|
+
def object?
|
239
243
|
!!object
|
240
244
|
end
|
245
|
+
alias_method :has_object?, :object?
|
241
246
|
|
242
247
|
##
|
243
|
-
# Returns `true` if any resource of this statement is a blank node
|
248
|
+
# Returns `true` if any resource of this statement is a blank node
|
249
|
+
# or has an embedded statement including a blank node.
|
244
250
|
#
|
245
251
|
# @return [Boolean]
|
246
252
|
# @since 2.0
|
@@ -312,10 +318,10 @@ module RDF
|
|
312
318
|
# @see RDF::Literal#eql?
|
313
319
|
# @see RDF::Query::Variable#eql?
|
314
320
|
def ===(other)
|
315
|
-
return false if
|
316
|
-
return false if
|
317
|
-
return false if
|
318
|
-
return false if
|
321
|
+
return false if object? && !object.eql?(other.object)
|
322
|
+
return false if predicate? && !predicate.eql?(other.predicate)
|
323
|
+
return false if subject? && !subject.eql?(other.subject)
|
324
|
+
return false if graph? && !graph_name.eql?(other.graph_name)
|
319
325
|
return true
|
320
326
|
end
|
321
327
|
|
@@ -359,6 +365,13 @@ module RDF
|
|
359
365
|
end
|
360
366
|
alias_method :to_a, :to_triple
|
361
367
|
|
368
|
+
##
|
369
|
+
# Returns an array of all the non-nil non-statement terms.
|
370
|
+
# @return [Array(RDF::Term)]
|
371
|
+
def terms
|
372
|
+
to_quad.map {|t| t.respond_to?(:terms) ? t.terms : t}.flatten.compact
|
373
|
+
end
|
374
|
+
|
362
375
|
##
|
363
376
|
# Canonicalizes each unfrozen term in the statement
|
364
377
|
#
|
@@ -366,10 +379,10 @@ module RDF
|
|
366
379
|
# @since 1.0.8
|
367
380
|
# @raise [ArgumentError] if any element cannot be canonicalized.
|
368
381
|
def canonicalize!
|
369
|
-
self.subject.canonicalize! if
|
370
|
-
self.predicate.canonicalize! if
|
371
|
-
self.object.canonicalize! if
|
372
|
-
self.graph_name.canonicalize! if
|
382
|
+
self.subject.canonicalize! if subject? && !self.subject.frozen?
|
383
|
+
self.predicate.canonicalize! if predicate? && !self.predicate.frozen?
|
384
|
+
self.object.canonicalize! if object? && !self.object.frozen?
|
385
|
+
self.graph_name.canonicalize! if graph? && !self.graph_name.frozen?
|
373
386
|
self.validate!
|
374
387
|
@hash = nil
|
375
388
|
self
|
data/lib/rdf/model/term.rb
CHANGED
data/lib/rdf/model/uri.rb
CHANGED
@@ -27,11 +27,6 @@ module RDF
|
|
27
27
|
class URI
|
28
28
|
include RDF::Resource
|
29
29
|
|
30
|
-
##
|
31
|
-
# Defines the maximum number of interned URI references that can be held
|
32
|
-
# cached in memory at any one time.
|
33
|
-
CACHE_SIZE = -1 # unlimited by default
|
34
|
-
|
35
30
|
# IRI components
|
36
31
|
UCSCHAR = Regexp.compile(<<-EOS.gsub(/\s+/, ''))
|
37
32
|
[\\u00A0-\\uD7FF]|[\\uF900-\\uFDCF]|[\\uFDF0-\\uFFEF]|
|
@@ -117,11 +112,13 @@ module RDF
|
|
117
112
|
).freeze
|
118
113
|
|
119
114
|
##
|
115
|
+
# Cache size may be set through {RDF.config} using `uri_cache_size`.
|
116
|
+
#
|
120
117
|
# @return [RDF::Util::Cache]
|
121
118
|
# @private
|
122
119
|
def self.cache
|
123
120
|
require 'rdf/util/cache' unless defined?(::RDF::Util::Cache)
|
124
|
-
@cache ||= RDF::Util::Cache.new(
|
121
|
+
@cache ||= RDF::Util::Cache.new(RDF.config.uri_cache_size)
|
125
122
|
end
|
126
123
|
|
127
124
|
##
|
@@ -229,13 +226,13 @@ module RDF
|
|
229
226
|
@value.dup.force_encoding(Encoding::UTF_8) if @value.encoding != Encoding::UTF_8
|
230
227
|
@value.freeze
|
231
228
|
else
|
232
|
-
%
|
229
|
+
%i(
|
233
230
|
scheme
|
234
231
|
user password userinfo
|
235
232
|
host port authority
|
236
233
|
path query fragment
|
237
|
-
).
|
238
|
-
if options.
|
234
|
+
).each do |meth|
|
235
|
+
if options.key?(meth)
|
239
236
|
self.send("#{meth}=".to_sym, options[meth])
|
240
237
|
else
|
241
238
|
self.send(meth)
|
@@ -311,12 +308,22 @@ module RDF
|
|
311
308
|
# @param [#to_s] base_uri
|
312
309
|
# @return [RDF::URI]
|
313
310
|
def relativize(base_uri)
|
314
|
-
if base_uri.to_s.
|
311
|
+
if self.to_s.start_with?(base_uri.to_s) && %w(# ?).include?(self.to_s[base_uri.to_s.length, 1]) ||
|
312
|
+
base_uri.to_s.end_with?("/", "#") &&
|
315
313
|
self.to_s.start_with?(base_uri.to_s)
|
316
|
-
RDF::URI(self.to_s[base_uri.to_s.length..-1])
|
314
|
+
return RDF::URI(self.to_s[base_uri.to_s.length..-1])
|
317
315
|
else
|
318
|
-
|
316
|
+
# Create a list of parents, for which this IRI may be relative.
|
317
|
+
u = RDF::URI(base_uri)
|
318
|
+
iri_set = u.to_s.end_with?('/') ? [u.to_s] : []
|
319
|
+
iri_set << u.to_s while (u = u.parent)
|
320
|
+
iri_set.each_with_index do |bb, index|
|
321
|
+
next unless self.to_s.start_with?(bb)
|
322
|
+
rel = "../" * index + self.to_s[bb.length..-1]
|
323
|
+
return rel.empty? ? "./" : rel
|
324
|
+
end
|
319
325
|
end
|
326
|
+
self
|
320
327
|
end
|
321
328
|
|
322
329
|
##
|
@@ -409,7 +416,7 @@ module RDF
|
|
409
416
|
# @see http://tools.ietf.org/html/rfc3986#section-5.2.2
|
410
417
|
# @see http://tools.ietf.org/html/rfc3986#section-5.2.3
|
411
418
|
def join(*uris)
|
412
|
-
joined_parts = object.dup.delete_if {|k, v|
|
419
|
+
joined_parts = object.dup.delete_if {|k, v| %i(user password host port).include?(k)}
|
413
420
|
|
414
421
|
uris.each do |uri|
|
415
422
|
uri = RDF::URI.new(uri) unless uri.is_a?(RDF::URI)
|
@@ -573,7 +580,7 @@ module RDF
|
|
573
580
|
else
|
574
581
|
RDF::URI.new(
|
575
582
|
**object.merge(path: '/').
|
576
|
-
keep_if {|k, v|
|
583
|
+
keep_if {|k, v| %i(scheme authority path).include?(k)})
|
577
584
|
end
|
578
585
|
end
|
579
586
|
|
@@ -581,13 +588,14 @@ module RDF
|
|
581
588
|
# Returns `true` if this URI is hierarchical and it's path component isn't equal to `/`.
|
582
589
|
#
|
583
590
|
# @example
|
584
|
-
# RDF::URI('http://example.org/').
|
585
|
-
# RDF::URI('http://example.org/path/').
|
591
|
+
# RDF::URI('http://example.org/').parent? #=> false
|
592
|
+
# RDF::URI('http://example.org/path/').parent? #=> true
|
586
593
|
#
|
587
594
|
# @return [Boolean] `true` or `false`
|
588
|
-
def
|
595
|
+
def parent?
|
589
596
|
!root?
|
590
597
|
end
|
598
|
+
alias_method :has_parent?, :parent?
|
591
599
|
|
592
600
|
##
|
593
601
|
# Returns a copy of this URI with the path component ascended to the
|
@@ -1115,7 +1123,7 @@ module RDF
|
|
1115
1123
|
# @param [String, #to_s] value
|
1116
1124
|
# @return [RDF::URI] self
|
1117
1125
|
def authority=(value)
|
1118
|
-
object.delete_if {|k, v|
|
1126
|
+
object.delete_if {|k, v| %i(user password host port userinfo).include?(k)}
|
1119
1127
|
object[:authority] = (value.to_s.dup.force_encoding(Encoding::UTF_8) if value)
|
1120
1128
|
user; password; userinfo; host; port
|
1121
1129
|
@value = nil
|
@@ -1145,7 +1153,7 @@ module RDF
|
|
1145
1153
|
# @param [String, #to_s] value
|
1146
1154
|
# @return [RDF::URI] self
|
1147
1155
|
def userinfo=(value)
|
1148
|
-
object.delete_if {|k, v|
|
1156
|
+
object.delete_if {|k, v| %i(user password authority).include?(k)}
|
1149
1157
|
object[:userinfo] = (value.to_s.dup.force_encoding(Encoding::UTF_8) if value)
|
1150
1158
|
user; password; authority
|
1151
1159
|
@value = nil
|
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 ||
|
72
|
+
subject = read_uriref || read_node || read_embTriple || fail_subject
|
73
73
|
predicate = read_uriref(intern: true) || fail_predicate
|
74
|
-
object = read_uriref || read_node || read_literal ||
|
74
|
+
object = read_uriref || read_node || read_literal || read_embTriple || 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)
|
data/lib/rdf/ntriples/reader.rb
CHANGED
@@ -213,7 +213,7 @@ module RDF::NTriples
|
|
213
213
|
begin
|
214
214
|
read_statement
|
215
215
|
rescue RDF::ReaderError
|
216
|
-
value = read_uriref || read_node || read_literal ||
|
216
|
+
value = read_uriref || read_node || read_literal || read_embTriple
|
217
217
|
log_recover
|
218
218
|
value
|
219
219
|
end
|
@@ -229,9 +229,9 @@ module RDF::NTriples
|
|
229
229
|
|
230
230
|
begin
|
231
231
|
unless blank? || read_comment
|
232
|
-
subject = read_uriref || read_node ||
|
232
|
+
subject = read_uriref || read_node || read_embTriple || fail_subject
|
233
233
|
predicate = read_uriref(intern: true) || fail_predicate
|
234
|
-
object = read_uriref || read_node || read_literal ||
|
234
|
+
object = read_uriref || read_node || read_literal || read_embTriple || fail_object
|
235
235
|
|
236
236
|
if validate? && !read_eos
|
237
237
|
log_error("Expected end of statement (found: #{current_line.inspect})", lineno: lineno, exception: RDF::ReaderError)
|
@@ -247,11 +247,11 @@ module RDF::NTriples
|
|
247
247
|
|
248
248
|
##
|
249
249
|
# @return [RDF::Statement]
|
250
|
-
def
|
250
|
+
def read_embTriple
|
251
251
|
if @options[:rdfstar] && match(ST_START)
|
252
|
-
subject = read_uriref || read_node ||
|
252
|
+
subject = read_uriref || read_node || read_embTriple || fail_subject
|
253
253
|
predicate = read_uriref(intern: true) || fail_predicate
|
254
|
-
object = read_uriref || read_node || read_literal ||
|
254
|
+
object = read_uriref || read_node || read_literal || read_embTriple || fail_object
|
255
255
|
if !match(ST_END)
|
256
256
|
log_error("Expected end of statement (found: #{current_line.inspect})", lineno: lineno, exception: RDF::ReaderError)
|
257
257
|
end
|
data/lib/rdf/ntriples/writer.rb
CHANGED
@@ -227,7 +227,7 @@ module RDF::NTriples
|
|
227
227
|
# @param [RDF::Statement] statement
|
228
228
|
# @param [Hash{Symbol => Object}] options ({})
|
229
229
|
# @return [String]
|
230
|
-
def
|
230
|
+
def format_embTriple(statement, **options)
|
231
231
|
"<<%s %s %s>>" % statement.to_a.map { |value| format_term(value, **options) }
|
232
232
|
end
|
233
233
|
##
|
@@ -309,8 +309,8 @@ module RDF::NTriples
|
|
309
309
|
when RDF::Literal
|
310
310
|
# Note, escaping here is more robust than in Term
|
311
311
|
text = quoted(escaped(literal.value))
|
312
|
-
text << "@#{literal.language}" if literal.
|
313
|
-
text << "^^<#{uri_for(literal.datatype)}>" if literal.
|
312
|
+
text << "@#{literal.language}" if literal.language?
|
313
|
+
text << "^^<#{uri_for(literal.datatype)}>" if literal.datatype?
|
314
314
|
text
|
315
315
|
else
|
316
316
|
quoted(escaped(literal.to_s))
|
data/lib/rdf/query.rb
CHANGED
@@ -247,15 +247,22 @@ module RDF
|
|
247
247
|
# Optimizes this query by reordering its constituent triple patterns
|
248
248
|
# according to their cost estimates.
|
249
249
|
#
|
250
|
+
# Optional patterns have greater cost than non-optional patterns so they will always come after non-optional patterns
|
251
|
+
#
|
250
252
|
# @param [Hash{Symbol => Object}] options
|
251
253
|
# any additional options for optimization
|
252
254
|
# @return [self]
|
253
255
|
# @see RDF::Query::Pattern#cost
|
254
256
|
# @since 0.3.0
|
255
257
|
def optimize!(**options)
|
256
|
-
@patterns.
|
258
|
+
optional, required = @patterns.uniq.partition(&:optional?)
|
259
|
+
required.sort! do |a, b|
|
260
|
+
(a.cost || 0) <=> (b.cost || 0)
|
261
|
+
end
|
262
|
+
optional.sort! do |a, b|
|
257
263
|
(a.cost || 0) <=> (b.cost || 0)
|
258
264
|
end
|
265
|
+
@patterns = required + optional
|
259
266
|
self
|
260
267
|
end
|
261
268
|
|
data/lib/rdf/query/pattern.rb
CHANGED
@@ -85,13 +85,13 @@ module RDF; class Query
|
|
85
85
|
#
|
86
86
|
# @return [Boolean] `true` or `false`
|
87
87
|
# @since 0.3.0
|
88
|
-
def
|
88
|
+
def variables?
|
89
89
|
subject && subject.variable? ||
|
90
90
|
predicate && predicate.variable? ||
|
91
91
|
object && object.variable? ||
|
92
92
|
graph_name && graph_name.variable?
|
93
93
|
end
|
94
|
-
alias_method :
|
94
|
+
alias_method :has_variables?, :variables?
|
95
95
|
|
96
96
|
##
|
97
97
|
# Returns `true` if this is an optional pattern.
|
@@ -111,10 +111,10 @@ module RDF; class Query
|
|
111
111
|
#
|
112
112
|
# @return [Boolean] `true` or `false`
|
113
113
|
def valid?
|
114
|
-
(
|
115
|
-
(
|
116
|
-
(
|
117
|
-
(
|
114
|
+
(subject? ? (subject.resource? || subject.variable?) && subject.valid? : true) &&
|
115
|
+
(predicate? ? (predicate.uri? || predicate.variable?) && predicate.valid? : true) &&
|
116
|
+
(object? ? (object.term? || object.variable?) && object.valid? : true) &&
|
117
|
+
(graph? ? (graph_name.resource? || graph_name.variable?) && graph_name.valid? : true)
|
118
118
|
rescue NoMethodError
|
119
119
|
false
|
120
120
|
end
|
@@ -181,16 +181,10 @@ module RDF; class Query
|
|
181
181
|
|
182
182
|
# No, some terms actually refer to the same variable...
|
183
183
|
else
|
184
|
-
#
|
185
|
-
|
186
|
-
terms = variable_terms(name)
|
187
|
-
break terms if terms.size > 1
|
188
|
-
end
|
184
|
+
# Considering embedding, figure out if variables that may appear more than once resolve to the same value.
|
185
|
+
vars = variables.keys
|
189
186
|
queryable.query(query).select do |statement|
|
190
|
-
|
191
|
-
# constraint is also satisfied:
|
192
|
-
# FIXME: `Array#uniq` uses `#eql?` and `#hash`, not `#==`
|
193
|
-
if terms.map { |term| statement.send(term) }.uniq.size.equal?(1)
|
187
|
+
if vars.all? {|var| self.var_values(var, statement).uniq.size == 1}
|
194
188
|
yield statement if block_given?
|
195
189
|
true
|
196
190
|
end
|
@@ -220,8 +214,8 @@ module RDF; class Query
|
|
220
214
|
solution[predicate.to_sym] = statement.predicate if predicate.is_a?(Variable)
|
221
215
|
solution[object.to_sym] = statement.object if object.is_a?(Variable)
|
222
216
|
solution[graph_name.to_sym] = statement.graph_name if graph_name.is_a?(Variable)
|
223
|
-
solution.merge!(subject.solution(statement.subject)) if subject.
|
224
|
-
solution.merge!(object.solution(statement.object)) if object.
|
217
|
+
solution.merge!(subject.solution(statement.subject)) if subject.respond_to?(:solution)
|
218
|
+
solution.merge!(object.solution(statement.object)) if object.respond_to?(:solution)
|
225
219
|
end
|
226
220
|
end
|
227
221
|
|
@@ -234,8 +228,11 @@ module RDF; class Query
|
|
234
228
|
# @param [Symbol, #to_sym] name
|
235
229
|
# an optional variable name
|
236
230
|
# @return [Array<Symbol>]
|
231
|
+
# @deprecated use {#var_values} instead
|
237
232
|
# @since 0.3.0
|
238
233
|
def variable_terms(name = nil)
|
234
|
+
warn "[DEPRECATION] RDF::Query::Pattern#variable_terms is deprecated and will be removed in a future version.\n" +
|
235
|
+
"Called from #{Gem.location_of_caller.join(':')}"
|
239
236
|
terms = []
|
240
237
|
terms << :subject if subject.is_a?(Variable) && (!name || name.eql?(subject.name))
|
241
238
|
terms << :predicate if predicate.is_a?(Variable) && (!name || name.eql?(predicate.name))
|
@@ -244,6 +241,20 @@ module RDF; class Query
|
|
244
241
|
terms
|
245
242
|
end
|
246
243
|
|
244
|
+
##
|
245
|
+
# Returns all values the statement in the same pattern position
|
246
|
+
#
|
247
|
+
# @param [Symbol] var
|
248
|
+
# @param [RDF::Statement] statement
|
249
|
+
# @return [Array<RDF::Term>]
|
250
|
+
def var_values(var, statement)
|
251
|
+
%i(subject predicate object graph_name).map do |position|
|
252
|
+
po = self.send(position)
|
253
|
+
so = statement.send(position)
|
254
|
+
po.var_values(var, so) if po.respond_to?(:var_values)
|
255
|
+
end.flatten.compact
|
256
|
+
end
|
257
|
+
|
247
258
|
##
|
248
259
|
# Returns the number of variables in this pattern.
|
249
260
|
#
|
@@ -254,7 +265,7 @@ module RDF; class Query
|
|
254
265
|
def variable_count
|
255
266
|
[subject, predicate, object, graph_name].inject(0) do |memo, term|
|
256
267
|
memo += (term.is_a?(Variable) ? 1 :
|
257
|
-
(term.
|
268
|
+
(term.respond_to?(:variable_count) ? term.variable_count : 0))
|
258
269
|
end
|
259
270
|
end
|
260
271
|
alias_method :cardinality, :variable_count
|
@@ -311,9 +322,9 @@ module RDF; class Query
|
|
311
322
|
def bindings
|
312
323
|
bindings = {}
|
313
324
|
bindings.merge!(subject.bindings) if subject && subject.variable?
|
314
|
-
bindings.merge!(predicate.bindings) if predicate.
|
325
|
+
bindings.merge!(predicate.bindings) if predicate && predicate.variable?
|
315
326
|
bindings.merge!(object.bindings) if object && object.variable?
|
316
|
-
bindings.merge!(graph_name.bindings) if graph_name.
|
327
|
+
bindings.merge!(graph_name.bindings) if graph_name && graph_name.variable?
|
317
328
|
bindings
|
318
329
|
end
|
319
330
|
|
@@ -354,24 +365,7 @@ module RDF; class Query
|
|
354
365
|
#
|
355
366
|
# @return [String]
|
356
367
|
def to_s
|
357
|
-
|
358
|
-
buffer << 'OPTIONAL ' if optional?
|
359
|
-
buffer << [subject, predicate, object].map do |r|
|
360
|
-
if r.is_a?(RDF::Query::Variable)
|
361
|
-
r.to_s
|
362
|
-
elsif r.is_a?(RDF::Query::Pattern)
|
363
|
-
"<<#{r.to_s[0..-3]}>>"
|
364
|
-
else
|
365
|
-
RDF::NTriples.serialize(r)
|
366
|
-
end
|
367
|
-
end.join(" ")
|
368
|
-
buffer << case graph_name
|
369
|
-
when nil, false then " ."
|
370
|
-
when Variable then " #{graph_name.to_s} ."
|
371
|
-
else " #{RDF::NTriples.serialize(graph_name)} ."
|
372
|
-
end
|
373
|
-
buffer.string
|
374
|
-
end
|
368
|
+
(optional? ? 'OPTIONAL ' : '') + super
|
375
369
|
end
|
376
370
|
end # Pattern
|
377
371
|
end; end # RDF::Query
|