sparql-client 2.0.2 → 3.1.0

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
- SHA1:
3
- metadata.gz: 1a6ad63410ae80d9c27f0be01b03b76e190ff9d3
4
- data.tar.gz: 8eb1f2318206ca77f8d3de492edd5b39a21544e6
2
+ SHA256:
3
+ metadata.gz: 25fd44467b4b7014096fea7c336164c863b3da501ee747466ed486bdfab2f93d
4
+ data.tar.gz: f44d3e424e8c3fb13b0a323403212134c34e8fa7fb7ebaba562ded69a9d02fd7
5
5
  SHA512:
6
- metadata.gz: 06077bcbae3445a986788c5b0a6486892a13dbcf66c20d21a6fae3af20b119065dcaef2608f734d8f9b2c37574c99a08799293ec95cb93c93e8d872a0b90d895
7
- data.tar.gz: 65a0b4b376331ec5997c34590035f00223391672a092c696129ca51de547082c58178677d49b74ac99e577f62a4b60552fa37d82e5d3c7d08c40a65b07e70ea3
6
+ metadata.gz: 404e7f204b5bda734f531b29133705dcdf236a4bc7f348f32f6034595e43cd7e78814cb2d8cf66c696a9fd548496fd50b245b5bf2e705a551ef6e5012321c7d6
7
+ data.tar.gz: 4764b49167f0bd23e16455d9e1cf9ede6193db3dcd96eb17fd9ed4245557906dd5195424dbe88f098c8381e580ffc433f577e558b5472cb4f8f2a1756de3f911
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- #SPARQL Client for RDF.rb
1
+ # SPARQL Client for RDF.rb
2
2
 
3
3
  This is a [Ruby][] implementation of a [SPARQL][] client for [RDF.rb][].
4
4
 
