sparql-client 3.0.1 → 3.2.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.
@@ -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