rdf 0.3.3 → 0.3.4
Sign up to get free protection for your applications and to get access to all the features.
- data/README +107 -20
- data/VERSION +1 -1
- data/bin/rdf +4 -8
- data/etc/doap.nt +8 -8
- data/lib/rdf.rb +1 -0
- data/lib/rdf/cli.rb +146 -19
- data/lib/rdf/format.rb +59 -10
- data/lib/rdf/mixin/type_check.rb +21 -0
- data/lib/rdf/model/graph.rb +1 -0
- data/lib/rdf/model/list.rb +36 -3
- data/lib/rdf/model/literal.rb +113 -74
- data/lib/rdf/model/literal/boolean.rb +15 -5
- data/lib/rdf/model/literal/date.rb +24 -6
- data/lib/rdf/model/literal/datetime.rb +21 -4
- data/lib/rdf/model/literal/decimal.rb +3 -128
- data/lib/rdf/model/literal/double.rb +4 -107
- data/lib/rdf/model/literal/integer.rb +3 -97
- data/lib/rdf/model/literal/numeric.rb +178 -3
- data/lib/rdf/model/literal/time.rb +23 -3
- data/lib/rdf/model/literal/token.rb +2 -2
- data/lib/rdf/model/literal/xml.rb +1 -1
- data/lib/rdf/model/node.rb +35 -5
- data/lib/rdf/model/statement.rb +7 -6
- data/lib/rdf/model/term.rb +32 -0
- data/lib/rdf/model/uri.rb +13 -7
- data/lib/rdf/model/value.rb +10 -0
- data/lib/rdf/nquads.rb +120 -3
- data/lib/rdf/ntriples/format.rb +9 -1
- data/lib/rdf/ntriples/writer.rb +1 -0
- data/lib/rdf/query.rb +121 -13
- data/lib/rdf/query/pattern.rb +28 -15
- data/lib/rdf/query/solution.rb +47 -0
- data/lib/rdf/query/solutions.rb +45 -10
- data/lib/rdf/query/variable.rb +39 -4
- data/lib/rdf/reader.rb +47 -4
- data/lib/rdf/repository.rb +8 -4
- data/lib/rdf/util/file.rb +5 -2
- data/lib/rdf/version.rb +1 -1
- data/lib/rdf/writer.rb +34 -5
- metadata +56 -88
data/lib/rdf/model/statement.rb
CHANGED
@@ -27,7 +27,8 @@ module RDF
|
|
27
27
|
def self.from(statement, options = {})
|
28
28
|
case statement
|
29
29
|
when Array, Query::Pattern
|
30
|
-
|
30
|
+
context = statement[3] == false ? nil : statement[3]
|
31
|
+
self.new(statement[0], statement[1], statement[2], options.merge(:context => context))
|
31
32
|
when Statement then statement
|
32
33
|
when Hash then self.new(options.merge(statement))
|
33
34
|
else raise ArgumentError, "expected RDF::Statement, Hash, or Array, but got #{statement.inspect}"
|
@@ -176,7 +177,7 @@ module RDF
|
|
176
177
|
# @param [Statement] other
|
177
178
|
# @return [Boolean]
|
178
179
|
def eql?(other)
|
179
|
-
other.is_a?(Statement) && self == other && self.context == other.context
|
180
|
+
other.is_a?(Statement) && self == other && (self.context || false) == (other.context || false)
|
180
181
|
end
|
181
182
|
|
182
183
|
##
|
@@ -190,10 +191,10 @@ module RDF
|
|
190
191
|
# @param [Statement] other
|
191
192
|
# @return [Boolean]
|
192
193
|
def ===(other)
|
193
|
-
return false if has_context? && context
|
194
|
-
return false if has_subject? && subject
|
195
|
-
return false if has_predicate? && predicate
|
196
|
-
return false if has_object? && object
|
194
|
+
return false if has_context? && !context.eql?(other.context)
|
195
|
+
return false if has_subject? && !subject.eql?(other.subject)
|
196
|
+
return false if has_predicate? && !predicate.eql?(other.predicate)
|
197
|
+
return false if has_object? && !object.eql?(other.object)
|
197
198
|
return true
|
198
199
|
end
|
199
200
|
|
data/lib/rdf/model/term.rb
CHANGED
@@ -24,6 +24,38 @@ module RDF
|
|
24
24
|
self.to_s <=> other.to_s
|
25
25
|
end
|
26
26
|
|
27
|
+
##
|
28
|
+
# Compares `self` to `other` to implement RDFterm-equal.
|
29
|
+
#
|
30
|
+
# Subclasses should override this to provide a more meaningful
|
31
|
+
# implementation than the default which simply performs a string
|
32
|
+
# comparison based on `#to_s`.
|
33
|
+
#
|
34
|
+
# @abstract
|
35
|
+
# @param [Object] other
|
36
|
+
# @return [Integer] `-1`, `0`, or `1`
|
37
|
+
#
|
38
|
+
# @see http://www.w3.org/TR/rdf-sparql-query/#func-RDFterm-equal
|
39
|
+
def ==(other)
|
40
|
+
super
|
41
|
+
end
|
42
|
+
|
43
|
+
##
|
44
|
+
# Determins if `self` is the same term as `other`.
|
45
|
+
#
|
46
|
+
# Subclasses should override this to provide a more meaningful
|
47
|
+
# implementation than the default which simply performs a string
|
48
|
+
# comparison based on `#to_s`.
|
49
|
+
#
|
50
|
+
# @abstract
|
51
|
+
# @param [Object] other
|
52
|
+
# @return [Integer] `-1`, `0`, or `1`
|
53
|
+
#
|
54
|
+
# @see http://www.w3.org/TR/rdf-sparql-query/#func-sameTerm
|
55
|
+
def eql?(other)
|
56
|
+
super
|
57
|
+
end
|
58
|
+
|
27
59
|
##
|
28
60
|
# Returns `true` if this term is constant.
|
29
61
|
#
|
data/lib/rdf/model/uri.rb
CHANGED
@@ -244,8 +244,8 @@ module RDF
|
|
244
244
|
# RDF::URI.new('urn:isbn') / 125235111
|
245
245
|
# #=> RDF::URI('urn:isbn:125235111')
|
246
246
|
def /(fragment)
|
247
|
-
|
248
|
-
raise ArgumentError, "Non-absolute URI or string required, got #{
|
247
|
+
frag = fragment.respond_to?(:to_uri) ? fragment.to_uri : RDF::URI(fragment.to_s)
|
248
|
+
raise ArgumentError, "Non-absolute URI or string required, got #{frag}" unless frag.relative?
|
249
249
|
if urn?
|
250
250
|
RDF::URI.intern(to_s.sub(/:+$/,'') + ':' + fragment.to_s.sub(/^:+/,''))
|
251
251
|
else # !urn?
|
@@ -435,7 +435,7 @@ module RDF
|
|
435
435
|
alias_method :ends_with?, :end_with?
|
436
436
|
|
437
437
|
##
|
438
|
-
# Checks whether this URI
|
438
|
+
# Checks whether this URI the same term as `other'.
|
439
439
|
#
|
440
440
|
# @example
|
441
441
|
# RDF::URI('http://t.co/').eql?(RDF::URI('http://t.co/')) #=> true
|
@@ -449,7 +449,9 @@ module RDF
|
|
449
449
|
end
|
450
450
|
|
451
451
|
##
|
452
|
-
# Checks whether this URI is equal to `other
|
452
|
+
# Checks whether this URI is equal to `other` (type checking).
|
453
|
+
#
|
454
|
+
# Per SPARQL data-r2/expr-equal/eq-2-2, numeric can't be compared with other types
|
453
455
|
#
|
454
456
|
# @example
|
455
457
|
# RDF::URI('http://t.co/') == RDF::URI('http://t.co/') #=> true
|
@@ -458,11 +460,15 @@ module RDF
|
|
458
460
|
#
|
459
461
|
# @param [Object] other
|
460
462
|
# @return [Boolean] `true` or `false`
|
463
|
+
# @see http://www.w3.org/TR/rdf-sparql-query/#func-RDFterm-equal
|
461
464
|
def ==(other)
|
462
465
|
case other
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
+
when Literal
|
467
|
+
# If other is a Literal, reverse test to consolodate complex type checking logic
|
468
|
+
other == self
|
469
|
+
when String then to_s == other
|
470
|
+
when URI, Addressable::URI then to_s == other.to_s
|
471
|
+
else other.respond_to?(:to_uri) && to_s == other.to_uri.to_s
|
466
472
|
end
|
467
473
|
end
|
468
474
|
|
data/lib/rdf/model/value.rb
CHANGED
@@ -119,5 +119,15 @@ module RDF
|
|
119
119
|
def inspect!
|
120
120
|
warn(inspect)
|
121
121
|
end
|
122
|
+
|
123
|
+
##
|
124
|
+
# Default implementation of raise_error, which returns false.
|
125
|
+
# Classes including RDF::TypeCheck will raise RDF::TypeError
|
126
|
+
# instead.
|
127
|
+
#
|
128
|
+
# @return [false]
|
129
|
+
def type_error(message)
|
130
|
+
false
|
131
|
+
end
|
122
132
|
end # Value
|
123
133
|
end # RDF
|
data/lib/rdf/nquads.rb
CHANGED
@@ -4,6 +4,8 @@ module RDF
|
|
4
4
|
#
|
5
5
|
# This has not yet been implemented as of RDF.rb 0.3.x.
|
6
6
|
module NQuads
|
7
|
+
include NTriples
|
8
|
+
|
7
9
|
##
|
8
10
|
# N-Quads format specification.
|
9
11
|
#
|
@@ -15,20 +17,135 @@ module RDF
|
|
15
17
|
# RDF::Format.for(:content_type => "text/x-nquads")
|
16
18
|
#
|
17
19
|
# @see http://sw.deri.org/2008/07/n-quads/#mediatype
|
20
|
+
# @since 0.4.0
|
18
21
|
class Format < RDF::Format
|
19
22
|
content_type 'text/x-nquads', :extension => :nq
|
20
|
-
content_encoding '
|
23
|
+
content_encoding 'utf-8'
|
21
24
|
|
22
25
|
reader { RDF::NQuads::Reader }
|
23
26
|
writer { RDF::NQuads::Writer }
|
27
|
+
|
28
|
+
##
|
29
|
+
# Sample detection to see if it matches N-Quads (or N-Triples)
|
30
|
+
#
|
31
|
+
# Use a text sample to detect the format of an input file. Sub-classes implement
|
32
|
+
# a matcher sufficient to detect probably format matches, including disambiguating
|
33
|
+
# between other similar formats.
|
34
|
+
#
|
35
|
+
# @param [String] sample Beginning several bytes (about 1K) of input.
|
36
|
+
# @return [Boolean]
|
37
|
+
def self.detect(sample)
|
38
|
+
!!sample.match(%r(
|
39
|
+
(?:\s*(?:<[^>]*>) | (?:_:\w+)) # Subject
|
40
|
+
(?:\s*<[^>]*>) # Predicate
|
41
|
+
\s*
|
42
|
+
(?:(?:<[^>]*>) | (?:_:\w+) | (?:"[^"]*"(?:^^|@\S+)?)) # Object
|
43
|
+
(?:\s*<[^>]*>)? # Optional context
|
44
|
+
\s*\.
|
45
|
+
)mx) && (
|
46
|
+
!sample.match(%r(@(base|prefix|keywords))) # Not Turtle/N3
|
47
|
+
)
|
48
|
+
end
|
24
49
|
end
|
25
50
|
|
26
51
|
class Reader < NTriples::Reader
|
27
|
-
|
52
|
+
##
|
53
|
+
# @param [String] input
|
54
|
+
# @return [RDF::Term]
|
55
|
+
# @since 0.4.0
|
56
|
+
def self.parse_context(input)
|
57
|
+
parse_uri(input) || parse_node(input) || parse_literal(input)
|
58
|
+
end
|
59
|
+
|
60
|
+
##
|
61
|
+
# Read a Quad, where the context is optional
|
62
|
+
#
|
63
|
+
# @return [Array]
|
64
|
+
# @see http://sw.deri.org/2008/07/n-quads/#grammar
|
65
|
+
# @since 0.4.0
|
66
|
+
def read_triple
|
67
|
+
loop do
|
68
|
+
readline.strip! # EOFError thrown on end of input
|
69
|
+
line = @line # for backtracking input in case of parse error
|
70
|
+
|
71
|
+
begin
|
72
|
+
unless blank? || read_comment
|
73
|
+
subject = read_uriref || read_node || fail_subject
|
74
|
+
predicate = read_uriref(:intern => true) || fail_predicate
|
75
|
+
object = read_uriref || read_node || read_literal || fail_object
|
76
|
+
context = read_uriref || read_node || read_literal
|
77
|
+
return [subject, predicate, object, {:context => context}]
|
78
|
+
end
|
79
|
+
rescue RDF::ReaderError => e
|
80
|
+
@line = line # this allows #read_value to work
|
81
|
+
raise e
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
28
86
|
end # Reader
|
29
87
|
|
30
88
|
class Writer < NTriples::Writer
|
31
|
-
|
89
|
+
##
|
90
|
+
# @param [RDF::Statement] statement
|
91
|
+
# @return [void] `self`
|
92
|
+
def write_statement(statement)
|
93
|
+
write_quad(*statement.to_quad)
|
94
|
+
self
|
95
|
+
end
|
96
|
+
alias_method :insert_statement, :write_statement # support the RDF::Writable interface
|
97
|
+
|
98
|
+
##
|
99
|
+
# Outputs the N-Quads representation of a statement.
|
100
|
+
#
|
101
|
+
# @param [RDF::Resource] subject
|
102
|
+
# @param [RDF::URI] predicate
|
103
|
+
# @param [RDF::Term] object
|
104
|
+
# @return [void]
|
105
|
+
def write_quad(subject, predicate, object, context)
|
106
|
+
puts format_quad(subject, predicate, object, context)
|
107
|
+
end
|
108
|
+
|
109
|
+
##
|
110
|
+
# Returns the N-Quads representation of a statement.
|
111
|
+
#
|
112
|
+
# @param [RDF::Statement] statement
|
113
|
+
# @return [String]
|
114
|
+
# @since 0.4.0
|
115
|
+
def format_statement(statement)
|
116
|
+
format_quad(*statement.to_quad)
|
117
|
+
end
|
118
|
+
|
119
|
+
##
|
120
|
+
# Returns the N-Triples representation of a triple.
|
121
|
+
#
|
122
|
+
# @param [RDF::Resource] subject
|
123
|
+
# @param [RDF::URI] predicate
|
124
|
+
# @param [RDF::Term] object
|
125
|
+
# @param [RDF::Term] context
|
126
|
+
# @return [String]
|
127
|
+
def format_quad(subject, predicate, object, context)
|
128
|
+
s = "%s %s %s " % [subject, predicate, object].map { |value| format_term(value) }
|
129
|
+
s += format_term(context) + " " if context
|
130
|
+
s + "."
|
131
|
+
end
|
32
132
|
end # Writer
|
33
133
|
end # NQuads
|
134
|
+
|
135
|
+
|
136
|
+
##
|
137
|
+
# Extensions for `RDF::Value`.
|
138
|
+
module Value
|
139
|
+
##
|
140
|
+
# Returns the N-Triples representation of this value.
|
141
|
+
#
|
142
|
+
# This method is only available when the 'rdf/ntriples' serializer has
|
143
|
+
# been explicitly required.
|
144
|
+
#
|
145
|
+
# @return [String]
|
146
|
+
# @since 0.4.0
|
147
|
+
def to_quad
|
148
|
+
RDF::NQuads.serialize(self)
|
149
|
+
end
|
150
|
+
end # Value
|
34
151
|
end # RDF
|
data/lib/rdf/ntriples/format.rb
CHANGED
@@ -2,19 +2,27 @@ module RDF::NTriples
|
|
2
2
|
##
|
3
3
|
# N-Triples format specification.
|
4
4
|
#
|
5
|
+
# Note: Latest standards activities treat N-Triples as a subset
|
6
|
+
# of Turtle. This includes text/ntriples+turtle mime type and a
|
7
|
+
# new default encoding of utf-8.
|
8
|
+
#
|
5
9
|
# @example Obtaining an NTriples format class
|
6
10
|
# RDF::Format.for(:ntriples) #=> RDF::NTriples::Format
|
7
11
|
# RDF::Format.for("etc/doap.nt")
|
8
12
|
# RDF::Format.for(:file_name => "etc/doap.nt")
|
9
13
|
# RDF::Format.for(:file_extension => "nt")
|
10
14
|
# RDF::Format.for(:content_type => "text/plain")
|
15
|
+
# RDF::Format.for(:content_type => "text/ntriples+turtle")
|
11
16
|
#
|
12
17
|
# @see http://www.w3.org/TR/rdf-testcases/#ntriples
|
13
18
|
class Format < RDF::Format
|
14
19
|
content_type 'text/plain', :extension => :nt
|
15
|
-
|
20
|
+
content_type 'text/ntriples+turtle', :extension => :nt
|
21
|
+
content_encoding 'utf-8'
|
16
22
|
|
17
23
|
reader { RDF::NTriples::Reader }
|
18
24
|
writer { RDF::NTriples::Writer }
|
25
|
+
|
26
|
+
# No format detection, as N-Triples can be parsed by N-Quads
|
19
27
|
end
|
20
28
|
end
|
data/lib/rdf/ntriples/writer.rb
CHANGED
data/lib/rdf/query.rb
CHANGED
@@ -2,6 +2,15 @@ module RDF
|
|
2
2
|
##
|
3
3
|
# An RDF basic graph pattern (BGP) query.
|
4
4
|
#
|
5
|
+
# Named queries either match against a specifically named
|
6
|
+
# contexts if the name is an RDF::Term or bound RDF::Query::Variable.
|
7
|
+
# Names that are against unbound variables match either default
|
8
|
+
# or named contexts.
|
9
|
+
# The name of `false' will only match against the default context.
|
10
|
+
#
|
11
|
+
# Variable names cause the variable to be added to the solution set
|
12
|
+
# elements.
|
13
|
+
#
|
5
14
|
# @example Constructing a basic graph pattern query (1)
|
6
15
|
# query = RDF::Query.new do
|
7
16
|
# pattern [:person, RDF.type, FOAF.Person]
|
@@ -36,6 +45,27 @@ module RDF
|
|
36
45
|
# }
|
37
46
|
# })
|
38
47
|
#
|
48
|
+
# @example In this example, the default graph contains the names of the publishers of two named graphs. The triples in the named graphs are not visible in the default graph in this example.
|
49
|
+
# # default graph
|
50
|
+
# @prefix dc: <http://purl.org/dc/elements/1.1/
|
51
|
+
#
|
52
|
+
# <http://example.org/bob> dc:publisher "Bob" .
|
53
|
+
# <http://example.org/alice> dc:publisher "Alice" .
|
54
|
+
#
|
55
|
+
# # Named graph: http://example.org/bob
|
56
|
+
# @prefix foaf: <http://xmlns.com/foaf/0.1/> .
|
57
|
+
#
|
58
|
+
# _:a foaf:name "Bob" .
|
59
|
+
# _:a foaf:mbox <mailto:bob@oldcorp.example.org> .
|
60
|
+
#
|
61
|
+
# # Named graph: http://example.org/alice
|
62
|
+
# @prefix foaf: <http://xmlns.com/foaf/0.1/> .
|
63
|
+
#
|
64
|
+
# _:a foaf:name "Alice" .
|
65
|
+
# _:a foaf:mbox <mailto:alice@work.example.org> .
|
66
|
+
#
|
67
|
+
#
|
68
|
+
# @see http://www.w3.org/TR/rdf-sparql-query/#rdfDataset
|
39
69
|
# @since 0.3.0
|
40
70
|
class Query
|
41
71
|
autoload :Pattern, 'rdf/query/pattern'
|
@@ -95,6 +125,13 @@ module RDF
|
|
95
125
|
# @param [Hash{Symbol => Object}] options
|
96
126
|
# any additional keyword options
|
97
127
|
# @option options [RDF::Query::Solutions] :solutions (Solutions.new)
|
128
|
+
# @option options [RDF::Term, RDF::Query::Variable, Boolean] :context (nil)
|
129
|
+
# Default context for matching against queryable.
|
130
|
+
# Named queries either match against a specifically named
|
131
|
+
# contexts if the name is an RDF::Term or bound RDF::Query::Variable.
|
132
|
+
# Names that are against unbound variables match either detault
|
133
|
+
# or named contexts.
|
134
|
+
# The name of `false' will only match against the default context.
|
98
135
|
# @yield [query]
|
99
136
|
# @yieldparam [RDF::Query] query
|
100
137
|
# @yieldreturn [void] ignored
|
@@ -105,24 +142,34 @@ module RDF
|
|
105
142
|
# @param [Hash{Symbol => Object}] options
|
106
143
|
# any additional keyword options
|
107
144
|
# @option options [RDF::Query::Solutions] :solutions (Solutions.new)
|
145
|
+
# @option options [RDF::Term, RDF::Query::Variable, Boolean] :context (nil)
|
146
|
+
# Default context for matching against queryable.
|
147
|
+
# Named queries either match against a specifically named
|
148
|
+
# contexts if the name is an RDF::Term or bound RDF::Query::Variable.
|
149
|
+
# Names that are against unbound variables match either detault
|
150
|
+
# or named contexts.
|
108
151
|
# @yield [query]
|
109
152
|
# @yieldparam [RDF::Query] query
|
110
153
|
# @yieldreturn [void] ignored
|
111
|
-
def initialize(patterns
|
112
|
-
@options
|
154
|
+
def initialize(*patterns, &block)
|
155
|
+
@options = patterns.last.is_a?(Hash) ? patterns.pop.dup : {}
|
156
|
+
patterns << @options if patterns.empty?
|
113
157
|
@variables = {}
|
114
158
|
@solutions = @options.delete(:solutions) || Solutions.new
|
159
|
+
context = @options.delete(:context)
|
115
160
|
|
116
|
-
@patterns = case patterns
|
117
|
-
when Hash then compile_hash_patterns(patterns.dup)
|
118
|
-
when Array then patterns
|
119
|
-
else
|
161
|
+
@patterns = case patterns.first
|
162
|
+
when Hash then compile_hash_patterns(patterns.first.dup)
|
163
|
+
when Array then patterns.first
|
164
|
+
else patterns
|
120
165
|
end
|
121
166
|
|
167
|
+
self.context = context
|
168
|
+
|
122
169
|
if block_given?
|
123
170
|
case block.arity
|
124
|
-
when
|
125
|
-
else block
|
171
|
+
when 1 then block.call(self)
|
172
|
+
else instance_eval(&block)
|
126
173
|
end
|
127
174
|
end
|
128
175
|
end
|
@@ -183,10 +230,20 @@ module RDF
|
|
183
230
|
##
|
184
231
|
# Executes this query on the given `queryable` graph or repository.
|
185
232
|
#
|
233
|
+
# Named queries either match against a specifically named
|
234
|
+
# contexts if the name is an RDF::Term or bound RDF::Query::Variable.
|
235
|
+
# Names that are against unbound variables match either detault
|
236
|
+
# or named contexts.
|
237
|
+
# The name of `false' will only match against the default context.
|
238
|
+
#
|
186
239
|
# @param [RDF::Queryable] queryable
|
187
240
|
# the graph or repository to query
|
188
241
|
# @param [Hash{Symbol => Object}] options
|
189
242
|
# any additional keyword options
|
243
|
+
# @option options [Hash{Symbol => RDF::Term}] bindings
|
244
|
+
# optional variable bindings to use
|
245
|
+
# @option options [Hash{Symbol => RDF::Term}] solutions
|
246
|
+
# optional initial solutions for chained queries
|
190
247
|
# @return [RDF::Query::Solutions]
|
191
248
|
# the resulting solution sequence
|
192
249
|
# @see http://www.holygoat.co.uk/blog/entry/2005-10-25-1
|
@@ -196,13 +253,24 @@ module RDF
|
|
196
253
|
# just so we can call #keys below without worrying
|
197
254
|
options[:bindings] ||= {}
|
198
255
|
|
199
|
-
|
200
|
-
#
|
256
|
+
# Use provided solutions to allow for query chaining
|
257
|
+
# Otherwise, a quick empty solution simplifies the logic below; no special case for
|
201
258
|
# the first pattern
|
202
|
-
@solutions << RDF::Query::Solution.new({})
|
259
|
+
@solutions = options[:solutions] || (Solutions.new << RDF::Query::Solution.new({}))
|
260
|
+
|
261
|
+
patterns = @patterns
|
262
|
+
|
263
|
+
# Add context to pattern, if necessary
|
264
|
+
unless self.context.nil?
|
265
|
+
if patterns.empty?
|
266
|
+
patterns = [Pattern.new(nil, nil, nil, :context => self.context)]
|
267
|
+
elsif patterns.first.context.nil?
|
268
|
+
patterns.first.context = self.context
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
patterns.each do |pattern|
|
203
273
|
|
204
|
-
@patterns.each do |pattern|
|
205
|
-
|
206
274
|
old_solutions, @solutions = @solutions, Solutions.new
|
207
275
|
|
208
276
|
options[:bindings].keys.each do |variable|
|
@@ -223,6 +291,8 @@ module RDF
|
|
223
291
|
end
|
224
292
|
end
|
225
293
|
|
294
|
+
#puts "solutions after #{pattern} are #{@solutions.to_a.inspect}"
|
295
|
+
|
226
296
|
# It's important to abort failed queries quickly because later patterns
|
227
297
|
# that can have constraints are often broad without them.
|
228
298
|
# We have no solutions at all:
|
@@ -259,6 +329,44 @@ module RDF
|
|
259
329
|
!@failed
|
260
330
|
end
|
261
331
|
|
332
|
+
# Add patterns from another query to form a new Query
|
333
|
+
# @param [RDF::Query] other
|
334
|
+
# @return [RDF::Query]
|
335
|
+
def +(other)
|
336
|
+
Query.new(self.patterns + other.patterns)
|
337
|
+
end
|
338
|
+
|
339
|
+
# Is this is a named query?
|
340
|
+
# @return [Boolean]
|
341
|
+
def named?
|
342
|
+
!!options[:context]
|
343
|
+
end
|
344
|
+
|
345
|
+
# Is this is an unamed query?
|
346
|
+
# @return [Boolean]
|
347
|
+
def unnamed?
|
348
|
+
!named?
|
349
|
+
end
|
350
|
+
|
351
|
+
# Add name to query
|
352
|
+
# @param [RDF::Value] value
|
353
|
+
# @return [RDF::Value]
|
354
|
+
def context=(value)
|
355
|
+
options[:context] = value
|
356
|
+
end
|
357
|
+
|
358
|
+
# Name of this query, if any
|
359
|
+
# @return [RDF::Value]
|
360
|
+
def context
|
361
|
+
options[:context]
|
362
|
+
end
|
363
|
+
|
364
|
+
# Query has no patterns
|
365
|
+
# @return [Boolean]
|
366
|
+
def empty?
|
367
|
+
patterns.empty?
|
368
|
+
end
|
369
|
+
|
262
370
|
##
|
263
371
|
# Enumerates over each matching query solution.
|
264
372
|
#
|