@@ -8,7 +8,7 @@ This is a [Ruby][] implementation of a [SPARQL][] client for [RDF.rb][].
8
8
  [![Build Status](https://travis-ci.org/ruby-rdf/sparql-client.png?branch=master)](http://travis-ci.org/ruby-rdf/sparql-client)
9
9
  [![Coverage Status](https://coveralls.io/repos/ruby-rdf/sparql-client/badge.svg?branch=master&service=github)](https://coveralls.io/github/ruby-rdf/sparql-client?branch=master)
10
10
 
11
- ##Features
11
+ ## Features
12
12
 
13
13
  * Executes queries against any SPARQL 1.0/1.1-compatible endpoint over HTTP,
14
14
  or against an `RDF::Queryable` instance, using the `SPARQL` gem.
@@ -22,90 +22,121 @@ This is a [Ruby][] implementation of a [SPARQL][] client for [RDF.rb][].
22
22
  * Supports accessing endpoints as read/write [`RDF::Repository`][RDF::Repository]
23
23
  instances {SPARQL::Client::Repository}.
24
24
 
25
- ##Examples
25
+ ## Examples
26
26
 
27
27
  ### Querying a remote SPARQL endpoint
28
- require 'sparql/client'
29
28
 
30
- sparql = SPARQL::Client.new("http://dbpedia.org/sparql")
29
+ ```ruby
30
+ require 'sparql/client'
31
+ sparql = SPARQL::Client.new("http://dbpedia.org/sparql")
32
+ ```
31
33
 
32
- ### Querying a `RDF::Repository` instance
34
+ ### Querying a remote SPARQL endpoint with a custom User-Agent
35
+ By default, SPARQL::Client adds a `User-Agent` field to requests, but applications may choose to provide their own, using the `headers` option:
33
36
 
34
- require 'rdf/trig'
35
- repository = RDF::Repository.load("http://example/dataset.trig")
37
+ ```ruby
38
+ require 'sparql/client'
39
+ sparql = SPARQL::Client.new("http://dbpedia.org/sparql", headers: {'User-Agent' => 'MyBotName'})
40
+ ```
36
41
 
37
- sparql = SPARQL::Client.new(repository)
42
+ ### Querying a remote SPARQL endpoint with a specified default graph
38
43
 
39
- ### Executing a boolean query and outputting the result
44
+ ```ruby
45
+ require 'sparql/client'
46
+ sparql = SPARQL::Client.new("http://dbpedia.org/sparql", { graph: "http://dbpedia.org" })
47
+ ```
48
+
49
+
50
+ ### Querying a `RDF::Repository` instance
51
+
52
+ ```ruby
53
+ require 'rdf/trig'
54
+ repository = RDF::Repository.load("http://example/dataset.trig")
55
+ sparql = SPARQL::Client.new(repository)
56
+ ```
40
57
 
41
- # ASK WHERE { ?s ?p ?o }
42
- result = sparql.ask.whether([:s, :p, :o]).true?
58
+ ### Executing a boolean query and outputting the result
43
59
 
44
- puts result.inspect #=> true or false
60
+ ```ruby
61
+ # ASK WHERE { ?s ?p ?o }
62
+ result = sparql.ask.whether([:s, :p, :o]).true?
63
+ puts result.inspect #=> true or false
64
+ ```
45
65
 
46
66
  ### Executing a tuple query and iterating over the returned solutions
47
67
 
48
- # SELECT * WHERE { ?s ?p ?o } OFFSET 100 LIMIT 10
49
- query = sparql.select.where([:s, :p, :o]).offset(100).limit(10)
68
+ ```ruby
69
+ # SELECT * WHERE { ?s ?p ?o } OFFSET 100 LIMIT 10
70
+ query = sparql.select.where([:s, :p, :o]).offset(100).limit(10)
50
71
 
51
- query.each_solution do |solution|
52
- puts solution.inspect
53
- end
72
+ query.each_solution do |solution|
73
+ puts solution.inspect
74
+ end
75
+ ```
54
76
 
55
77
  ### Executing a graph query and iterating over the returned statements
56
78
 
57
- # CONSTRUCT { ?s ?p ?o } WHERE { ?s ?p ?o } LIMIT 10
58
- query = sparql.construct([:s, :p, :o]).where([:s, :p, :o]).limit(10)
59
79
 
60
- query.each_statement do |statement|
61
- puts statement.inspect
62
- end
80
+ ```ruby
81
+ # CONSTRUCT { ?s ?p ?o } WHERE { ?s ?p ?o } LIMIT 10
82
+ query = sparql.construct([:s, :p, :o]).where([:s, :p, :o]).limit(10)
83
+
84
+ query.each_statement do |statement|
85
+ puts statement.inspect
86
+ end
87
+ ```
63
88
 
64
89
  ### Executing an arbitrary textual SPARQL query string
65
90
 
66
- result = sparql.query("ASK WHERE { ?s ?p ?o }")
91
+ ```ruby
92
+ result = sparql.query("ASK WHERE { ?s ?p ?o }")
67
93
 
68
- puts result.inspect #=> true or false
94
+ puts result.inspect #=> true or false
95
+ ```
69
96
 
70
97
  ### Inserting data into a graph
71
98
 
72
- # INSERT DATA { <http://example.org/jhacker> <http://xmlns.com/foaf/0.1/name> "J. Random Hacker" .}
73
- data = RDF::Graph.new do |graph|
74
- graph << [RDF::URI('http://example.org/jhacker'), RDF::Vocab::FOAF.name, "J. Random Hacker"]
75
- end
76
- insert_data(data)
99
+ ```ruby
100
+ # INSERT DATA { <http://example.org/jhacker> <http://xmlns.com/foaf/0.1/name> "J. Random Hacker" .}
101
+ data = RDF::Graph.new do |graph|
102
+ graph << [RDF::URI('http://example.org/jhacker'), RDF::Vocab::FOAF.name, "J. Random Hacker"]
103
+ end
104
+ sparql.insert_data(data)
105
+ ```
77
106
 
78
107
  ### Deleting data from a graph
79
108
 
80
- # DELETE DATA { <http://example.org/jhacker> <http://xmlns.com/foaf/0.1/name> "J. Random Hacker" .}
81
- data = RDF::Graph.new do |graph|
82
- graph << [RDF::URI('http://example.org/jhacker'), RDF::Vocab::FOAF.name, "J. Random Hacker"]
83
- end
84
- delete_data(data)
109
+ ```ruby
110
+ # DELETE DATA { <http://example.org/jhacker> <http://xmlns.com/foaf/0.1/name> "J. Random Hacker" .}
111
+ data = RDF::Graph.new do |graph|
112
+ graph << [RDF::URI('http://example.org/jhacker'), RDF::Vocab::FOAF.name, "J. Random Hacker"]
113
+ end
114
+ sparql.delete_data(data)
115
+ ```
85
116
 
86
- ##Documentation
117
+ ## Documentation
87
118
 
88
- * {SPARQL::Client}
89
- * {SPARQL::Client::Query}
90
- * {SPARQL::Client::Repository}
91
- * {SPARQL::Client::Update}
119
+ * [SPARQL::Client](https://www.rubydoc.info/github/ruby-rdf/sparql-client/SPARQL/Client)
120
+ * [SPARQL::Client::Query](https://www.rubydoc.info/github/ruby-rdf/sparql-client/SPARQL/Client/Query)
121
+ * [SPARQL::Client::Repository](https://www.rubydoc.info/github/ruby-rdf/sparql-client/SPARQL/Client/Repository)
122
+ * [SPARQL::Client::Update](https://www.rubydoc.info/github/ruby-rdf/sparql-client/SPARQL/Client/Update)
92
123
 
93
- ##Dependencies
124
+ ## Dependencies
94
125
 
95
- * [Ruby](http://ruby-lang.org/) (>= 2.0)
96
- * [RDF.rb](http://rubygems.org/gems/rdf) (>= 2.0)
97
- * [Net::HTTP::Persistent](http://rubygems.org/gems/net-http-persistent) (>= 1.4)
98
- * Soft dependency on [SPARQL](http://rubygems.org/gems/sparql) (>= 1.1)
99
- * Soft dependency on [Nokogiri](http://rubygems.org/gems/nokogiri) (>= 1.6)
126
+ * [Ruby](http://ruby-lang.org/) (>= 2.4)
127
+ * [RDF.rb](http://rubygems.org/gems/rdf) (~> 3.1)
128
+ * [Net::HTTP::Persistent](http://rubygems.org/gems/net-http-persistent) (~> 3.1)
129
+ * Soft dependency on [SPARQL](http://rubygems.org/gems/sparql) (~> 3.1)
130
+ * Soft dependency on [Nokogiri](http://rubygems.org/gems/nokogiri) (>= 1.10)
100
131
 
101
- ##Installation
132
+ ## Installation
102
133
 
103
134
  The recommended installation method is via [RubyGems](http://rubygems.org/).
104
135
  To install the latest official release of the `SPARQL::Client` gem, do:
105
136
 
106
137
  % [sudo] gem install sparql-client
107
138
 
108
- ##Download
139
+ ## Download
109
140
 
110
141
  To get a local working copy of the development repository, do:
111
142
 
@@ -116,17 +147,17 @@ follows:
116
147
 
117
148
  % wget http://github.com/ruby-rdf/sparql-client/tarball/master
118
149
 
119
- ##Mailing List
150
+ ## Mailing List
120
151
 
121
152
  * <http://lists.w3.org/Archives/Public/public-rdf-ruby/>
122
153
 
123
- ##Authors
154
+ ## Authors
124
155
 
125
156
  * [Arto Bendiken](http://github.com/bendiken) - <http://ar.to/>
126
157
  * [Ben Lavender](http://github.com/bhuga) - <http://bhuga.net/>
127
158
  * [Gregg Kellogg](http://github.com/gkellogg) - <http://greggkellogg.net/>
128
159
 
129
- ##Contributors
160
+ ## Contributors
130
161
 
131
162
  * [Christoph Badura](http://github.com/bad) - <http://github.com/bad>
132
163
  * [James Hetherington](http://github.com/jamespjh) - <http://twitter.com/jamespjh>
@@ -140,7 +171,7 @@ follows:
140
171
  * [Thomas Feron](http://github.com/thoferon) - <http://github.com/thoferon>
141
172
  * [Nick Gottlieb](http://github.com/ngottlieb) - <http://www.nicholasgottlieb.com>
142
173
 
143
- ##Contributing
174
+ ## Contributing
144
175
  This repository uses [Git Flow](https://github.com/nvie/gitflow) to mange development and release activity. All submissions _must_ be on a feature branch based on the _develop_ branch to ease staging and integration.
145
176
 
146
177
  * Do your best to adhere to the existing coding conventions and idioms.
@@ -155,16 +186,15 @@ This repository uses [Git Flow](https://github.com/nvie/gitflow) to mange develo
155
186
  of thumb, additions larger than about 15 lines of code), we need an
156
187
  explicit [public domain dedication][PDD] on record from you.
157
188
 
158
- ##Resources
189
+ ## Resources
159
190
 
160
191
  * <http://ruby-rdf.github.com/sparql-client/>
161
192
  * <http://github.com/ruby-rdf/sparql-client>
162
193
  * <http://rubygems.org/gems/sparql-client>
163
- * <http://rubyforge.org/projects/sparql/>
164
194
  * <http://raa.ruby-lang.org/project/sparql-client/>
165
195
  * <http://www.ohloh.net/p/rdf>
166
196
 
167
- ##License
197
+ ## License
168
198
 
169
199
  This is free and unencumbered public domain software. For more information,
170
200
  see <http://unlicense.org/> or the accompanying {file:UNLICENSE} file.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 2.0.2
1
+ 3.1.0
@@ -40,7 +40,7 @@ module SPARQL
40
40
  '*/*;q=0.1'
41
41
  ].join(', ').freeze
42
42
  GRAPH_ALL = (
43
- RDF::Format.content_types.keys +
43
+ RDF::Format.content_types.keys +
44
44
  ['*/*;q=0.1']
45
45
  ).join(', ').freeze
46
46
 
@@ -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, proc {@http.shutdown if @http.respond_to?(:shutdown)})
98
106
  end
99
107
 
100
108
  if block_given?
@@ -105,13 +113,23 @@ module SPARQL
105
113
  end
106
114
  end
107
115
 
116
+ ##
117
+ # Closes a client instance by finishing the connection.
118
+ # 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.
119
+ # @return [void] `self`
120
+ def close
121
+ @http.shutdown if @http
122
+ @http = nil
123
+ self
124
+ end
125
+
108
126
  ##
109
127
  # Executes a boolean `ASK` query.
110
128
  #
111
129
  # @param (see Query.ask)
112
130
  # @return [Query]
113
- def ask(*args)
114
- call_query_method(:ask, *args)
131
+ def ask(*args, **options)
132
+ call_query_method(:ask, *args, **options)
115
133
  end
116
134
 
117
135
  ##
@@ -119,8 +137,8 @@ module SPARQL
119
137
  #
120
138
  # @param (see Query.select)
121
139
  # @return [Query]
122
- def select(*args)
123
- call_query_method(:select, *args)
140
+ def select(*args, **options)
141
+ call_query_method(:select, *args, **options)
124
142
  end
125
143
 
126
144
  ##
@@ -128,8 +146,8 @@ module SPARQL
128
146
  #
129
147
  # @param (see Query.describe)
130
148
  # @return [Query]
131
- def describe(*args)
132
- call_query_method(:describe, *args)
149
+ def describe(*args, **options)
150
+ call_query_method(:describe, *args, **options)
133
151
  end
134
152
 
135
153
  ##
@@ -137,8 +155,8 @@ module SPARQL
137
155
  #
138
156
  # @param (see Query.construct)
139
157
  # @return [Query]
140
- def construct(*args)
141
- call_query_method(:construct, *args)
158
+ def construct(*args, **options)
159
+ call_query_method(:construct, *args, **options)
142
160
  end
143
161
 
144
162
  ##
@@ -157,19 +175,19 @@ module SPARQL
157
175
  # })
158
176
  #
159
177
  # @example Inserting data sourced from a file or URL
160
- # data = RDF::Graph.load("http://rdf.rubyforge.org/doap.nt")
178
+ # data = RDF::Graph.load("https://raw.githubusercontent.com/ruby-rdf/rdf/develop/etc/doap.nt")
161
179
  # client.insert_data(data)
162
180
  #
163
181
  # @example Inserting data into a named graph
164
- # client.insert_data(data, :graph => "http://example.org/")
182
+ # client.insert_data(data, graph: "http://example.org/")
165
183
  #
166
184
  # @param [RDF::Enumerable] data
167
185
  # @param [Hash{Symbol => Object}] options
168
186
  # @option options [RDF::URI, String] :graph
169
187
  # @return [void] `self`
170
188
  # @see http://www.w3.org/TR/sparql11-update/#insertData
171
- def insert_data(data, options = {})
172
- self.update(Update::InsertData.new(data, options))
189
+ def insert_data(data, **options)
190
+ self.update(Update::InsertData.new(data, **options))
173
191
  end
174
192
 
175
193
  ##
@@ -178,19 +196,19 @@ module SPARQL
178
196
  # This requires that the endpoint support SPARQL 1.1 Update.
179
197
  #
180
198
  # @example Deleting data sourced from a file or URL
181
- # data = RDF::Graph.load("http://rdf.rubyforge.org/doap.nt")
199
+ # data = RDF::Graph.load("https://raw.githubusercontent.com/ruby-rdf/rdf/develop/etc/doap.nt")
182
200
  # client.delete_data(data)
183
201
  #
184
202
  # @example Deleting data from a named graph
185
- # client.delete_data(data, :graph => "http://example.org/")
203
+ # client.delete_data(data, graph: "http://example.org/")
186
204
  #
187
205
  # @param [RDF::Enumerable] data
188
206
  # @param [Hash{Symbol => Object}] options
189
207
  # @option options [RDF::URI, String] :graph
190
208
  # @return [void] `self`
191
209
  # @see http://www.w3.org/TR/sparql11-update/#deleteData
192
- def delete_data(data, options = {})
193
- self.update(Update::DeleteData.new(data, options))
210
+ def delete_data(data, **options)
211
+ self.update(Update::DeleteData.new(data, **options))
194
212
  end
195
213
 
196
214
  ##
@@ -205,8 +223,8 @@ module SPARQL
205
223
  # @option options [RDF::URI, String] :graph
206
224
  # @return [void] `self`
207
225
  # @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))
226
+ def delete_insert(delete_graph, insert_graph = nil, where_graph = nil, **options)
227
+ self.update(Update::DeleteInsert.new(delete_graph, insert_graph, where_graph, **options))
210
228
  end
211
229
 
212
230
  ##
@@ -222,8 +240,8 @@ module SPARQL
222
240
  # @option options [Boolean] :silent
223
241
  # @return [void] `self`
224
242
  # @see http://www.w3.org/TR/sparql11-update/#clear
225
- def clear_graph(graph_uri, options = {})
226
- self.clear(:graph, graph_uri, options)
243
+ def clear_graph(graph_uri, **options)
244
+ self.clear(:graph, graph_uri, **options)
227
245
  end
228
246
 
229
247
  ##
@@ -249,7 +267,7 @@ module SPARQL
249
267
  # @option options [Boolean] :silent
250
268
  # @return [void] `self`
251
269
  #
252
- # @overload clear(what, *arguments, options = {})
270
+ # @overload clear(what, *arguments, **options)
253
271
  # @param [Symbol, #to_sym] what
254
272
  # @param [Array] arguments splat of other arguments to {Update::Clear}.
255
273
  # @param [Hash{Symbol => Object}] options
@@ -263,9 +281,9 @@ module SPARQL
263
281
 
264
282
  ##
265
283
  # @private
266
- def call_query_method(meth, *args)
284
+ def call_query_method(meth, *args, **options)
267
285
  client = self
268
- result = Query.send(meth, *args)
286
+ result = Query.send(meth, *args, **options)
269
287
  (class << result; self; end).send(:define_method, :execute) do
270
288
  client.query(self)
271
289
  end
@@ -288,21 +306,22 @@ module SPARQL
288
306
  # @option options [String] :content_type
289
307
  # @option options [Hash] :headers
290
308
  # @return [Array<RDF::Query::Solution>]
309
+ # @raise [IOError] if connection is closed
291
310
  # @see http://www.w3.org/TR/sparql11-protocol/#query-operation
292
- def query(query, options = {})
311
+ def query(query, **options)
293
312
  @op = :query
294
313
  @alt_endpoint = options[:endpoint]
295
314
  case @url
296
315
  when RDF::Queryable
297
316
  require 'sparql' unless defined?(::SPARQL::Grammar)
298
317
  begin
299
- SPARQL.execute(query, @url, options)
318
+ SPARQL.execute(query, @url, **options)
300
319
  rescue SPARQL::MalformedQuery
301
320
  $stderr.puts "error running #{query}: #{$!}"
302
321
  raise
303
322
  end
304
323
  else
305
- parse_response(response(query, options), options)
324
+ parse_response(response(query, **options), **options)
306
325
  end
307
326
  end
308
327
 
@@ -315,16 +334,17 @@ module SPARQL
315
334
  # @option options [String] :content_type
316
335
  # @option options [Hash] :headers
317
336
  # @return [void] `self`
337
+ # @raise [IOError] if connection is closed
318
338
  # @see http://www.w3.org/TR/sparql11-protocol/#update-operation
319
- def update(query, options = {})
339
+ def update(query, **options)
320
340
  @op = :update
321
341
  @alt_endpoint = options[:endpoint]
322
342
  case @url
323
343
  when RDF::Queryable
324
344
  require 'sparql' unless defined?(::SPARQL::Grammar)
325
- SPARQL.execute(query, @url, options.merge(update: true))
345
+ SPARQL.execute(query, @url, update: true, **options)
326
346
  else
327
- response(query, options)
347
+ response(query, **options)
328
348
  end
329
349
  self
330
350
  end
@@ -338,8 +358,9 @@ module SPARQL
338
358
  # @option options [String] :content_type
339
359
  # @option options [Hash] :headers
340
360
  # @return [String]
341
- def response(query, options = {})
342
- headers = options[:headers] || {}
361
+ # @raise [IOError] if connection is closed
362
+ def response(query, **options)
363
+ headers = options[:headers] || @headers
343
364
  headers['Accept'] = options[:content_type] if options[:content_type]
344
365
  request(query, headers) do |response|
345
366
  case response
@@ -359,7 +380,7 @@ module SPARQL
359
380
  # @param [Net::HTTPSuccess] response
360
381
  # @param [Hash{Symbol => Object}] options
361
382
  # @return [Object]
362
- def parse_response(response, options = {})
383
+ def parse_response(response, **options)
363
384
  case options[:content_type] || response.content_type
364
385
  when NilClass
365
386
  response.body
@@ -374,7 +395,7 @@ module SPARQL
374
395
  when RESULT_TSV
375
396
  self.class.parse_tsv_bindings(response.body, nodes)
376
397
  else
377
- parse_rdf_serialization(response, options)
398
+ parse_rdf_serialization(response, **options)
378
399
  end
379
400
  end
380
401
 
@@ -411,9 +432,9 @@ module SPARQL
411
432
  when :uri
412
433
  RDF::URI.new(value['value'])
413
434
  when :literal
414
- RDF::Literal.new(value['value'], :datatype => value['datatype'], :language => value['xml:lang'])
435
+ RDF::Literal.new(value['value'], datatype: value['datatype'], language: value['xml:lang'])
415
436
  when :'typed-literal'
416
- RDF::Literal.new(value['value'], :datatype => value['datatype'])
437
+ RDF::Literal.new(value['value'], datatype: value['datatype'])
417
438
  else nil
418
439
  end
419
440
  end
@@ -529,7 +550,7 @@ module SPARQL
529
550
  when :literal
530
551
  lang = value.respond_to?(:attr) ? value.attr('xml:lang') : value.attributes['xml:lang']
531
552
  datatype = value.respond_to?(:attr) ? value.attr('datatype') : value.attributes['datatype']
532
- RDF::Literal.new(value.text, :language => lang, :datatype => datatype)
553
+ RDF::Literal.new(value.text, language: lang, datatype: datatype)
533
554
  else nil
534
555
  end
535
556
  end
@@ -538,12 +559,12 @@ module SPARQL
538
559
  # @param [Net::HTTPSuccess] response
539
560
  # @param [Hash{Symbol => Object}] options
540
561
  # @return [RDF::Enumerable]
541
- def parse_rdf_serialization(response, options = {})
542
- options = {:content_type => response.content_type} unless options[:content_type]
562
+ def parse_rdf_serialization(response, **options)
563
+ options = {content_type: response.content_type} unless options[:content_type]
543
564
  if reader = RDF::Reader.for(options)
544
565
  reader.new(response.body)
545
566
  else
546
- raise RDF::ReaderError, "no suitable rdf reader was found."
567
+ raise RDF::ReaderError, "no RDF reader was found for #{options}."
547
568
  end
548
569
  end
549
570
 
@@ -609,11 +630,15 @@ module SPARQL
609
630
  # @private
610
631
  def self.serialize_patterns(patterns, use_vars = false)
611
632
  patterns.map do |pattern|
612
- serialized_pattern = RDF::Statement.from(pattern).to_triple.each_with_index.map do |v, i|
613
- if i == 1
614
- SPARQL::Client.serialize_predicate(v)
615
- else
616
- SPARQL::Client.serialize_value(v, use_vars)
633
+ serialized_pattern = case pattern
634
+ when SPARQL::Client::QueryElement then [pattern.to_s]
635
+ else
636
+ RDF::Statement.from(pattern).to_triple.each_with_index.map do |v, i|
637
+ if i == 1
638
+ SPARQL::Client.serialize_predicate(v)
639
+ else
640
+ SPARQL::Client.serialize_value(v, use_vars)
641
+ end
617
642
  end
618
643
  end
619
644
  serialized_pattern.join(' ') + ' .'
@@ -654,7 +679,7 @@ module SPARQL
654
679
  value = ENV['https_proxy']
655
680
  proxy_url = URI.parse(value) unless value.nil? || value.empty?
656
681
  end
657
- klass = Net::HTTP::Persistent.new(self.class.to_s, proxy_url)
682
+ klass = Net::HTTP::Persistent.new(name: self.class.to_s, proxy: proxy_url)
658
683
  klass.keep_alive = @options[:keep_alive] || 120
659
684
  klass.read_timeout = @options[:read_timeout] || 60
660
685
  klass
@@ -665,9 +690,15 @@ module SPARQL
665
690
  #
666
691
  # @param [String, #to_s] query
667
692
  # @param [Hash{String => String}] headers
693
+ # HTTP Request headers
694
+ #
695
+ # 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.
696
+ #
697
+ # Defaults `User-Agent` header, unless one is specified.
668
698
  # @yield [response]
669
699
  # @yieldparam [Net::HTTPResponse] response
670
700
  # @return [Net::HTTPResponse]
701
+ # @raise [IOError] if connection is closed
671
702
  # @see http://www.w3.org/TR/sparql11-protocol/#query-operation
672
703
  def request(query, headers = {}, &block)
673
704
  # Make sure an appropriate Accept header is present
@@ -678,6 +709,7 @@ module SPARQL
678
709
  else
679
710
  RESULT_ALL
680
711
  end
712
+ headers['User-Agent'] ||= "Ruby SPARQL::Client/#{SPARQL::Client::VERSION}"
681
713
 
682
714
  request = send("make_#{request_method(query)}_request", query, headers)
683
715
 
@@ -685,6 +717,7 @@ module SPARQL
685
717
 
686
718
  pre_http_hook(request) if respond_to?(:pre_http_hook)
687
719
 
720
+ raise IOError, "Client has been closed" unless @http
688
721
  response = @http.request(::URI.parse(url.to_s), request)
689
722
 
690
723
  post_http_hook(response) if respond_to?(:post_http_hook)
@@ -693,8 +726,8 @@ module SPARQL
693
726
  if response.kind_of? Net::HTTPRedirection
694
727
  response = @http.request(::URI.parse(response['location']), request)
695
728
  else
696
- return block_given? ? block.call(response) : response
697
- end
729
+ return block_given? ? block.call(response) : response
730
+ end
698
731
  end
699
732
  raise ServerError, "Infinite redirect at #{url}. Redirected more than 10 times."
700
733
  end
@@ -717,7 +750,8 @@ module SPARQL
717
750
  # @see http://www.w3.org/TR/sparql11-protocol/#query-via-get
718
751
  def make_get_request(query, headers = {})
719
752
  url = self.url.dup
720
- url.query_values = (url.query_values || {}).merge(:query => query.to_s)
753
+ url.query_values = (url.query_values || {}).merge(query: query.to_s)
754
+ set_url_default_graph url unless @options[:graph].nil?
721
755
  request = Net::HTTP::Get.new(url.request_uri, self.headers.merge(headers))
722
756
  request
723
757
  end
@@ -732,21 +766,67 @@ module SPARQL
732
766
  # @see http://www.w3.org/TR/sparql11-protocol/#query-via-post-urlencoded
733
767
  def make_post_request(query, headers = {})
734
768
  if @alt_endpoint.nil?
735
- endpoint = url.request_uri
769
+ url = self.url.dup
770
+ set_url_default_graph url unless @options[:graph].nil?
771
+ endpoint = url.request_uri
736
772
  else
737
773
  endpoint = @alt_endpoint
738
774
  end
775
+
739
776
  request = Net::HTTP::Post.new(endpoint, self.headers.merge(headers))
740
777
  case (self.options[:protocol] || DEFAULT_PROTOCOL).to_s
741
778
  when '1.1'
742
779
  request['Content-Type'] = 'application/sparql-' + (@op || :query).to_s
743
780
  request.body = query.to_s
744
781
  when '1.0'
745
- request.set_form_data((@op || :query) => query.to_s)
782
+ form_data = {(@op || :query) => query.to_s}
783
+ form_data.merge!(
784
+ {:'default-graph-uri' => @options[:graph]}
785
+ ) if !@options[:graph].nil? && (@op.eql? :query)
786
+ form_data.merge!(
787
+ {:'using-graph-uri' => @options[:graph]}
788
+ ) if !@options[:graph].nil? && (@op.eql? :update)
789
+ request.set_form_data(form_data)
746
790
  else
747
791
  raise ArgumentError, "unknown SPARQL protocol version: #{self.options[:protocol].inspect}"
748
792
  end
749
793
  request
750
794
  end
795
+
796
+ ##
797
+ # Setup url query parameter to use a specified default graph
798
+ #
799
+ # @see https://www.w3.org/TR/sparql11-protocol/#query-operation
800
+ # @see https://www.w3.org/TR/sparql11-protocol/#update-operation
801
+ def set_url_default_graph url
802
+ if @options[:graph].is_a? Array
803
+ graphs = @options[:graph].map {|graph|
804
+ CGI::escape(graph)
805
+ }
806
+ else
807
+ graphs = CGI::escape(@options[:graph])
808
+ end
809
+ case @op
810
+ when :query
811
+ url.query_values = (url.query_values || {})
812
+ .merge(:'default-graph-uri' => graphs)
813
+ when :update
814
+ url.query_values = (url.query_values || {})
815
+ .merge(:'using-graph-uri' => graphs)
816
+ end
817
+ end
818
+
819
+ # A query element can be used as a component of a query. It may be initialized with a string, which is wrapped in an appropriate container depending on the type of QueryElement. Implements {#to_s} to property serialize when generating a SPARQL query.
820
+ class QueryElement
821
+ attr_reader :elements
822
+
823
+ def initialize(*args)
824
+ @elements = args
825
+ end
826
+
827
+ def to_s
828
+ raise NotImplemented
829
+ end
830
+ end
751
831
  end # Client
752
832
  end # SPARQL