sparql-client 3.0.1 → 3.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -12,12 +12,12 @@ class SPARQL::Client
12
12
  # insert_data(data)
13
13
  #
14
14
  # @example INSERT DATA \{ GRAPH <http://example.org/> \{\}\}
15
- # insert_data(RDF::Graph.new, :graph => 'http://example.org/')
15
+ # insert_data(RDF::Graph.new, graph: 'http://example.org/')
16
16
  # insert_data(RDF::Graph.new).graph('http://example.org/')
17
17
  #
18
18
  # @param (see InsertData#initialize)
19
- def self.insert_data(*arguments)
20
- InsertData.new(*arguments)
19
+ def self.insert_data(*arguments, **options)
20
+ InsertData.new(*arguments, **options)
21
21
  end
22
22
 
23
23
  ##
@@ -30,12 +30,12 @@ class SPARQL::Client
30
30
  # delete_data(data)
31
31
  #
32
32
  # @example DELETE DATA \{ GRAPH <http://example.org/> \{\}\}
33
- # delete_data(RDF::Graph.new, :graph => 'http://example.org/')
33
+ # delete_data(RDF::Graph.new, graph: 'http://example.org/')
34
34
  # delete_data(RDF::Graph.new).graph('http://example.org/')
35
35
  #
36
36
  # @param (see DeleteData#initialize)
37
- def self.delete_data(*arguments)
38
- DeleteData.new(*arguments)
37
+ def self.delete_data(*arguments, **options)
38
+ DeleteData.new(*arguments, **options)
39
39
  end
40
40
 
41
41
  ##
@@ -53,8 +53,8 @@ class SPARQL::Client
53
53
  # load(RDF::URI(http://example.org/data.rdf), into: RDF::URI(http://example.org/data.rdf))
54
54
  #
55
55
  # @param (see Load#initialize)
56
- def self.load(*arguments)
57
- Load.new(*arguments)
56
+ def self.load(*arguments, **options)
57
+ Load.new(*arguments, **options)
58
58
  end
59
59
 
60
60
  ##
@@ -81,8 +81,8 @@ class SPARQL::Client
81
81
  # clear(:all, silent: true)
82
82
  #
83
83
  # @param (see Clear#initialize)
84
- def self.clear(*arguments)
85
- Clear.new(*arguments)
84
+ def self.clear(*arguments, **options)
85
+ Clear.new(*arguments, **options)
86
86
  end
87
87
 
88
88
  ##
@@ -96,8 +96,8 @@ class SPARQL::Client
96
96
  # create(RDF::URI(http://example.org/data.rdf), silent: true)
97
97
  #
98
98
  # @param (see Create#initialize)
99
- def self.create(*arguments)
100
- Create.new(*arguments)
99
+ def self.create(*arguments, **options)
100
+ Create.new(*arguments, **options)
101
101
  end
102
102
 
103
103
  ##
@@ -124,15 +124,15 @@ class SPARQL::Client
124
124
  # drop(:all, silent: true)
125
125
  #
126
126
  # @param (see Drop#initialize)
127
- def self.drop(*arguments)
128
- Drop.new(*arguments)
127
+ def self.drop(*arguments, **options)
128
+ Drop.new(*arguments, **options)
129
129
  end
130
130
 
131
131
  class Operation
132
132
  attr_reader :options
133
133
 
134
- def initialize(*arguments)
135
- @options = arguments.last.is_a?(Hash) ? arguments.pop.dup : {}
134
+ def initialize(*arguments, **options)
135
+ @options = options.dup
136
136
  unless arguments.empty?
137
137
  send(arguments.shift, *arguments)
138
138
  end
@@ -155,7 +155,7 @@ class SPARQL::Client
155
155
  end
156
156
 
157
157
  ##
158
- # @see http://www.w3.org/TR/sparql11-update/#insertData
158
+ # @see https://www.w3.org/TR/sparql11-update/#insertData
159
159
  class InsertData < Operation
160
160
  # @return [RDF::Enumerable]
161
161
  attr_reader :data
@@ -171,9 +171,9 @@ class SPARQL::Client
171
171
  #
