rdf 0.3.0.pre → 0.3.0
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.
- data/README +40 -19
- data/VERSION +1 -1
- data/lib/rdf/mixin/enumerable.rb +15 -15
- data/lib/rdf/mixin/queryable.rb +47 -28
- data/lib/rdf/model/list.rb +22 -22
- data/lib/rdf/model/literal/boolean.rb +13 -1
- data/lib/rdf/model/literal/decimal.rb +5 -2
- data/lib/rdf/model/literal/double.rb +14 -6
- data/lib/rdf/model/literal/integer.rb +2 -0
- data/lib/rdf/model/literal/numeric.rb +9 -0
- data/lib/rdf/model/literal.rb +37 -19
- data/lib/rdf/model/resource.rb +3 -3
- data/lib/rdf/model/statement.rb +16 -15
- data/lib/rdf/model/term.rb +45 -0
- data/lib/rdf/model/value.rb +2 -18
- data/lib/rdf/nquads.rb +15 -3
- data/lib/rdf/ntriples/reader.rb +4 -4
- data/lib/rdf/ntriples/writer.rb +7 -4
- data/lib/rdf/ntriples.rb +3 -3
- data/lib/rdf/query/pattern.rb +95 -59
- data/lib/rdf/query/solution.rb +9 -9
- data/lib/rdf/query/variable.rb +9 -9
- data/lib/rdf/query.rb +62 -40
- data/lib/rdf/reader.rb +6 -5
- data/lib/rdf/repository.rb +40 -22
- data/lib/rdf/util/aliasing.rb +3 -3
- data/lib/rdf/util/cache.rb +8 -7
- data/lib/rdf/version.rb +1 -1
- data/lib/rdf/writer.rb +15 -13
- data/lib/rdf.rb +5 -1
- metadata +12 -14
data/lib/rdf/query/pattern.rb
CHANGED
@@ -7,30 +7,27 @@ module RDF; class Query
|
|
7
7
|
# @since 0.2.2
|
8
8
|
def self.from(pattern, options = {})
|
9
9
|
case pattern
|
10
|
-
when Pattern
|
11
|
-
when Statement
|
12
|
-
|
13
|
-
when
|
14
|
-
else raise ArgumentError
|
10
|
+
when Pattern then pattern
|
11
|
+
when Array, Statement
|
12
|
+
self.new(pattern[0], pattern[1], pattern[2], options.merge(:context => pattern[3]))
|
13
|
+
when Hash then self.new(options.merge(pattern))
|
14
|
+
else raise ArgumentError, "expected RDF::Query::Pattern, RDF::Statement, Hash, or Array, but got #{pattern.inspect}"
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
-
# @return [Hash{Symbol => Object}]
|
19
|
-
attr_reader :options
|
20
|
-
|
21
18
|
##
|
22
19
|
# @overload initialize(options = {})
|
23
20
|
# @param [Hash{Symbol => Object}] options
|
24
21
|
# @option options [Variable, Resource] :subject (nil)
|
25
22
|
# @option options [Variable, URI] :predicate (nil)
|
26
|
-
# @option options [Variable,
|
23
|
+
# @option options [Variable, Term] :object (nil)
|
27
24
|
# @option options [Variable, Resource] :context (nil)
|
28
25
|
# @option options [Boolean] :optional (false)
|
29
26
|
#
|
30
27
|
# @overload initialize(subject, predicate, object, options = {})
|
31
28
|
# @param [Variable, Resource] subject
|
32
29
|
# @param [Variable, URI] predicate
|
33
|
-
# @param [Variable,
|
30
|
+
# @param [Variable, Term] object
|
34
31
|
# @param [Hash{Symbol => Object}] options
|
35
32
|
# @option options [Variable, Resource] :context (nil)
|
36
33
|
# @option options [Boolean] :optional (false)
|
@@ -48,6 +45,63 @@ module RDF; class Query
|
|
48
45
|
super
|
49
46
|
end
|
50
47
|
|
48
|
+
##
|
49
|
+
# Any additional options for this pattern.
|
50
|
+
#
|
51
|
+
# @return [Hash]
|
52
|
+
attr_reader :options
|
53
|
+
|
54
|
+
##
|
55
|
+
# The estimated cost of this pattern (for query optimization).
|
56
|
+
#
|
57
|
+
# @return [Numeric]
|
58
|
+
attr_accessor :cost
|
59
|
+
|
60
|
+
##
|
61
|
+
# Returns `true` if this is a blank pattern, with all terms being `nil`.
|
62
|
+
#
|
63
|
+
# @return [Boolean] `true` or `false`
|
64
|
+
# @since 0.3.0
|
65
|
+
def blank?
|
66
|
+
subject.nil? && predicate.nil? && object.nil? && context.nil?
|
67
|
+
end
|
68
|
+
|
69
|
+
##
|
70
|
+
# Returns `true` if this is a constant pattern, with all terms being
|
71
|
+
# either URIs, blank nodes, or literals.
|
72
|
+
#
|
73
|
+
# A constant pattern is structurally and functionally equivalent to an
|
74
|
+
# RDF statement.
|
75
|
+
#
|
76
|
+
# @return [Boolean] `true` or `false`
|
77
|
+
# @since 0.3.0
|
78
|
+
def constant?
|
79
|
+
!(variable?)
|
80
|
+
end
|
81
|
+
|
82
|
+
##
|
83
|
+
# Returns `true` if this is a variable pattern, with any term being
|
84
|
+
# `nil` or a variable.
|
85
|
+
#
|
86
|
+
# @return [Boolean] `true` or `false`
|
87
|
+
# @since 0.3.0
|
88
|
+
def variable?
|
89
|
+
subject.nil? || predicate.nil? || object.nil? || context.nil? || has_variables?
|
90
|
+
end
|
91
|
+
|
92
|
+
##
|
93
|
+
# Returns `true` if this pattern contains any variables.
|
94
|
+
#
|
95
|
+
# @return [Boolean] `true` or `false`
|
96
|
+
# @since 0.3.0
|
97
|
+
def has_variables?
|
98
|
+
subject.is_a?(Variable) ||
|
99
|
+
predicate.is_a?(Variable) ||
|
100
|
+
object.is_a?(Variable) ||
|
101
|
+
context.is_a?(Variable)
|
102
|
+
end
|
103
|
+
alias_method :variables?, :has_variables?
|
104
|
+
|
51
105
|
##
|
52
106
|
# Returns `true` if this is an optional pattern.
|
53
107
|
#
|
@@ -55,7 +109,7 @@ module RDF; class Query
|
|
55
109
|
# Pattern.new(:s, :p, :o).optional? #=> false
|
56
110
|
# Pattern.new(:s, :p, :o, :optional => true).optional? #=> true
|
57
111
|
#
|
58
|
-
# @return [Boolean]
|
112
|
+
# @return [Boolean] `true` or `false`
|
59
113
|
# @since 0.3.0
|
60
114
|
def optional?
|
61
115
|
!!options[:optional]
|
@@ -74,7 +128,7 @@ module RDF; class Query
|
|
74
128
|
#
|
75
129
|
# @param [RDF::Queryable] queryable
|
76
130
|
# the graph or repository to query
|
77
|
-
# @param [Hash{Symbol => RDF::
|
131
|
+
# @param [Hash{Symbol => RDF::Term}] bindings
|
78
132
|
# optional variable bindings to use
|
79
133
|
# @yield [statement]
|
80
134
|
# each matching statement
|
@@ -83,44 +137,35 @@ module RDF; class Query
|
|
83
137
|
# @return [Enumerator]
|
84
138
|
# an enumerator yielding matching statements
|
85
139
|
# @see RDF::Queryable#query
|
140
|
+
# @since 0.3.0
|
86
141
|
def execute(queryable, bindings = {}, &block)
|
87
|
-
|
142
|
+
query = {
|
143
|
+
:subject => subject && subject.variable? ? bindings[subject.to_sym] : subject,
|
144
|
+
:predicate => predicate && predicate.variable? ? bindings[predicate.to_sym] : predicate,
|
145
|
+
:object => object && object.variable? ? bindings[object.to_sym] : object,
|
146
|
+
# TODO: context handling?
|
147
|
+
}
|
88
148
|
|
89
|
-
#
|
90
|
-
|
91
|
-
|
92
|
-
#
|
93
|
-
|
149
|
+
# Do all the variable terms refer to distinct variables?
|
150
|
+
variables = self.variables
|
151
|
+
if variable_count == variables.size
|
152
|
+
# If so, we can just let the repository implementation handle
|
153
|
+
# everything and yield matching statements directly:
|
154
|
+
queryable.query(query, &block)
|
94
155
|
|
95
|
-
#
|
156
|
+
# No, some terms actually refer to the same variable...
|
96
157
|
else
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
queryable.query(query, &block)
|
109
|
-
|
110
|
-
# No, some terms actually refer to the same variable...
|
111
|
-
else
|
112
|
-
# Figure out which terms refer to the same variable:
|
113
|
-
terms = variables.each_key.find do |name|
|
114
|
-
terms = variable_terms(name)
|
115
|
-
break terms if terms.size > 1
|
116
|
-
end
|
117
|
-
queryable.query(query) do |statement|
|
118
|
-
# Only yield those matching statements where the variable
|
119
|
-
# constraint is also satisfied:
|
120
|
-
# FIXME: `Array#uniq` uses `#eql?` and `#hash`, not `#==`
|
121
|
-
if matches = terms.map { |term| statement.send(term) }.uniq.size.equal?(1)
|
122
|
-
block.call(statement)
|
123
|
-
end
|
158
|
+
# Figure out which terms refer to the same variable:
|
159
|
+
terms = variables.each_key.find do |name|
|
160
|
+
terms = variable_terms(name)
|
161
|
+
break terms if terms.size > 1
|
162
|
+
end
|
163
|
+
queryable.query(query) do |statement|
|
164
|
+
# Only yield those matching statements where the variable
|
165
|
+
# constraint is also satisfied:
|
166
|
+
# FIXME: `Array#uniq` uses `#eql?` and `#hash`, not `#==`
|
167
|
+
if matches = terms.map { |term| statement.send(term) }.uniq.size.equal?(1)
|
168
|
+
block.call(statement)
|
124
169
|
end
|
125
170
|
end
|
126
171
|
end
|
@@ -136,6 +181,7 @@ module RDF; class Query
|
|
136
181
|
# @param [RDF::Statement] statement
|
137
182
|
# an RDF statement to bind terms from
|
138
183
|
# @return [RDF::Query::Solution]
|
184
|
+
# @since 0.3.0
|
139
185
|
def solution(statement)
|
140
186
|
RDF::Query::Solution.new do |solution|
|
141
187
|
solution[subject.to_sym] = statement.subject if subject.variable?
|
@@ -144,16 +190,6 @@ module RDF; class Query
|
|
144
190
|
end
|
145
191
|
end
|
146
192
|
|
147
|
-
##
|
148
|
-
# Returns `true` if this pattern contains any variables.
|
149
|
-
#
|
150
|
-
# @return [Boolean] `true` or `false`
|
151
|
-
def variables?
|
152
|
-
subject.is_a?(Variable) ||
|
153
|
-
predicate.is_a?(Variable) ||
|
154
|
-
object.is_a?(Variable)
|
155
|
-
end
|
156
|
-
|
157
193
|
##
|
158
194
|
# Returns the variable terms in this pattern.
|
159
195
|
#
|
@@ -222,7 +258,7 @@ module RDF; class Query
|
|
222
258
|
##
|
223
259
|
# Returns all bindings in this pattern.
|
224
260
|
#
|
225
|
-
# @return [Hash{Symbol =>
|
261
|
+
# @return [Hash{Symbol => RDF::Term}]
|
226
262
|
def bindings
|
227
263
|
bindings = {}
|
228
264
|
bindings.merge!(subject.bindings) if subject.is_a?(Variable)
|
@@ -234,7 +270,7 @@ module RDF; class Query
|
|
234
270
|
##
|
235
271
|
# Returns `true` if all variables in this pattern are bound.
|
236
272
|
#
|
237
|
-
# @return [Boolean]
|
273
|
+
# @return [Boolean] `true` or `false`
|
238
274
|
def bound?
|
239
275
|
!variables.empty? && variables.values.all?(&:bound?)
|
240
276
|
end
|
@@ -250,7 +286,7 @@ module RDF; class Query
|
|
250
286
|
##
|
251
287
|
# Returns `true` if all variables in this pattern are unbound.
|
252
288
|
#
|
253
|
-
# @return [Boolean]
|
289
|
+
# @return [Boolean] `true` or `false`
|
254
290
|
def unbound?
|
255
291
|
!variables.empty? && variables.values.all?(&:unbound?)
|
256
292
|
end
|
data/lib/rdf/query/solution.rb
CHANGED
@@ -31,7 +31,7 @@ class RDF::Query
|
|
31
31
|
##
|
32
32
|
# Initializes the query solution.
|
33
33
|
#
|
34
|
-
# @param [Hash{Symbol => RDF::
|
34
|
+
# @param [Hash{Symbol => RDF::Term}] bindings
|
35
35
|
# @yield [solution]
|
36
36
|
def initialize(bindings = {}, &block)
|
37
37
|
@bindings = bindings.to_hash
|
@@ -52,7 +52,7 @@ class RDF::Query
|
|
52
52
|
#
|
53
53
|
# @yield [name, value]
|
54
54
|
# @yieldparam [Symbol] name
|
55
|
-
# @yieldparam [RDF::
|
55
|
+
# @yieldparam [RDF::Term] value
|
56
56
|
# @return [Enumerator]
|
57
57
|
def each_binding(&block)
|
58
58
|
@bindings.each(&block)
|
@@ -74,7 +74,7 @@ class RDF::Query
|
|
74
74
|
# Enumerates over every variable value in this solution.
|
75
75
|
#
|
76
76
|
# @yield [value]
|
77
|
-
# @yieldparam [RDF::
|
77
|
+
# @yieldparam [RDF::Term] value
|
78
78
|
# @return [Enumerator]
|
79
79
|
def each_value(&block)
|
80
80
|
@bindings.each_value(&block)
|
@@ -129,7 +129,7 @@ class RDF::Query
|
|
129
129
|
#
|
130
130
|
# @param [Symbol, #to_sym] name
|
131
131
|
# the variable name
|
132
|
-
# @return [RDF::
|
132
|
+
# @return [RDF::Term]
|
133
133
|
def [](name)
|
134
134
|
@bindings[name.to_sym]
|
135
135
|
end
|
@@ -139,8 +139,8 @@ class RDF::Query
|
|
139
139
|
#
|
140
140
|
# @param [Symbol, #to_sym] name
|
141
141
|
# the variable name
|
142
|
-
# @param [RDF::
|
143
|
-
# @return [RDF::
|
142
|
+
# @param [RDF::Term] value
|
143
|
+
# @return [RDF::Term]
|
144
144
|
# @since 0.3.0
|
145
145
|
def []=(name, value)
|
146
146
|
@bindings[name.to_sym] = value
|
@@ -172,13 +172,13 @@ class RDF::Query
|
|
172
172
|
end
|
173
173
|
|
174
174
|
##
|
175
|
-
# @return [Array<Array(Symbol, RDF::
|
175
|
+
# @return [Array<Array(Symbol, RDF::Term)>}
|
176
176
|
def to_a
|
177
177
|
@bindings.to_a
|
178
178
|
end
|
179
179
|
|
180
180
|
##
|
181
|
-
# @return [Hash{Symbol => RDF::
|
181
|
+
# @return [Hash{Symbol => RDF::Term}}
|
182
182
|
def to_hash
|
183
183
|
@bindings.dup
|
184
184
|
end
|
@@ -193,7 +193,7 @@ class RDF::Query
|
|
193
193
|
|
194
194
|
##
|
195
195
|
# @param [Symbol] name
|
196
|
-
# @return [RDF::
|
196
|
+
# @return [RDF::Term]
|
197
197
|
def method_missing(name, *args, &block)
|
198
198
|
if args.empty? && @bindings.has_key?(name.to_sym)
|
199
199
|
@bindings[name.to_sym]
|
data/lib/rdf/query/variable.rb
CHANGED
@@ -43,7 +43,7 @@ class RDF::Query
|
|
43
43
|
# var.to_s #=> "?y=123"
|
44
44
|
#
|
45
45
|
class Variable
|
46
|
-
include RDF::
|
46
|
+
include RDF::Term
|
47
47
|
|
48
48
|
##
|
49
49
|
# The variable's name.
|
@@ -55,13 +55,13 @@ class RDF::Query
|
|
55
55
|
##
|
56
56
|
# The variable's value.
|
57
57
|
#
|
58
|
-
# @return [RDF::
|
58
|
+
# @return [RDF::Term]
|
59
59
|
attr_accessor :value
|
60
60
|
|
61
61
|
##
|
62
62
|
# @param [Symbol, #to_sym] name
|
63
63
|
# the variable name
|
64
|
-
# @param [RDF::
|
64
|
+
# @param [RDF::Term] value
|
65
65
|
# an optional variable value
|
66
66
|
def initialize(name = nil, value = nil)
|
67
67
|
@name = (name || "g#{__id__.to_i.abs}").to_sym
|
@@ -72,7 +72,7 @@ class RDF::Query
|
|
72
72
|
# Returns `true`.
|
73
73
|
#
|
74
74
|
# @return [Boolean]
|
75
|
-
# @see RDF::
|
75
|
+
# @see RDF::Term#variable?
|
76
76
|
# @since 0.1.7
|
77
77
|
def variable?
|
78
78
|
true
|
@@ -105,8 +105,8 @@ class RDF::Query
|
|
105
105
|
##
|
106
106
|
# Rebinds this variable to the given `value`.
|
107
107
|
#
|
108
|
-
# @param [RDF::
|
109
|
-
# @return [RDF::
|
108
|
+
# @param [RDF::Term] value
|
109
|
+
# @return [RDF::Term] the previous value, if any.
|
110
110
|
def bind(value)
|
111
111
|
old_value = self.value
|
112
112
|
self.value = value
|
@@ -117,7 +117,7 @@ class RDF::Query
|
|
117
117
|
##
|
118
118
|
# Unbinds this variable, discarding any currently bound value.
|
119
119
|
#
|
120
|
-
# @return [RDF::
|
120
|
+
# @return [RDF::Term] the previous value, if any.
|
121
121
|
def unbind
|
122
122
|
old_value = self.value
|
123
123
|
self.value = nil
|
@@ -137,7 +137,7 @@ class RDF::Query
|
|
137
137
|
##
|
138
138
|
# Returns this variable's bindings (if any) as a `Hash`.
|
139
139
|
#
|
140
|
-
# @return [Hash{Symbol => RDF::
|
140
|
+
# @return [Hash{Symbol => RDF::Term}]
|
141
141
|
def bindings
|
142
142
|
unbound? ? {} : {name => value}
|
143
143
|
end
|
@@ -165,7 +165,7 @@ class RDF::Query
|
|
165
165
|
##
|
166
166
|
# Compares this variable with the given value.
|
167
167
|
#
|
168
|
-
# @param [RDF::
|
168
|
+
# @param [RDF::Term] other
|
169
169
|
# @return [Boolean]
|
170
170
|
def ===(other)
|
171
171
|
if unbound?
|
data/lib/rdf/query.rb
CHANGED
@@ -21,7 +21,7 @@ module RDF
|
|
21
21
|
# @example Executing a basic graph pattern query
|
22
22
|
# graph = RDF::Graph.load('etc/doap.nt')
|
23
23
|
# query.execute(graph).each do |solution|
|
24
|
-
# solution.inspect
|
24
|
+
# puts solution.inspect
|
25
25
|
# end
|
26
26
|
#
|
27
27
|
# @example Constructing and executing a query in one go (1)
|
@@ -153,6 +153,33 @@ module RDF
|
|
153
153
|
self
|
154
154
|
end
|
155
155
|
|
156
|
+
##
|
157
|
+
# Returns an optimized copy of this query.
|
158
|
+
#
|
159
|
+
# @param [Hash{Symbol => Object}] options
|
160
|
+
# any additional options for optimization
|
161
|
+
# @return [RDF::Query] a copy of `self`
|
162
|
+
# @since 0.3.0
|
163
|
+
def optimize(options = {})
|
164
|
+
self.dup.optimize!(options)
|
165
|
+
end
|
166
|
+
|
167
|
+
##
|
168
|
+
# Optimizes this query by reordering its constituent triple patterns
|
169
|
+
# according to their cost estimates.
|
170
|
+
#
|
171
|
+
# @param [Hash{Symbol => Object}] options
|
172
|
+
# any additional options for optimization
|
173
|
+
# @return [void] `self`
|
174
|
+
# @see RDF::Query::Pattern#cost
|
175
|
+
# @since 0.3.0
|
176
|
+
def optimize!(options = {})
|
177
|
+
@patterns.sort! do |a, b|
|
178
|
+
(a.cost || 0) <=> (b.cost || 0)
|
179
|
+
end
|
180
|
+
self
|
181
|
+
end
|
182
|
+
|
156
183
|
##
|
157
184
|
# Executes this query on the given `queryable` graph or repository.
|
158
185
|
#
|
@@ -164,51 +191,46 @@ module RDF
|
|
164
191
|
# the resulting solution sequence
|
165
192
|
# @see http://www.holygoat.co.uk/blog/entry/2005-10-25-1
|
166
193
|
def execute(queryable, options = {})
|
167
|
-
|
168
|
-
@failed = false
|
169
|
-
@patterns.each do |pattern|
|
170
|
-
case pattern.variable_count
|
171
|
-
when 0 # no variables
|
172
|
-
if pattern.execute(queryable).empty?
|
173
|
-
# return an empty solution sequence:
|
174
|
-
@solutions.clear
|
175
|
-
@failed = true
|
176
|
-
break
|
177
|
-
end
|
194
|
+
options = options.dup
|
178
195
|
|
179
|
-
|
180
|
-
|
181
|
-
@solutions << pattern.solution(statement)
|
182
|
-
end
|
196
|
+
# just so we can call #keys below without worrying
|
197
|
+
options[:bindings] ||= {}
|
183
198
|
|
184
|
-
|
199
|
+
@solutions = Solutions.new
|
200
|
+
# A quick empty solution simplifies the logic below; no special case for
|
201
|
+
# the first pattern
|
202
|
+
@solutions << RDF::Query::Solution.new({})
|
185
203
|
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
@solutions << pattern.solution(statement)
|
190
|
-
end
|
191
|
-
else # union
|
192
|
-
old_solutions, @solutions = @solutions, Solutions.new
|
193
|
-
old_solutions.each do |solution|
|
194
|
-
pattern.execute(queryable) do |statement|
|
195
|
-
@solutions << solution.merge(pattern.solution(statement))
|
196
|
-
end
|
197
|
-
end
|
198
|
-
end
|
204
|
+
@patterns.each do |pattern|
|
205
|
+
|
206
|
+
old_solutions, @solutions = @solutions, Solutions.new
|
199
207
|
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
end
|
207
|
-
@solutions[index] = nil if failed && !pattern.optional?
|
208
|
+
options[:bindings].keys.each do |variable|
|
209
|
+
if pattern.variables.include?(variable)
|
210
|
+
unbound_solutions, old_solutions = old_solutions, Solutions.new
|
211
|
+
options[:bindings][variable].each do |binding|
|
212
|
+
unbound_solutions.each do |solution|
|
213
|
+
old_solutions << solution.merge(variable => binding)
|
208
214
|
end
|
209
|
-
|
215
|
+
end
|
216
|
+
options[:bindings].delete(variable)
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
old_solutions.each do |solution|
|
221
|
+
pattern.execute(queryable, solution) do |statement|
|
222
|
+
@solutions << solution.merge(pattern.solution(statement))
|
210
223
|
end
|
211
224
|
end
|
225
|
+
|
226
|
+
# It's important to abort failed queries quickly because later patterns
|
227
|
+
# that can have constraints are often broad without them.
|
228
|
+
# We have no solutions at all:
|
229
|
+
return @solutions if @solutions.empty?
|
230
|
+
# We have no solutions for variables we should have solutions for:
|
231
|
+
if !pattern.optional? && pattern.variables.keys.any? { |variable| !@solutions.variable_names.include?(variable) }
|
232
|
+
return Solutions.new
|
233
|
+
end
|
212
234
|
end
|
213
235
|
@solutions
|
214
236
|
end
|
@@ -222,7 +244,7 @@ module RDF
|
|
222
244
|
# @return [Boolean]
|
223
245
|
# @see #matched?
|
224
246
|
def failed?
|
225
|
-
@
|
247
|
+
@solutions.empty?
|
226
248
|
end
|
227
249
|
|
228
250
|
##
|
data/lib/rdf/reader.rb
CHANGED
@@ -221,8 +221,8 @@ module RDF
|
|
221
221
|
#
|
222
222
|
# @return [RDF::URI]
|
223
223
|
def prefix(name, uri = nil)
|
224
|
-
name = name.respond_to?(:to_sym) ? name.to_sym : name.to_s.to_sym
|
225
|
-
uri.nil? ? prefixes[name] : prefixes[name] =
|
224
|
+
name = name.to_s.empty? ? nil : (name.respond_to?(:to_sym) ? name.to_sym : name.to_s.to_sym)
|
225
|
+
uri.nil? ? prefixes[name] : prefixes[name] = uri
|
226
226
|
end
|
227
227
|
alias_method :prefix!, :prefix
|
228
228
|
|
@@ -271,7 +271,7 @@ module RDF
|
|
271
271
|
# each triple
|
272
272
|
# @yieldparam [RDF::Resource] subject
|
273
273
|
# @yieldparam [RDF::URI] predicate
|
274
|
-
# @yieldparam [RDF::
|
274
|
+
# @yieldparam [RDF::Term] object
|
275
275
|
# @yieldreturn [void] ignored
|
276
276
|
# @return [void]
|
277
277
|
#
|
@@ -331,7 +331,7 @@ module RDF
|
|
331
331
|
##
|
332
332
|
# Reads a triple from the input stream.
|
333
333
|
#
|
334
|
-
# @return [Array(RDF::
|
334
|
+
# @return [Array(RDF::Term)] a triple
|
335
335
|
# @raise [NotImplementedError] unless implemented in subclass
|
336
336
|
# @abstract
|
337
337
|
def read_triple
|
@@ -423,7 +423,8 @@ module RDF
|
|
423
423
|
##
|
424
424
|
# @return [String]
|
425
425
|
def readline
|
426
|
-
@line = @input.readline
|
426
|
+
@line = @input.readline
|
427
|
+
@line.chomp!
|
427
428
|
@line.force_encoding(encoding) if @line.respond_to?(:force_encoding) # for Ruby 1.9+
|
428
429
|
@line
|
429
430
|
end
|