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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 39ba8235c527933f06e9685428f3948547e46563c68ca5d0e1f3ac22f12b3d60
4
- data.tar.gz: 00fb02e10e11e2e011c58766c609ca186dc1e2c74ef44f09af704297681e94b8
3
+ metadata.gz: 7e220d98b1d53ade20bf5999761a948e495597dc74eaccd6830c22adadc77fa4
4
+ data.tar.gz: 13b643963aeb32f99e2c455490e3cbc661c56153abb6dd38ff192e42ce0ee5f5
5
5
  SHA512:
6
- metadata.gz: 46e0b83df6bf5fbdecdee12cc9bb2e34f93dce625a1a86edbd3251366a6ac6ef09fa4a1520c883c0f7a0a5d2bdb492e97fddeed739b4db28e6e69e278cc78e33
7
- data.tar.gz: db8b82296da844a5b8c0ab8547038cdd4f96e41231db41f2f8f0abd2d04859918a90adee3ded6369c9a37f20c192e16cc9d656910661533bb3bbbf5fb46a6aa5
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://lists.w3.org/Archives/Public/public-rdf-ruby/2010May/0013.html
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.2
1
+ 3.1.7
data/bin/rdf CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
- $:.unshift(File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib')))
2
+ $:.unshift(File.expand_path("../../lib", __FILE__))
3
3
  require 'rubygems'
4
- require 'rdf/cli'
4
+ require 'rdf'
5
5
 
6
6
  options = RDF::CLI.options(ARGV)
7
7
 
data/lib/rdf.rb CHANGED
@@ -76,6 +76,9 @@ module RDF
76
76
  # Utilities
77
77
  autoload :Util, 'rdf/util'
78
78
 
79
+ # CLI
80
+ autoload :CLI, 'rdf/cli'
81
+
79
82
  ##
80
83
  # Alias for `RDF::Resource.new`.
81
84
  #
@@ -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
@@ -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(reasoner rdfa rdfxml turtle vocab json/ld ld/patch).each do |ser|
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 = RDF::Repository.new
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 << reader
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."
@@ -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(nil, nil (1, 2, 3))
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
- RDF::List[*(to_a & other.to_a)]
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
- RDF::List[*(to_a | other.to_a)]
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
- RDF::List[*(to_a + other.to_a)]
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
- RDF::List[*(to_a - other.to_a)]
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 RDF::List[*(to_a * int_or_str)]
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
- RDF::List[*to_a.slice(start, length)]
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
- RDF::List[*to_a.slice(range)]
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
- RDF::List[*to_a.reverse]
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
- RDF::List[*super]
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
- RDF::List[*super]
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
- RDF::List[*to_a.uniq]
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 RDF::List.new(subject: nil, graph: graph, values: value)
967
+ when Array then self.class.new(subject: nil, graph: graph, values: value)
968
968
  else value
969
969
  end
970
970
  end
@@ -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
- self.class.new(to_d.round)
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
- self.class.new(to_d.ceil)
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
- self.class.new(to_d.floor)
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 number greater than or equal to `self`.
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
- self.class.new(to_f.ceil)
156
+ RDF::Literal::Integer.new(to_f.ceil)
157
157
  end
158
158
 
159
159
  ##
160
- # Returns the largest number less than or equal to `self`.
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
- self.class.new(to_f.floor)
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(to_f.round)
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
  #
@@ -1,5 +1,5 @@
1
1
  # coding: utf-8
2
- require 'uri'
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.end_with?("/", "#") &&
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
- self
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] = (URI.decode(port).to_i if 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(URI.decode(user), /[^#{IUNRESERVED}|#{SUB_DELIMS}]/) if user
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(URI.decode(password), /[^#{IUNRESERVED}|#{SUB_DELIMS}]/) if password
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 = URI.decode(k)
1184
- v = URI.decode(v) if 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 = URI.decode(value)
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
 
@@ -1,4 +1,7 @@
1
1
  # -*- encoding: utf-8 -*-
2
+
3
+ require 'strscan'
4
+
2
5
  module RDF::NTriples
3
6
  ##
4
7
  # N-Triples parser.
@@ -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.sort! do |a, b|
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
 
@@ -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
- # Figure out which terms refer to the same variable:
185
- terms = variables.each_key.find do |name|
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
- # Only yield those matching statements where the variable
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.is_a?(Pattern)
224
- solution.merge!(object.solution(statement.object)) if object.is_a?(Pattern)
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.is_a?(Pattern) ? term.variable_count : 0))
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.is_a?(Variable)
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.is_a?(Variable)
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
- StringIO.open do |buffer| # FIXME in RDF::Statement
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
@@ -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 '??' or '$$' in name.
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
@@ -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
- ps
414
- elsif ps.has_key?(predicate)
415
- { predicate => ps[predicate] }
416
- else
417
- []
418
- end
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)
@@ -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.http_adapter}.
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
 
@@ -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)
@@ -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(::URI.decode(arg)).inject({}) do |m1, (term, defs)|
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
- "%(#{value.to_s.gsub('(', '\(').gsub(')', '\)')}).freeze"
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)
@@ -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 associated vocabulary Class Name
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 = RDF::Vocabulary.from_sym(vocab_detail[:class_name])
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.class, attributes: {})
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.2
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-05-30 00:00:00.000000000 Z
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.3
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: []