172
172
  # @param [Array<RDF::Statement>, RDF::Enumerable] data
173
173
  # @param [Hash{Symbol => Object}] options
174
- def initialize(data, options = {})
174
+ def initialize(data, **options)
175
175
  @data = data
176
- super(options)
176
+ super(**options)
177
177
  end
178
178
 
179
179
  ##
@@ -205,7 +205,7 @@ class SPARQL::Client
205
205
  end
206
206
 
207
207
  ##
208
- # @see http://www.w3.org/TR/sparql11-update/#deleteData
208
+ # @see https://www.w3.org/TR/sparql11-update/#deleteData
209
209
  class DeleteData < Operation
210
210
  # @return [RDF::Enumerable]
211
211
  attr_reader :data
@@ -221,9 +221,9 @@ class SPARQL::Client
221
221
  #
222
222
  # @param [Array<RDF::Statement>, RDF::Enumerable] data
223
223
  # @param [Hash{Symbol => Object}] options
224
- def initialize(data, options = {})
224
+ def initialize(data, **options)
225
225
  @data = data
226
- super(options)
226
+ super(**options)
227
227
  end
228
228
 
229
229
  ##
@@ -247,17 +247,17 @@ class SPARQL::Client
247
247
  end
248
248
 
249
249
  ##
250
- # @see http://www.w3.org/TR/sparql11-update/#deleteInsert
250
+ # @see https://www.w3.org/TR/sparql11-update/#deleteInsert
251
251
  class DeleteInsert < Operation
252
252
  attr_reader :insert_graph
253
253
  attr_reader :delete_graph
254
254
  attr_reader :where_graph
255
255
 
256
- def initialize(_delete_graph, _insert_graph = nil, _where_graph = nil, options = {})
256
+ def initialize(_delete_graph, _insert_graph = nil, _where_graph = nil, **options)
257
257
  @delete_graph = _delete_graph
258
258
  @insert_graph = _insert_graph
259
259
  @where_graph = _where_graph
260
- super(options)
260
+ super(**options)
261
261
  end
262
262
 
263
263
  ##
@@ -301,7 +301,7 @@ class SPARQL::Client
301
301
  end
302
302
 
303
303
  ##
304
- # @see http://www.w3.org/TR/sparql11-update/#load
304
+ # @see https://www.w3.org/TR/sparql11-update/#load
305
305
  class Load < Operation
306
306
  attr_reader :from
307
307
  attr_reader :into
@@ -324,11 +324,10 @@ class SPARQL::Client
324
324
  # @param [Hash{Symbol => Object}] options
325
325
  # @option [RDF::URI] :into
326
326
  # @option [Boolean] :silent
327
- def initialize(from, options = {})
328
- options = options.dup
327
+ def initialize(from, into: nil,**options)
329
328
  @from = RDF::URI(from)
330
- @into = RDF::URI(options.delete(:into)) if options[:into]
331
- super(options)
329
+ @into = RDF::URI(into) if into
330
+ super(**options)
332
331
  end
333
332
 
334
333
  ##
@@ -351,7 +350,7 @@ class SPARQL::Client
351
350
  end
352
351
 
353
352
  ##
354
- # @see http://www.w3.org/TR/sparql11-update/#clear
353
+ # @see https://www.w3.org/TR/sparql11-update/#clear
355
354
  class Clear < Operation
356
355
  attr_reader :uri
357
356
 
@@ -415,14 +414,14 @@ class SPARQL::Client
415
414
  end
416
415
 
417
416
  ##
418
- # @see http://www.w3.org/TR/sparql11-update/#create
417
+ # @see https://www.w3.org/TR/sparql11-update/#create
419
418
  class Create < Operation
420
419
  attr_reader :uri
421
420
 
422
421
  # @param [Hash{Symbol => Object}] options
423
- def initialize(uri, options = {})
422
+ def initialize(uri, **options)
424
423
  @uri = RDF::URI(uri)
425
- super(options)
424
+ super(**options)
426
425
  end
427
426
 
428
427
  def to_s
@@ -434,7 +433,7 @@ class SPARQL::Client
434
433
  end
