rdf 3.1.2 → 3.1.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +5 -2
- data/VERSION +1 -1
- data/bin/rdf +2 -2
- data/lib/rdf.rb +3 -0
- data/lib/rdf/changeset.rb +7 -0
- data/lib/rdf/cli.rb +11 -3
- data/lib/rdf/model/list.rb +15 -15
- data/lib/rdf/model/literal.rb +1 -0
- 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/uri.rb +21 -11
- data/lib/rdf/ntriples/reader.rb +3 -0
- data/lib/rdf/query.rb +8 -1
- data/lib/rdf/query/pattern.rb +26 -32
- data/lib/rdf/query/variable.rb +12 -1
- data/lib/rdf/repository.rb +6 -6
- data/lib/rdf/util/file.rb +3 -3
- data/lib/rdf/util/logger.rb +1 -1
- data/lib/rdf/vocab/writer.rb +3 -2
- data/lib/rdf/vocabulary.rb +40 -4
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7e220d98b1d53ade20bf5999761a948e495597dc74eaccd6830c22adadc77fa4
|
4
|
+
data.tar.gz: 13b643963aeb32f99e2c455490e3cbc661c56153abb6dd38ff192e42ce0ee5f5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9a845aa06b3cb0af80aa3e2ca0d9f051d4158258d5007032f73b974c4976e0dd9a34b8d1c55eda3fe2b5fd8c5f9ee9528647514f81387f0032e4adcbc8a0f46d
|
7
|
+
data.tar.gz: 388f74852651a13a7a24f10c6dee8767d76d44b7d002d58efc356dfae76629c7fccd0c462a19df874ee64c39516b838661e4b586847718084a41ad72644483fa
|
data/README.md
CHANGED
@@ -438,7 +438,10 @@ This repository uses [Git Flow](https://github.com/nvie/gitflow) to mange develo
|
|
438
438
|
enough, be assured we will eventually add you in there.
|
439
439
|
* Do note that in order for us to merge any non-trivial changes (as a rule
|
440
440
|
of thumb, additions larger than about 15 lines of code), we need an
|
441
|
-
explicit [public domain dedication][PDD] on record from you
|
441
|
+
explicit [public domain dedication][PDD] on record from you,
|
442
|
+
which you will be asked to agree to on the first commit to a repo within the organization.
|
443
|
+
Note that the agreement applies to all repos in the [Ruby RDF](https://github.com/ruby-rdf/) organization.
|
444
|
+
|
442
445
|
|
443
446
|
## License
|
444
447
|
|
@@ -450,7 +453,7 @@ see <https://unlicense.org/> or the accompanying {file:UNLICENSE} file.
|
|
450
453
|
[N-Quads]: https://www.w3.org/TR/n-quads/
|
451
454
|
[YARD]: https://yardoc.org/
|
452
455
|
[YARD-GS]: https://rubydoc.info/docs/yard/file/docs/GettingStarted.md
|
453
|
-
[PDD]: https://
|
456
|
+
[PDD]: https://unlicense.org/#unlicensing-contributions
|
454
457
|
[JSONLD doc]: https://rubydoc.info/github/ruby-rdf/json-ld
|
455
458
|
[LinkedData doc]: https://rubydoc.info/github/ruby-rdf/linkeddata
|
456
459
|
[Microdata doc]: https://rubydoc.info/github/ruby-rdf/rdf-microdata
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.1.
|
1
|
+
3.1.7
|
data/bin/rdf
CHANGED
data/lib/rdf.rb
CHANGED
data/lib/rdf/changeset.rb
CHANGED
@@ -218,5 +218,12 @@ module RDF
|
|
218
218
|
stmts.each { |s| send(target) << s }
|
219
219
|
end
|
220
220
|
|
221
|
+
# This simply returns its argument as a query in order to trick
|
222
|
+
# {RDF::Mutable#delete} into working.
|
223
|
+
def query(stmt)
|
224
|
+
RDF::Query.new RDF::Query::Pattern.from(stmt)
|
225
|
+
end
|
226
|
+
|
227
|
+
undef_method :load
|
221
228
|
end # Changeset
|
222
229
|
end # RDF
|
data/lib/rdf/cli.rb
CHANGED
@@ -8,7 +8,7 @@ begin
|
|
8
8
|
require 'linkeddata'
|
9
9
|
rescue LoadError
|
10
10
|
# Silently load without linkeddata, but try some others
|
11
|
-
%w(
|
11
|
+
%w(microdata n3 rdfa rdfxml reasoner tabular trig trix turtle vocab xsd json/ld ld/patch).each do |ser|
|
12
12
|
begin
|
13
13
|
require ser.include?('/') ? ser : "rdf/#{ser}"
|
14
14
|
rescue LoadError
|
@@ -296,6 +296,12 @@ module RDF
|
|
296
296
|
control: :none,
|
297
297
|
on: ["-o", "--output FILE"],
|
298
298
|
description: "File to write output, defaults to STDOUT") {|arg| File.open(arg, "w")},
|
299
|
+
RDF::CLI::Option.new(
|
300
|
+
symbol: :ordered,
|
301
|
+
control: :checkbox,
|
302
|
+
datatype: TrueClass,
|
303
|
+
on: ["--ordered"],
|
304
|
+
description: "Use order preserving repository"),
|
299
305
|
RDF::CLI::Option.new(
|
300
306
|
symbol: :format,
|
301
307
|
control: :select,
|
@@ -495,14 +501,16 @@ module RDF
|
|
495
501
|
options[:format] = options[:format].to_sym if options[:format]
|
496
502
|
options[:output_format] = options[:output_format].to_sym if options[:output_format]
|
497
503
|
|
498
|
-
@repository =
|
504
|
+
@repository = options[:ordered] ?
|
505
|
+
[].extend(RDF::Enumerable, RDF::Queryable) :
|
506
|
+
RDF::Repository.new
|
499
507
|
|
500
508
|
# Parse input files if any command requires it
|
501
509
|
if cmds.any? {|c| COMMANDS[c.to_sym][:parse]}
|
502
510
|
start = Time.new
|
503
511
|
count = 0
|
504
512
|
self.parse(args, **options) do |reader|
|
505
|
-
@repository <<
|
513
|
+
reader.each_statement {|st| @repository << st}
|
506
514
|
end
|
507
515
|
secs = Time.new - start
|
508
516
|
options[:logger].info "Parsed #{repository.count} statements with #{@readers.join(', ')} in #{secs} seconds @ #{count/secs} statements/second."
|
data/lib/rdf/model/list.rb
CHANGED
@@ -45,7 +45,7 @@ module RDF
|
|
45
45
|
# identified by `subject`, but will be invalid.
|
46
46
|
#
|
47
47
|
# @example add constructed list to existing graph
|
48
|
-
# l = RDF::List(
|
48
|
+
# l = RDF::List(values: (1, 2, 3))
|
49
49
|
# g = RDF::Graph.new << l
|
50
50
|
# g.count # => l.count
|
51
51
|
#
|
@@ -68,8 +68,8 @@ module RDF
|
|
68
68
|
if first || values.length > 0
|
69
69
|
# Intantiate the list from values, and insert the first value using subject.
|
70
70
|
values.reverse_each {|value| self.unshift(value)}
|
71
|
-
graph.insert RDF::Statement(subject, RDF.first, first || RDF.nil)
|
72
|
-
graph.insert RDF::Statement(subject, RDF.rest, @subject)
|
71
|
+
@graph.insert RDF::Statement(subject, RDF.first, first || RDF.nil)
|
72
|
+
@graph.insert RDF::Statement(subject, RDF.rest, @subject)
|
73
73
|
end
|
74
74
|
@subject = subject
|
75
75
|
else
|
@@ -175,7 +175,7 @@ module RDF
|
|
175
175
|
# @return [RDF::List]
|
176
176
|
# @see http://ruby-doc.org/core-2.2.2/Array.html#method-i-26
|
177
177
|
def &(other)
|
178
|
-
|
178
|
+
self.class.new(values: (to_a & other.to_a))
|
179
179
|
end
|
180
180
|
|
181
181
|
##
|
@@ -193,7 +193,7 @@ module RDF
|
|
193
193
|
# @return [RDF::List]
|
194
194
|
# @see http://ruby-doc.org/core-2.2.2/Array.html#method-i-7C
|
195
195
|
def |(other)
|
196
|
-
|
196
|
+
self.class.new(values: (to_a | other.to_a))
|
197
197
|
end
|
198
198
|
|
199
199
|
##
|
@@ -206,7 +206,7 @@ module RDF
|
|
206
206
|
# @return [RDF::List]
|
207
207
|
# @see http://ruby-doc.org/core-2.2.2/Array.html#method-i-2B
|
208
208
|
def +(other)
|
209
|
-
|
209
|
+
self.class.new(values: (to_a + other.to_a))
|
210
210
|
end
|
211
211
|
|
212
212
|
##
|
@@ -220,7 +220,7 @@ module RDF
|
|
220
220
|
# @return [RDF::List]
|
221
221
|
# @see http://ruby-doc.org/core-2.2.2/Array.html#method-i-2D
|
222
222
|
def -(other)
|
223
|
-
|
223
|
+
self.class.new(values: (to_a - other.to_a))
|
224
224
|
end
|
225
225
|
|
226
226
|
##
|
@@ -250,7 +250,7 @@ module RDF
|
|
250
250
|
# @see http://ruby-doc.org/core-2.2.2/Array.html#method-i-2A
|
251
251
|
def *(int_or_str)
|
252
252
|
case int_or_str
|
253
|
-
when Integer then
|
253
|
+
when Integer then self.class.new(values: (to_a * int_or_str))
|
254
254
|
else join(int_or_str.to_s)
|
255
255
|
end
|
256
256
|
end
|
@@ -538,13 +538,13 @@ module RDF
|
|
538
538
|
##
|
539
539
|
# @private
|
540
540
|
def slice_with_start_and_length(start, length)
|
541
|
-
|
541
|
+
self.class.new(values: to_a.slice(start, length))
|
542
542
|
end
|
543
543
|
|
544
544
|
##
|
545
545
|
# @private
|
546
546
|
def slice_with_range(range)
|
547
|
-
|
547
|
+
self.class.new(values: to_a.slice(range))
|
548
548
|
end
|
549
549
|
|
550
550
|
protected :slice_with_start_and_length
|
@@ -851,7 +851,7 @@ module RDF
|
|
851
851
|
# @return [RDF::List]
|
852
852
|
# @see http://ruby-doc.org/core-2.2.2/Array.html#method-i-reverse
|
853
853
|
def reverse
|
854
|
-
|
854
|
+
self.class.new(values: to_a.reverse)
|
855
855
|
end
|
856
856
|
|
857
857
|
##
|
@@ -863,7 +863,7 @@ module RDF
|
|
863
863
|
# @return [RDF::List]
|
864
864
|
# @see http://ruby-doc.org/core-2.2.2/Array.html#method-i-sort
|
865
865
|
def sort(&block)
|
866
|
-
|
866
|
+
self.class.new(values: super)
|
867
867
|
end
|
868
868
|
|
869
869
|
##
|
@@ -875,7 +875,7 @@ module RDF
|
|
875
875
|
# @return [RDF::List]
|
876
876
|
# @see http://ruby-doc.org/core-2.2.2/Array.html#method-i-sort_by
|
877
877
|
def sort_by(&block)
|
878
|
-
|
878
|
+
self.class.new(values: super)
|
879
879
|
end
|
880
880
|
|
881
881
|
##
|
@@ -887,7 +887,7 @@ module RDF
|
|
887
887
|
# @return [RDF::List]
|
888
888
|
# @see http://ruby-doc.org/core-2.2.2/Array.html#method-i-uniq
|
889
889
|
def uniq
|
890
|
-
|
890
|
+
self.class.new(values: to_a.uniq)
|
891
891
|
end
|
892
892
|
|
893
893
|
##
|
@@ -964,7 +964,7 @@ module RDF
|
|
964
964
|
case value
|
965
965
|
when nil then RDF.nil
|
966
966
|
when RDF::Value then value
|
967
|
-
when Array then
|
967
|
+
when Array then self.class.new(subject: nil, graph: graph, values: value)
|
968
968
|
else value
|
969
969
|
end
|
970
970
|
end
|
data/lib/rdf/model/literal.rb
CHANGED
@@ -118,6 +118,7 @@ module RDF
|
|
118
118
|
when ::Integer then RDF::Literal::Integer
|
119
119
|
when ::Float then RDF::Literal::Double
|
120
120
|
when ::BigDecimal then RDF::Literal::Decimal
|
121
|
+
when ::Rational then RDF::Literal::Double
|
121
122
|
when ::DateTime then RDF::Literal::DateTime
|
122
123
|
when ::Time then RDF::Literal::DateTime
|
123
124
|
when ::Date then RDF::Literal::Date
|
@@ -63,9 +63,15 @@ module RDF; class Literal
|
|
63
63
|
##
|
64
64
|
# Returns the number with no fractional part that is closest to the argument. If there are two such numbers, then the one that is closest to positive infinity is returned. An error is raised if arg is not a numeric value.
|
65
65
|
#
|
66
|
-
# @return [RDF::Literal]
|
66
|
+
# @return [RDF::Literal::Decimal]
|
67
67
|
def round
|
68
|
-
|
68
|
+
rounded = to_d.round(half: (to_d < 0 ? :down : :up))
|
69
|
+
if rounded == -0.0
|
70
|
+
# to avoid -0.0
|
71
|
+
self.class.new(0.0)
|
72
|
+
else
|
73
|
+
self.class.new(rounded)
|
74
|
+
end
|
69
75
|
end
|
70
76
|
|
71
77
|
##
|
@@ -74,9 +80,9 @@ module RDF; class Literal
|
|
74
80
|
# @example
|
75
81
|
# RDF::Literal(1).ceil #=> RDF::Literal(1)
|
76
82
|
#
|
77
|
-
# @return [RDF::Literal]
|
83
|
+
# @return [RDF::Literal::Integer]
|
78
84
|
def ceil
|
79
|
-
|
85
|
+
RDF::Literal::Integer.new(to_d.ceil)
|
80
86
|
end
|
81
87
|
|
82
88
|
##
|
@@ -85,9 +91,9 @@ module RDF; class Literal
|
|
85
91
|
# @example
|
86
92
|
# RDF::Literal(1).floor #=> RDF::Literal(1)
|
87
93
|
#
|
88
|
-
# @return [RDF::Literal]
|
94
|
+
# @return [RDF::Literal::Integer]
|
89
95
|
def floor
|
90
|
-
|
96
|
+
RDF::Literal::Integer.new(to_d.floor)
|
91
97
|
end
|
92
98
|
|
93
99
|
##
|
@@ -142,7 +142,7 @@ module RDF; class Literal
|
|
142
142
|
end
|
143
143
|
|
144
144
|
##
|
145
|
-
# Returns the smallest
|
145
|
+
# Returns the smallest integer greater than or equal to `self`.
|
146
146
|
#
|
147
147
|
# @example
|
148
148
|
# RDF::Literal(1.2).ceil #=> RDF::Literal(2)
|
@@ -150,14 +150,14 @@ module RDF; class Literal
|
|
150
150
|
# RDF::Literal(2.0).ceil #=> RDF::Literal(2)
|
151
151
|
# RDF::Literal(-2.0).ceil #=> RDF::Literal(-2)
|
152
152
|
#
|
153
|
-
# @return [RDF::Literal]
|
153
|
+
# @return [RDF::Literal::Integer]
|
154
154
|
# @since 0.2.3
|
155
155
|
def ceil
|
156
|
-
|
156
|
+
RDF::Literal::Integer.new(to_f.ceil)
|
157
157
|
end
|
158
158
|
|
159
159
|
##
|
160
|
-
# Returns the largest
|
160
|
+
# Returns the largest integer less than or equal to `self`.
|
161
161
|
#
|
162
162
|
# @example
|
163
163
|
# RDF::Literal(1.2).floor #=> RDF::Literal(1)
|
@@ -165,10 +165,10 @@ module RDF; class Literal
|
|
165
165
|
# RDF::Literal(2.0).floor #=> RDF::Literal(2)
|
166
166
|
# RDF::Literal(-2.0).floor #=> RDF::Literal(-2)
|
167
167
|
#
|
168
|
-
# @return [RDF::Literal]
|
168
|
+
# @return [RDF::Literal::Integer]
|
169
169
|
# @since 0.2.3
|
170
170
|
def floor
|
171
|
-
|
171
|
+
RDF::Literal::Integer.new(to_f.floor)
|
172
172
|
end
|
173
173
|
|
174
174
|
##
|
@@ -183,9 +183,9 @@ module RDF; class Literal
|
|
183
183
|
##
|
184
184
|
# Returns the number with no fractional part that is closest to the argument. If there are two such numbers, then the one that is closest to positive infinity is returned. An error is raised if arg is not a numeric value.
|
185
185
|
#
|
186
|
-
# @return [RDF::Literal]
|
186
|
+
# @return [RDF::Literal::Double]
|
187
187
|
def round
|
188
|
-
self.class.new(
|
188
|
+
self.class.new(to_d.round(half: (to_d < 0 ? :down : :up)))
|
189
189
|
end
|
190
190
|
|
191
191
|
##
|
@@ -123,6 +123,40 @@ module RDF; class Literal
|
|
123
123
|
end
|
124
124
|
end
|
125
125
|
|
126
|
+
##
|
127
|
+
# Exponent − Performs exponential (power) calculation on operators.
|
128
|
+
#
|
129
|
+
# Promotes values, as necessary, with the result type depending on the input values.
|
130
|
+
#
|
131
|
+
# @param [Literal::Numeric, #to_i, #to_f, #to_d] other
|
132
|
+
# @return [RDF::Literal::Numeric]
|
133
|
+
# @since 0.2.3
|
134
|
+
# @see https://www.w3.org/TR/xpath-functions/#func-math-pow
|
135
|
+
def **(other)
|
136
|
+
RDF::Literal(object ** (other.is_a?(RDF::Literal::Numeric) ? other.object : other))
|
137
|
+
rescue ZeroDivisionError
|
138
|
+
RDF::Literal::Double.new('INF')
|
139
|
+
end
|
140
|
+
|
141
|
+
##
|
142
|
+
# Exponent − Performs remainder of `self` divided by `other`.
|
143
|
+
#
|
144
|
+
# @param [Literal::Numeric, #to_i, #to_f, #to_d] other
|
145
|
+
# @return [RDF::Literal]
|
146
|
+
# @since 0.2.3
|
147
|
+
# @see https://www.w3.org/TR/xpath-functions/#func-numeric-mod
|
148
|
+
def %(other)
|
149
|
+
if self.class == Double || [Double, ::Float].include?(other.class)
|
150
|
+
self.class.new(to_f % other.to_f)
|
151
|
+
elsif ((self.class == RDF::Literal::Float || other.class == RDF::Literal::Float) rescue false)
|
152
|
+
self.class.new(to_f % other.to_f)
|
153
|
+
elsif self.class == Decimal || other.class == Decimal
|
154
|
+
self.class.new(to_d % (other.respond_to?(:to_d) ? other.to_d : BigDecimal(other.to_s)))
|
155
|
+
else
|
156
|
+
self.class.new(to_i % other.to_i)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
126
160
|
##
|
127
161
|
# Returns the quotient of `self` divided by `other`.
|
128
162
|
#
|
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
|
##
|
@@ -311,12 +311,22 @@ module RDF
|
|
311
311
|
# @param [#to_s] base_uri
|
312
312
|
# @return [RDF::URI]
|
313
313
|
def relativize(base_uri)
|
314
|
-
if base_uri.to_s.
|
314
|
+
if self.to_s.start_with?(base_uri.to_s) && %w(# ?).include?(self.to_s[base_uri.to_s.length, 1]) ||
|
315
|
+
base_uri.to_s.end_with?("/", "#") &&
|
315
316
|
self.to_s.start_with?(base_uri.to_s)
|
316
|
-
RDF::URI(self.to_s[base_uri.to_s.length..-1])
|
317
|
+
return RDF::URI(self.to_s[base_uri.to_s.length..-1])
|
317
318
|
else
|
318
|
-
|
319
|
+
# Create a list of parents, for which this IRI may be relative.
|
320
|
+
u = RDF::URI(base_uri)
|
321
|
+
iri_set = u.to_s.end_with?('/') ? [u.to_s] : []
|
322
|
+
iri_set << u.to_s while (u = u.parent)
|
323
|
+
iri_set.each_with_index do |bb, index|
|
324
|
+
next unless self.to_s.start_with?(bb)
|
325
|
+
rel = "../" * index + self.to_s[bb.length..-1]
|
326
|
+
return rel.empty? ? "./" : rel
|
327
|
+
end
|
319
328
|
end
|
329
|
+
self
|
320
330
|
end
|
321
331
|
|
322
332
|
##
|
@@ -846,7 +856,7 @@ module RDF
|
|
846
856
|
parts[:user] = (user.dup.force_encoding(Encoding::UTF_8) if user)
|
847
857
|
parts[:password] = (password.dup.force_encoding(Encoding::UTF_8) if password)
|
848
858
|
parts[:host] = (host.dup.force_encoding(Encoding::UTF_8) if host)
|
849
|
-
parts[:port] = (
|
859
|
+
parts[:port] = (CGI.unescape(port).to_i if port)
|
850
860
|
parts[:path] = (path.to_s.dup.force_encoding(Encoding::UTF_8) unless path.empty?)
|
851
861
|
parts[:query] = (query[1..-1].dup.force_encoding(Encoding::UTF_8) if query)
|
852
862
|
parts[:fragment] = (fragment[1..-1].dup.force_encoding(Encoding::UTF_8) if fragment)
|
@@ -902,7 +912,7 @@ module RDF
|
|
902
912
|
# Normalized version of user
|
903
913
|
# @return [String]
|
904
914
|
def normalized_user
|
905
|
-
URI.encode(
|
915
|
+
URI.encode(CGI.unescape(user), /[^#{IUNRESERVED}|#{SUB_DELIMS}]/).force_encoding(Encoding::UTF_8) if user
|
906
916
|
end
|
907
917
|
|
908
918
|
##
|
@@ -928,7 +938,7 @@ module RDF
|
|
928
938
|
# Normalized version of password
|
929
939
|
# @return [String]
|
930
940
|
def normalized_password
|
931
|
-
URI.encode(
|
941
|
+
URI.encode(CGI.unescape(password), /[^#{IUNRESERVED}|#{SUB_DELIMS}]/).force_encoding(Encoding::UTF_8) if password
|
932
942
|
end
|
933
943
|
|
934
944
|
HOST_FROM_AUTHORITY_RE = /(?:[^@]+@)?([^:]+)(?::.*)?$/.freeze
|
@@ -1180,8 +1190,8 @@ module RDF
|
|
1180
1190
|
inject(return_type == Hash ? {} : []) do |memo,kv|
|
1181
1191
|
k,v = kv.to_s.split('=', 2)
|
1182
1192
|
next if k.to_s.empty?
|
1183
|
-
k =
|
1184
|
-
v =
|
1193
|
+
k = CGI.unescape(k)
|
1194
|
+
v = CGI.unescape(v) if v
|
1185
1195
|
if return_type == Hash
|
1186
1196
|
case memo[k]
|
1187
1197
|
when nil then memo[k] = v
|
@@ -1293,9 +1303,9 @@ module RDF
|
|
1293
1303
|
def normalize_segment(value, expr, downcase = false)
|
1294
1304
|
if value
|
1295
1305
|
value = value.dup.force_encoding(Encoding::UTF_8)
|
1296
|
-
decoded =
|
1306
|
+
decoded = CGI.unescape(value)
|
1297
1307
|
decoded.downcase! if downcase
|
1298
|
-
URI.encode(decoded, /[^(?:#{expr})]/)
|
1308
|
+
URI.encode(decoded, /[^(?:#{expr})]/).force_encoding(Encoding::UTF_8)
|
1299
1309
|
end
|
1300
1310
|
end
|
1301
1311
|
|
data/lib/rdf/ntriples/reader.rb
CHANGED
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.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
@@ -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
|
+
[: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
|
data/lib/rdf/query/variable.rb
CHANGED
@@ -65,7 +65,7 @@ class RDF::Query
|
|
65
65
|
# the variable name
|
66
66
|
# @param [RDF::Term] value
|
67
67
|
# an optional variable value
|
68
|
-
# @param [Boolean] distinguished (true) Also interpreted by leading '
|
68
|
+
# @param [Boolean] distinguished (true) Also interpreted by leading '?' or '$' in name. If non-distinguished, '??' or '$$'.
|
69
69
|
# @param [Boolean] existential (true) Also interpreted by leading '$' in name
|
70
70
|
def initialize(name = nil, value = nil, distinguished: nil, existential: nil)
|
71
71
|
name = (name || "g#{__id__.to_i.abs}").to_s
|
@@ -246,6 +246,16 @@ class RDF::Query
|
|
246
246
|
end
|
247
247
|
end
|
248
248
|
|
249
|
+
##
|
250
|
+
# Returns term if var is the same as this variable.
|
251
|
+
#
|
252
|
+
# @param [Symbol] var
|
253
|
+
# @param [RDF::Term] term
|
254
|
+
# @return [RDF::Term]
|
255
|
+
def var_values(var, term)
|
256
|
+
term if var == name
|
257
|
+
end
|
258
|
+
|
249
259
|
##
|
250
260
|
# Returns a string representation of this variable.
|
251
261
|
#
|
@@ -265,5 +275,6 @@ class RDF::Query
|
|
265
275
|
prefix = distinguished? ? (existential? ? '$' : '?') : (existential? ? '$$' : '??')
|
266
276
|
unbound? ? "#{prefix}#{name}" : "#{prefix}#{name}=#{value}"
|
267
277
|
end
|
278
|
+
alias_method :to_base, :to_s
|
268
279
|
end # Variable
|
269
280
|
end # RDF::Query
|
data/lib/rdf/repository.rb
CHANGED
@@ -410,12 +410,12 @@ module RDF
|
|
410
410
|
end
|
411
411
|
ss.each do |s, ps|
|
412
412
|
ps = if predicate.nil? || predicate.is_a?(RDF::Query::Variable)
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
413
|
+
ps
|
414
|
+
elsif ps.has_key?(predicate)
|
415
|
+
{ predicate => ps[predicate] }
|
416
|
+
else
|
417
|
+
[]
|
418
|
+
end
|
419
419
|
ps.each do |p, os|
|
420
420
|
os.each do |o, object_options|
|
421
421
|
next unless object.nil? || object.eql?(o)
|
data/lib/rdf/util/file.rb
CHANGED
@@ -14,7 +14,7 @@ module RDF; module Util
|
|
14
14
|
# allowing the use of `Rack::Cache` to avoid network access.
|
15
15
|
#
|
16
16
|
# To use other HTTP clients, consumers can subclass
|
17
|
-
# {RDF::Util::File::HttpAdapter} and set the {RDF::Util::File.
|
17
|
+
# {RDF::Util::File::HttpAdapter} and set the {RDF::Util::File.}.
|
18
18
|
#
|
19
19
|
# Also supports the file: scheme for access to local files.
|
20
20
|
#
|
@@ -121,8 +121,8 @@ module RDF; module Util
|
|
121
121
|
|
122
122
|
redirect_count = 0
|
123
123
|
max_redirects = 5
|
124
|
-
parsed_url = ::URI.parse(base_uri)
|
125
|
-
parsed_proxy = ::URI.parse(proxy.to_s)
|
124
|
+
parsed_url = RDF::URI.parse(base_uri)
|
125
|
+
parsed_proxy = RDF::URI.parse(proxy.to_s)
|
126
126
|
base_uri = parsed_url.to_s
|
127
127
|
remote_document = nil
|
128
128
|
|
data/lib/rdf/util/logger.rb
CHANGED
@@ -219,9 +219,9 @@ module RDF; module Util
|
|
219
219
|
# @return [void]
|
220
220
|
def logger_common(*args, level:, **options)
|
221
221
|
logger = self.logger(**options)
|
222
|
-
logger.log_statistics[level] = logger.log_statistics[level].to_i + 1
|
223
222
|
# Some older code uses integer level numbers
|
224
223
|
level = LOGGER_COMMON_LEVELS_REVERSE.fetch(level) if level.is_a?(Integer)
|
224
|
+
logger.log_statistics[level] = logger.log_statistics[level].to_i + 1
|
225
225
|
return if logger.level > LOGGER_COMMON_LEVELS.fetch(level)
|
226
226
|
|
227
227
|
depth = options.fetch(:depth, logger.log_depth)
|
data/lib/rdf/vocab/writer.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'rdf'
|
2
2
|
require 'rdf/vocabulary'
|
3
|
+
require 'cgi'
|
3
4
|
|
4
5
|
module RDF
|
5
6
|
##
|
@@ -84,7 +85,7 @@ module RDF
|
|
84
85
|
on: ["--extra URIEncodedJSON"],
|
85
86
|
description: "URI Encoded JSON representation of extra data"
|
86
87
|
) do |arg|
|
87
|
-
::JSON.parse(::
|
88
|
+
::JSON.parse(::CGI.unescape(arg)).inject({}) do |m1, (term, defs)|
|
88
89
|
d1 = defs.inject({}) {|m, (k,v)| m.merge(k.to_sym => v)}
|
89
90
|
m1.merge(term.to_sym => d1)
|
90
91
|
end
|
@@ -262,7 +263,7 @@ module RDF
|
|
262
263
|
|
263
264
|
def serialize_value(value, key, indent: "")
|
264
265
|
if value.is_a?(Literal) && %w(: comment definition notation note editorialNote).include?(key.to_s)
|
265
|
-
"
|
266
|
+
"#{value.to_s.inspect}.freeze"
|
266
267
|
elsif value.is_a?(RDF::URI)
|
267
268
|
"#{value.pname.inspect}.freeze"
|
268
269
|
elsif value.is_a?(RDF::Vocabulary::Term)
|
data/lib/rdf/vocabulary.rb
CHANGED
@@ -85,10 +85,15 @@ module RDF
|
|
85
85
|
end
|
86
86
|
|
87
87
|
##
|
88
|
-
# A hash of all vocabularies by prefix showing relevant URI and
|
88
|
+
# A hash of all vocabularies by prefix showing relevant URI and
|
89
|
+
# associated vocabulary Class Name
|
90
|
+
#
|
89
91
|
# @return [Hash{Symbol => Hash{Symbol => String}}]
|
90
92
|
def vocab_map
|
91
|
-
VOCABS
|
93
|
+
# Create an initial duplicate of RDF::VOCABS. We want to
|
94
|
+
# ensure the hash itself is modifiable but the values are
|
95
|
+
# frozen.
|
96
|
+
@vocab_map ||= RDF::VOCABS.transform_values(&:freeze)
|
92
97
|
end
|
93
98
|
|
94
99
|
##
|
@@ -100,6 +105,36 @@ module RDF
|
|
100
105
|
RDF.const_get(sym.to_sym)
|
101
106
|
end
|
102
107
|
|
108
|
+
##
|
109
|
+
# Register a vocabulary for internal prefix lookups. Parameters
|
110
|
+
# of interest include `:uri`, `:class_name`, `:source`, and `:skip`.
|
111
|
+
#
|
112
|
+
# @param prefix [Symbol] the prefix to use
|
113
|
+
# @param vocab [String, Class] either the URI or the vocab class
|
114
|
+
# @param params [Hash{Symbol => String}] Relevant parameters
|
115
|
+
# @return [Hash] The parameter hash, but frozen
|
116
|
+
def register(prefix, vocab, **params)
|
117
|
+
# check the input
|
118
|
+
raise ArgumentError, "#{prefix} must be symbol-able" unless
|
119
|
+
[String, Symbol].any? { |c| prefix.is_a? c }
|
120
|
+
|
121
|
+
# note an explicit uri: param overrides
|
122
|
+
case vocab
|
123
|
+
when String then params[:uri] ||= vocab
|
124
|
+
when Class
|
125
|
+
raise ArgumentError, 'vocab must be an RDF::(Strict)Vocabulary' unless
|
126
|
+
vocab.ancestors.include? RDF::Vocabulary
|
127
|
+
params[:class] = vocab
|
128
|
+
params[:uri] ||= vocab.to_uri.to_s
|
129
|
+
end
|
130
|
+
|
131
|
+
# fill in the class name
|
132
|
+
params[:class_name] ||= prefix.to_s.upcase
|
133
|
+
|
134
|
+
# now freeze and assign
|
135
|
+
vocab_map[prefix.to_s.to_sym] = params.freeze
|
136
|
+
end
|
137
|
+
|
103
138
|
##
|
104
139
|
# Limits iteration over vocabularies to just those selected
|
105
140
|
#
|
@@ -347,7 +382,8 @@ module RDF
|
|
347
382
|
if prefix == "rdf"
|
348
383
|
RDF[suffix]
|
349
384
|
elsif vocab_detail = RDF::Vocabulary.vocab_map[prefix.to_sym]
|
350
|
-
vocab =
|
385
|
+
vocab = vocab_detail[:class] ||
|
386
|
+
RDF::Vocabulary.from_sym(vocab_detail[:class_name])
|
351
387
|
suffix.to_s.empty? ? vocab.to_uri : vocab[suffix]
|
352
388
|
else
|
353
389
|
(RDF::Vocabulary.find_term(pname) rescue nil) || RDF::URI(pname, validate: true)
|
@@ -695,7 +731,7 @@ module RDF
|
|
695
731
|
# @param [#to_s] property
|
696
732
|
# @return [URI]
|
697
733
|
def [](property)
|
698
|
-
Term.intern([to_s, property.to_s].join(''), vocab: self
|
734
|
+
Term.intern([to_s, property.to_s].join(''), vocab: self, attributes: {})
|
699
735
|
end
|
700
736
|
|
701
737
|
##
|
metadata
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rdf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.1.
|
4
|
+
version: 3.1.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Arto Bendiken
|
8
8
|
- Ben Lavender
|
9
9
|
- Gregg Kellogg
|
10
|
-
autorequire:
|
10
|
+
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2020-
|
13
|
+
date: 2020-11-15 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: link_header
|
@@ -288,7 +288,7 @@ metadata:
|
|
288
288
|
homepage_uri: https://ruby-rdf.github.io/rdf
|
289
289
|
mailing_list_uri: https://lists.w3.org/Archives/Public/public-rdf-ruby/
|
290
290
|
source_code_uri: https://github.com/ruby-rdf/rdf
|
291
|
-
post_install_message:
|
291
|
+
post_install_message:
|
292
292
|
rdoc_options: []
|
293
293
|
require_paths:
|
294
294
|
- lib
|
@@ -303,8 +303,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
303
303
|
- !ruby/object:Gem::Version
|
304
304
|
version: '0'
|
305
305
|
requirements: []
|
306
|
-
rubygems_version: 3.1.
|
307
|
-
signing_key:
|
306
|
+
rubygems_version: 3.1.4
|
307
|
+
signing_key:
|
308
308
|
specification_version: 4
|
309
309
|
summary: A Ruby library for working with Resource Description Framework (RDF) data.
|
310
310
|
test_files: []
|