sparql-client 2.0.2 → 3.1.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.
- checksums.yaml +5 -5
- data/README.md +85 -55
- data/VERSION +1 -1
- data/lib/sparql/client.rb +132 -52
- data/lib/sparql/client/query.rb +373 -68
- data/lib/sparql/client/repository.rb +39 -15
- data/lib/sparql/client/update.rb +28 -29
- data/lib/sparql/client/version.rb +2 -2
- metadata +21 -50
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 25fd44467b4b7014096fea7c336164c863b3da501ee747466ed486bdfab2f93d
|
4
|
+
data.tar.gz: f44d3e424e8c3fb13b0a323403212134c34e8fa7fb7ebaba562ded69a9d02fd7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
[](http://travis-ci.org/ruby-rdf/sparql-client)
|
9
9
|
[](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
|
-
|
29
|
+
```ruby
|
30
|
+
require 'sparql/client'
|
31
|
+
sparql = SPARQL::Client.new("http://dbpedia.org/sparql")
|
32
|
+
```
|
31
33
|
|
32
|
-
### Querying a
|
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
|
-
|
35
|
-
|
37
|
+
```ruby
|
38
|
+
require 'sparql/client'
|
39
|
+
sparql = SPARQL::Client.new("http://dbpedia.org/sparql", headers: {'User-Agent' => 'MyBotName'})
|
40
|
+
```
|
36
41
|
|
37
|
-
|
42
|
+
### Querying a remote SPARQL endpoint with a specified default graph
|
38
43
|
|
39
|
-
|
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
|
-
|
42
|
-
result = sparql.ask.whether([:s, :p, :o]).true?
|
58
|
+
### Executing a boolean query and outputting the result
|
43
59
|
|
44
|
-
|
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
|
-
|
49
|
-
|
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
|
-
|
52
|
-
|
53
|
-
|
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
|
-
|
61
|
-
|
62
|
-
|
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
|
-
|
91
|
+
```ruby
|
92
|
+
result = sparql.query("ASK WHERE { ?s ?p ?o }")
|
67
93
|
|
68
|
-
|
94
|
+
puts result.inspect #=> true or false
|
95
|
+
```
|
69
96
|
|
70
97
|
### Inserting data into a graph
|
71
98
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
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
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
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
|
-
*
|
89
|
-
*
|
90
|
-
*
|
91
|
-
*
|
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.
|
96
|
-
* [RDF.rb](http://rubygems.org/gems/rdf) (
|
97
|
-
* [Net::HTTP::Persistent](http://rubygems.org/gems/net-http-persistent) (
|
98
|
-
* Soft dependency on [SPARQL](http://rubygems.org/gems/sparql) (
|
99
|
-
* Soft dependency on [Nokogiri](http://rubygems.org/gems/nokogiri) (>= 1.
|
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
|
-
|
1
|
+
3.1.0
|
data/lib/sparql/client.rb
CHANGED
@@ -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
|
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("
|
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, :
|
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("
|
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, :
|
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,
|
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
|
-
|
342
|
-
|
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'], :
|
435
|
+
RDF::Literal.new(value['value'], datatype: value['datatype'], language: value['xml:lang'])
|
415
436
|
when :'typed-literal'
|
416
|
-
RDF::Literal.new(value['value'], :
|
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, :
|
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 = {:
|
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
|
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 =
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
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(:
|
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
|
-
|
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
|
-
|
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
|