435
434
 
436
435
  ##
437
- # @see http://www.w3.org/TR/sparql11-update/#drop
436
+ # @see https://www.w3.org/TR/sparql11-update/#drop
438
437
  class Drop < Clear
439
438
  def to_s
440
439
  query_text = 'DROP '
@@ -451,7 +450,7 @@ class SPARQL::Client
451
450
  end
452
451
 
453
452
  ##
454
- # @see http://www.w3.org/TR/sparql11-update/#copy
453
+ # @see https://www.w3.org/TR/sparql11-update/#copy
455
454
  class Copy < Operation
456
455
  def to_s
457
456
  # TODO
@@ -459,7 +458,7 @@ class SPARQL::Client
459
458
  end
460
459
 
461
460
  ##
462
- # @see http://www.w3.org/TR/sparql11-update/#move
461
+ # @see https://www.w3.org/TR/sparql11-update/#move
463
462
  class Move < Operation
464
463
  def to_s
465
464
  # TODO
@@ -467,7 +466,7 @@ class SPARQL::Client
467
466
  end
468
467
 
469
468
  ##
470
- # @see http://www.w3.org/TR/sparql11-update/#add
469
+ # @see https://www.w3.org/TR/sparql11-update/#add
471
470
  class Add < Operation
472
471
  def to_s
473
472
  # TODO
data/lib/sparql/client.rb CHANGED
@@ -1,6 +1,6 @@
1
- require 'net/http/persistent' # @see http://rubygems.org/gems/net-http-persistent
2
- require 'rdf' # @see http://rubygems.org/gems/rdf
3
- require 'rdf/ntriples' # @see http://rubygems.org/gems/rdf
1
+ require 'net/http/persistent' # @see https://rubygems.org/gems/net-http-persistent
2
+ require 'rdf' # @see https://rubygems.org/gems/rdf
3
+ require 'rdf/ntriples' # @see https://rubygems.org/gems/rdf
4
4
  begin
5
5
  require 'nokogiri'
6
6
  rescue LoadError
@@ -11,10 +11,10 @@ module SPARQL
11
11
  ##
12
12
  # A SPARQL 1.0/1.1 client for RDF.rb.
13
13
  #
14
- # @see http://www.w3.org/TR/sparql11-query/
15
- # @see http://www.w3.org/TR/sparql11-protocol/
16
- # @see http://www.w3.org/TR/sparql11-results-json/
17
- # @see http://www.w3.org/TR/sparql11-results-csv-tsv/
14
+ # @see https://www.w3.org/TR/sparql11-query/
15
+ # @see https://www.w3.org/TR/sparql11-protocol/
16
+ # @see https://www.w3.org/TR/sparql11-results-json/
17
+ # @see https://www.w3.org/TR/sparql11-results-csv-tsv/
18
18
  class Client
19
19
  autoload :Query, 'sparql/client/query'
20
20
  autoload :Repository, 'sparql/client/repository'
@@ -86,8 +86,13 @@ module SPARQL
86
86
  # @option options [Symbol] :method (DEFAULT_METHOD)
87
87
  # @option options [Number] :protocol (DEFAULT_PROTOCOL)
88
88
  # @option options [Hash] :headers
89
+ # HTTP Request headers
90
+ #
91
+ # Defaults `Accept` header based on available reader content types if triples are expected and to SPARQL result types otherwise, to allow for content negotiation based on available readers.
92
+ #
93
+ # Defaults `User-Agent` header, unless one is specified.
89
94
  # @option options [Hash] :read_timeout
90
- def initialize(url, options = {}, &block)
95
+ def initialize(url, **options, &block)
91
96
  case url
92
97
  when RDF::Queryable
93
98
  @url, @options = url, options.dup
@@ -95,6 +100,9 @@ module SPARQL
95
100
  @url, @options = RDF::URI.new(url.to_s), options.dup
96
101
  @headers = @options.delete(:headers) || {}
97
102
  @http = http_klass(@url.scheme)
103
+
104
+ # Close the http connection when object is deallocated
105
+ ObjectSpace.define_finalizer(self, self.class.finalize(@http))
98
106
  end
99
107
 
100
108
  if block_given?
@@ -105,13 +113,30 @@ module SPARQL
105
113
  end
106
114
  end
107
115
 
116
+ # Close the http connection when object is deallocated
117
+ def self.finalize(klass)
118
+ proc do
119
+ klass.shutdown if klass.respond_to?(:shutdown)
120
+ end
121
+ end
122
+
123
+ ##
124
+ # Closes a client instance by finishing the connection.
125
+ # The client is unavailable for any further data operations; an IOError is raised if such an attempt is made. I/O streams are automatically closed when they are claimed by the garbage collector.
126
+ # @return [void] `self`
127
+ def close
128
+ @http.shutdown if @http
129
+ @http = nil
130
+ self
131
+ end
132
+
108
133
  ##
109
134
  # Executes a boolean `ASK` query.
110
135
  #
111
136
  # @param (see Query.ask)
112
137
  # @return [Query]
113
- def ask(*args)
114
- call_query_method(:ask, *args)
138
+ def ask(*args, **options)
139
+ call_query_method(:ask, *args, **options)
115
140
  end
116
141
 
117
142
  ##
@@ -119,8 +144,8 @@ module SPARQL
119
144
  #
120
145
  # @param (see Query.select)
121
146
  # @return [Query]
122
- def select(*args)
123
- call_query_method(:select, *args)
147
+ def select(*args, **options)
148
+ call_query_method(:select, *args, **options)
124
149
  end
125
150
 
126
151
  ##
@@ -128,8 +153,8 @@ module SPARQL
128
153
  #
129
154
  # @param (see Query.describe)
130
155
  # @return [Query]
131
- def describe(*args)
132
- call_query_method(:describe, *args)
156
+ def describe(*args, **options)
157
+ call_query_method(:describe, *args, **options)
133
158
  end
134
159
 
135
160
  ##
@@ -137,8 +162,8 @@ module SPARQL
137
162
  #
138
163
  # @param (see Query.construct)
139
164
  # @return [Query]
140
- def construct(*args)
141
- call_query_method(:construct, *args)
165
+ def construct(*args, **options)
166
+ call_query_method(:construct, *args, **options)
142
167
  end
143
168
 
144
169
  ##
@@ -161,15 +186,15 @@ module SPARQL
161
186
  # client.insert_data(data)
162
187
  #
163
188
  # @example Inserting data into a named graph
164
- # client.insert_data(data, :graph => "http://example.org/")
189
+ # client.insert_data(data, graph: "http://example.org/")
165
190
  #
166
191
  # @param [RDF::Enumerable] data
167
192
  # @param [Hash{Symbol => Object}] options
168
193
  # @option options [RDF::URI, String] :graph
169
194
  # @return [void] `self`
170
- # @see http://www.w3.org/TR/sparql11-update/#insertData
171
- def insert_data(data, options = {})
172
- self.update(Update::InsertData.new(data, options))
195
+ # @see https://www.w3.org/TR/sparql11-update/#insertData
196
+ def insert_data(data, **options)
197
+ self.update(Update::InsertData.new(data, **options))
173
198
  end
174
199
 
175
200
  ##
@@ -182,15 +207,15 @@ module SPARQL
182
207
  # client.delete_data(data)
183
208
  #
184
209
  # @example Deleting data from a named graph
185
- # client.delete_data(data, :graph => "http://example.org/")
210
+ # client.delete_data(data, graph: "http://example.org/")
186
211
  #
187
212
  # @param [RDF::Enumerable] data
188
213
  # @param [Hash{Symbol => Object}] options
189
214
  # @option options [RDF::URI, String] :graph
190
215
  # @return [void] `self`
191
- # @see http://www.w3.org/TR/sparql11-update/#deleteData
192
- def delete_data(data, options = {})
193
- self.update(Update::DeleteData.new(data, options))
216
+ # @see https://www.w3.org/TR/sparql11-update/#deleteData
217
+ def delete_data(data, **options)
218
+ self.update(Update::DeleteData.new(data, **options))
194
219
  end
195
220
 
196
221
  ##
@@ -204,9 +229,9 @@ module SPARQL
204
229
  # @param [Hash{Symbol => Object}] options
205
230
  # @option options [RDF::URI, String] :graph
206
231
  # @return [void] `self`
207
- # @see http://www.w3.org/TR/sparql11-update/#deleteInsert
208
- def delete_insert(delete_graph, insert_graph = nil, where_graph = nil, options = {})
209
- self.update(Update::DeleteInsert.new(delete_graph, insert_graph, where_graph, options))
232
+ # @see https://www.w3.org/TR/sparql11-update/#deleteInsert
233
+ def delete_insert(delete_graph, insert_graph = nil, where_graph = nil, **options)
234
+ self.update(Update::DeleteInsert.new(delete_graph, insert_graph, where_graph, **options))
210
235
  end
211
236
 
212
237
  ##
@@ -221,9 +246,9 @@ module SPARQL
221
246
  # @param [Hash{Symbol => Object}] options
222
247
  # @option options [Boolean] :silent
223
248
  # @return [void] `self`
224
- # @see http://www.w3.org/TR/sparql11-update/#clear
225
- def clear_graph(graph_uri, options = {})
226
- self.clear(:graph, graph_uri, options)
249
+ # @see https://www.w3.org/TR/sparql11-update/#clear
250
+ def clear_graph(graph_uri, **options)
251
+ self.clear(:graph, graph_uri, **options)
227
252
  end
228
253
 
229
254
  ##
@@ -249,23 +274,23 @@ module SPARQL
249
274
  # @option options [Boolean] :silent
250
275
  # @return [void] `self`
251
276
  #
252
- # @overload clear(what, *arguments, options = {})
277
+ # @overload clear(what, *arguments, **options)
253
278
  # @param [Symbol, #to_sym] what
254
279
  # @param [Array] arguments splat of other arguments to {Update::Clear}.
255
280
  # @param [Hash{Symbol => Object}] options
256
281
  # @option options [Boolean] :silent
257
282
  # @return [void] `self`
258
283
  #
259
- # @see http://www.w3.org/TR/sparql11-update/#clear
284
+ # @see https://www.w3.org/TR/sparql11-update/#clear
260
285
  def clear(what, *arguments)
261
286
  self.update(Update::Clear.new(what, *arguments))
262
287
  end
263
288
 
264
289
  ##
265
290
  # @private
266
- def call_query_method(meth, *args)
291
+ def call_query_method(meth, *args, **options)
267
292
  client = self
268
- result = Query.send(meth, *args)
293
+ result = Query.send(meth, *args, **options)
269
294
  (class << result; self; end).send(:define_method, :execute) do
270
295
  client.query(self)
271
296
  end
@@ -288,21 +313,22 @@ module SPARQL
288
313
  # @option options [String] :content_type
289
314
  # @option options [Hash] :headers
290
315
  # @return [Array<RDF::Query::Solution>]
291
- # @see http://www.w3.org/TR/sparql11-protocol/#query-operation
292
- def query(query, options = {})
316
+ # @raise [IOError] if connection is closed
317
+ # @see https://www.w3.org/TR/sparql11-protocol/#query-operation
318
+ def query(query, **options)
293
319
  @op = :query
294
320
  @alt_endpoint = options[:endpoint]
295
321
  case @url
296
322
  when RDF::Queryable
297
323
  require 'sparql' unless defined?(::SPARQL::Grammar)
298
324
  begin
299
- SPARQL.execute(query, @url, options)
325
+ SPARQL.execute(query, @url, optimize: true, **options)
300
326
  rescue SPARQL::MalformedQuery
301
327
  $stderr.puts "error running #{query}: #{$!}"
302
328
  raise
303
329
  end
304
330
  else
305
- parse_response(response(query, options), options)
331
+ parse_response(response(query, **options), **options)
306
332
  end
307
333
  end
308
334
 
@@ -315,16 +341,17 @@ module SPARQL
315
341
  # @option options [String] :content_type
316
342
  # @option options [Hash] :headers
317
343
  # @return [void] `self`
318
- # @see http://www.w3.org/TR/sparql11-protocol/#update-operation
319
- def update(query, options = {})
344
+ # @raise [IOError] if connection is closed
345
+ # @see https://www.w3.org/TR/sparql11-protocol/#update-operation
346
+ def update(query, **options)
320
347
  @op = :update
321
348
  @alt_endpoint = options[:endpoint]
322
349
  case @url
323
350
  when RDF::Queryable
324
351
  require 'sparql' unless defined?(::SPARQL::Grammar)
325
- SPARQL.execute(query, @url, options.merge(update: true))
352
+ SPARQL.execute(query, @url, update: true, optimize: true, **options)
326
353
  else
327
- response(query, options)
354
+ response(query, **options)
328
355
  end
329
356
  self
330
357
  end
@@ -338,8 +365,9 @@ module SPARQL
338
365
  # @option options [String] :content_type
339
366
  # @option options [Hash] :headers
340
367
  # @return [String]
341
- def response(query, options = {})
342
- headers = options[:headers] || {}
368
+ # @raise [IOError] if connection is closed
369
+ def response(query, **options)
370
+ headers = options[:headers] || @headers
343
371
  headers['Accept'] = options[:content_type] if options[:content_type]
344
372
  request(query, headers) do |response|
345
373
  case response
@@ -359,7 +387,7 @@ module SPARQL
359
387
  # @param [Net::HTTPSuccess] response
360
388
  # @param [Hash{Symbol => Object}] options
361
389
  # @return [Object]
362
- def parse_response(response, options = {})
390
+ def parse_response(response, **options)
363
391
  case options[:content_type] || response.content_type
364
392
  when NilClass
365
393
  response.body
@@ -374,14 +402,14 @@ module SPARQL
374
402
  when RESULT_TSV
375
403
  self.class.parse_tsv_bindings(response.body, nodes)
376
404
  else
377
- parse_rdf_serialization(response, options)
405
+ parse_rdf_serialization(response, **options)
378
406
  end
379
407
  end
380
408
 
381
409
  ##
382
410
  # @param [String, Hash] json
383
411
  # @return [<RDF::Query::Solutions>]
384
- # @see http://www.w3.org/TR/rdf-sparql-json-res/#results
412
+ # @see https://www.w3.org/TR/rdf-sparql-json-res/#results
385
413
  def self.parse_json_bindings(json, nodes = {})
386
414
  require 'json' unless defined?(::JSON)
387
415
  json = JSON.parse(json.to_s) unless json.is_a?(Hash)
@@ -402,8 +430,8 @@ module SPARQL
402
430
  ##
403
431
  # @param [Hash{String => String}] value
404
432
  # @return [RDF::Value]
405
- # @see http://www.w3.org/TR/sparql11-results-json/#select-encode-terms
406
- # @see http://www.w3.org/TR/rdf-sparql-json-res/#variable-binding-results
433
+ # @see https://www.w3.org/TR/sparql11-results-json/#select-encode-terms
434
+ # @see https://www.w3.org/TR/rdf-sparql-json-res/#variable-binding-results
407
435
  def self.parse_json_value(value, nodes = {})
408
436
  case value['type'].to_sym
409
437
  when :bnode
@@ -411,9 +439,14 @@ module SPARQL
411
439
  when :uri
412
440
  RDF::URI.new(value['value'])
413
441
  when :literal
414
- RDF::Literal.new(value['value'], :datatype => value['datatype'], :language => value['xml:lang'])
442
+ RDF::Literal.new(value['value'], datatype: value['datatype'], language: value['xml:lang'])
415
443
  when :'typed-literal'
416
- RDF::Literal.new(value['value'], :datatype => value['datatype'])
444
+ RDF::Literal.new(value['value'], datatype: value['datatype'])
445
+ when :triple
446
+ s = parse_json_value(value['value']['subject'], nodes)
447
+ p = parse_json_value(value['value']['predicate'], nodes)
448
+ o = parse_json_value(value['value']['object'], nodes)
449
+ RDF::Statement(s, p, o)
417
450
  else nil
418
451
  end
419
452
  end
@@ -421,7 +454,7 @@ module SPARQL
421
454
  ##
422
455
  # @param [String, Array<Array<String>>] csv
423
456
  # @return [<RDF::Query::Solutions>]
424
- # @see http://www.w3.org/TR/sparql11-results-csv-tsv/
457
+ # @see https://www.w3.org/TR/sparql11-results-csv-tsv/
425
458
  def self.parse_csv_bindings(csv, nodes = {})
426
459
  require 'csv' unless defined?(::CSV)
427
460
  csv = CSV.parse(csv.to_s) unless csv.is_a?(Array)
@@ -445,7 +478,7 @@ module SPARQL
445
478
  ##
446
479
  # @param [String, Array<Array<String>>] tsv
447
480
  # @return [<RDF::Query::Solutions>]
448
- # @see http://www.w3.org/TR/sparql11-results-csv-tsv/
481
+ # @see https://www.w3.org/TR/sparql11-results-csv-tsv/
449
482
  def self.parse_tsv_bindings(tsv, nodes = {})
450
483
  tsv = tsv.lines.map {|l| l.chomp.split("\t")} unless tsv.is_a?(Array)
451
484
  vars = tsv.shift.map {|h| h.sub(/^\?/, '')}
@@ -474,7 +507,7 @@ module SPARQL
474
507
  ##
475
508
  # @param [String, IO, Nokogiri::XML::Node, REXML::Element] xml
476
509
  # @return [<RDF::Query::Solutions>]
477
- # @see http://www.w3.org/TR/rdf-sparql-json-res/#results
510
+ # @see https://www.w3.org/TR/rdf-sparql-json-res/#results
478
511
  def self.parse_xml_bindings(xml, nodes = {})
479
512
  xml.force_encoding(::Encoding::UTF_8) if xml.respond_to?(:force_encoding)
480
513
 
@@ -519,7 +552,7 @@ module SPARQL
519
552
  ##
520
553
  # @param [Nokogiri::XML::Element, REXML::Element] value
521
554
  # @return [RDF::Value]
522
- # @see http://www.w3.org/TR/rdf-sparql-json-res/#variable-binding-results
555
+ # @see https://www.w3.org/TR/rdf-sparql-json-res/#variable-binding-results
523
556
  def self.parse_xml_value(value, nodes = {})
524
557
  case value.name.to_sym
525
558
  when :bnode
@@ -529,7 +562,12 @@ module SPARQL
529
562
  when :literal
530
563
  lang = value.respond_to?(:attr) ? value.attr('xml:lang') : value.attributes['xml:lang']
531
564
  datatype = value.respond_to?(:attr) ? value.attr('datatype') : value.attributes['datatype']
532
- RDF::Literal.new(value.text, :language => lang, :datatype => datatype)
565
+ RDF::Literal.new(value.text, language: lang, datatype: datatype)
566
+ when :triple
567
+ # Note, this is order dependent
568
+ res = value.elements.map {|e| e.elements.to_a}.
569
+ flatten.map {|e| parse_xml_value(e, nodes)}
570
+ RDF::Statement(*res)
533
571
  else nil
534
572
  end
535
573
  end
@@ -538,8 +576,8 @@ module SPARQL
538
576
  # @param [Net::HTTPSuccess] response
539
577
  # @param [Hash{Symbol => Object}] options
540
578
  # @return [RDF::Enumerable]
541
- def parse_rdf_serialization(response, options = {})
542
- options = {:content_type => response.content_type} unless options[:content_type]
579
+ def parse_rdf_serialization(response, **options)
580
+ options = {content_type: response.content_type} unless options[:content_type]
543
581
  if reader = RDF::Reader.for(options)
544
582
  reader.new(response.body)
545
583
  else
@@ -615,7 +653,7 @@ module SPARQL
615
653
  RDF::Statement.from(pattern).to_triple.each_with_index.map do |v, i|
616
654
  if i == 1
617
655
  SPARQL::Client.serialize_predicate(v)
618
- else
656
+ else
619
657
  SPARQL::Client.serialize_value(v, use_vars)
620
658
  end
621
659
  end
@@ -658,11 +696,7 @@ module SPARQL
658
696
  value = ENV['https_proxy']
659
697
  proxy_url = URI.parse(value) unless value.nil? || value.empty?
660
698
  end
661
- klass = if Net::HTTP::Persistent::VERSION >= '3.0'
662
- Net::HTTP::Persistent.new(name: self.class.to_s, proxy: proxy_url)
663
- else
664
- Net::HTTP::Persistent.new(self.class.to_s, proxy_url)
665
- end
699
+ klass = Net::HTTP::Persistent.new(name: self.class.to_s, proxy: proxy_url)
666
700
  klass.keep_alive = @options[:keep_alive] || 120
667
701
  klass.read_timeout = @options[:read_timeout] || 60
668
702
  klass
@@ -673,10 +707,16 @@ module SPARQL
673
707
  #
674
708
  # @param [String, #to_s] query
675
709
  # @param [Hash{String => String}] headers
710
+ # HTTP Request headers
711
+ #
712
+ # Defaults `Accept` header based on available reader content types if triples are expected and to SPARQL result types otherwise, to allow for content negotiation based on available readers.
713
+ #
714
+ # Defaults `User-Agent` header, unless one is specified.
676
715
  # @yield [response]
677
716
  # @yieldparam [Net::HTTPResponse] response
678
717
  # @return [Net::HTTPResponse]
679
- # @see http://www.w3.org/TR/sparql11-protocol/#query-operation
718
+ # @raise [IOError] if connection is closed
719
+ # @see https://www.w3.org/TR/sparql11-protocol/#query-operation
680
720
  def request(query, headers = {}, &block)
681
721
  # Make sure an appropriate Accept header is present
682
722
  headers['Accept'] ||= if (query.respond_to?(:expects_statements?) ?
@@ -686,6 +726,7 @@ module SPARQL
686
726
  else
687
727
  RESULT_ALL
688
728
  end
729
+ headers['User-Agent'] ||= "Ruby SPARQL::Client/#{SPARQL::Client::VERSION}"
689
730
 
690
731
  request = send("make_#{request_method(query)}_request", query, headers)
691
732
 
@@ -693,6 +734,7 @@ module SPARQL
693
734
 
694
735
  pre_http_hook(request) if respond_to?(:pre_http_hook)
695
736
 
737
+ raise IOError, "Client has been closed" unless @http
696
738
  response = @http.request(::URI.parse(url.to_s), request)
697
739
 
698
740
  post_http_hook(response) if respond_to?(:post_http_hook)
@@ -722,10 +764,10 @@ module SPARQL
722
764
  # @param [String, #to_s] query
723
765
  # @param [Hash{String => String}] headers
724
766
  # @return [Net::HTTPRequest]
725
- # @see http://www.w3.org/TR/sparql11-protocol/#query-via-get
767
+ # @see https://www.w3.org/TR/sparql11-protocol/#query-via-get
726
768
  def make_get_request(query, headers = {})
727
769
  url = self.url.dup
728
- url.query_values = (url.query_values || {}).merge(:query => query.to_s)
770
+ url.query_values = (url.query_values || {}).merge(query: query.to_s)
729
771
  set_url_default_graph url unless @options[:graph].nil?
730
772
  request = Net::HTTP::Get.new(url.request_uri, self.headers.merge(headers))
731
773
  request
@@ -737,8 +779,8 @@ module SPARQL
737
779
  # @param [String, #to_s] query
738
780
  # @param [Hash{String => String}] headers
739
781
  # @return [Net::HTTPRequest]
740
- # @see http://www.w3.org/TR/sparql11-protocol/#query-via-post-direct
741
- # @see http://www.w3.org/TR/sparql11-protocol/#query-via-post-urlencoded
782
+ # @see https://www.w3.org/TR/sparql11-protocol/#query-via-post-direct
783
+ # @see https://www.w3.org/TR/sparql11-protocol/#query-via-post-urlencoded
742
784
  def make_post_request(query, headers = {})
743
785
  if @alt_endpoint.nil?
744
786
  url = self.url.dup