sparql-client 2.2.1 → 3.1.2

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: 63643389b5260847e6a5ff81f8ec4e7a8d754adf
4
- data.tar.gz: b0ed32a9d7f1fd58efe6de87ab64f2eb0f10a758
2
+ SHA256:
3
+ metadata.gz: 512a63b7dcf77b57309f5c1cd734a4db60e84ba1977df4e3c8fab3529c0b96be
4
+ data.tar.gz: ea1e7413c3b92668960da2ad9ed632a5511d3ff334702631a29bb6bd3cf523b9
5
5
  SHA512:
6
- metadata.gz: fcfec9d172d4bb98f27136bdde32f242780080b05b1fa92390fa69f3c4faea3aad03971dc7d19b22026e228065210b86ccd543d6a749d7fe1d132737480e9459
7
- data.tar.gz: b0a1ce446f6930c620b78aee2978cd46b0c9d54f9fec3c08ea00c91f5761eeae083a19f07f00d8a48867505addb370d986d54ad9cb345dcd026826244caed2c3
6
+ metadata.gz: 185b11ee8c1597a3ed72a1161d101fccae20dcadb025fa333d0c956930d92c0ff2d98f979c9213cd8ceef73cb287fb7073b338aefa47afb51c075c307172906d
7
+ data.tar.gz: 68c871d80127d46298bddd60b4bf4df7326d67a00d1d8c522862b870846bb08326a27a44ca5aa15a9a813fd2bb4299ec98d69a3b4a554e2ad8b78f307b5432cf
data/README.md CHANGED
@@ -2,11 +2,12 @@
2
2
 
3
3
  This is a [Ruby][] implementation of a [SPARQL][] client for [RDF.rb][].
4
4
 
5
- * <http://ruby-rdf.github.com/sparql-client/>
5
+ * <https://ruby-rdf.github.com/sparql-client/>
6
6
 
7
- [![Gem Version](https://badge.fury.io/rb/sparql-client.png)](http://badge.fury.io/rb/sparql-client)
8
- [![Build Status](https://travis-ci.org/ruby-rdf/sparql-client.png?branch=master)](http://travis-ci.org/ruby-rdf/sparql-client)
7
+ [![Gem Version](https://badge.fury.io/rb/sparql-client.png)](https://badge.fury.io/rb/sparql-client)
8
+ [![Build Status](https://github.com/ruby-rdf/sparql-client/workflows/CI/badge.svg?branch=develop)](https://github.com/ruby-rdf/sparql-client/actions?query=workflow%3ACI)
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
+ [![Gitter chat](https://badges.gitter.im/ruby-rdf/rdf.png)](https://gitter.im/ruby-rdf/rdf)
10
11
 
11
12
  ## Features
12
13
 
@@ -18,89 +19,120 @@ This is a [Ruby][] implementation of a [SPARQL][] client for [RDF.rb][].
18
19
  * Supports tuple result sets in both XML, JSON, CSV and TSV formats, with JSON being
19
20
  the preferred default for content-negotiation purposes.
20
21
  * Supports graph results in any RDF serialization format understood by RDF.rb.
21
- * Returns results using the [RDF.rb object model][RDF.rb model].
22
+ * Returns results using the RDF.rb object model.
22
23
  * Supports accessing endpoints as read/write [`RDF::Repository`][RDF::Repository]
23
24
  instances {SPARQL::Client::Repository}.
24
25
 
25
26
  ## Examples
26
27
 
27
28
  ### Querying a remote SPARQL endpoint
28
- require 'sparql/client'
29
29
 
30
- sparql = SPARQL::Client.new("http://dbpedia.org/sparql")
30
+ ```ruby
31
+ require 'sparql/client'
32
+ sparql = SPARQL::Client.new("http://dbpedia.org/sparql")
33
+ ```
31
34
 
32
- ### Querying a `RDF::Repository` instance
35
+ ### Querying a remote SPARQL endpoint with a custom User-Agent
36
+ By default, SPARQL::Client adds a `User-Agent` field to requests, but applications may choose to provide their own, using the `headers` option:
33
37
 
34
- require 'rdf/trig'
35
- repository = RDF::Repository.load("http://example/dataset.trig")
38
+ ```ruby
39
+ require 'sparql/client'
40
+ sparql = SPARQL::Client.new("http://dbpedia.org/sparql", headers: {'User-Agent' => 'MyBotName'})
41
+ ```
36
42
 
37
- sparql = SPARQL::Client.new(repository)
43
+ ### Querying a remote SPARQL endpoint with a specified default graph
38
44
 
39
- ### Executing a boolean query and outputting the result
45
+ ```ruby
46
+ require 'sparql/client'
47
+ sparql = SPARQL::Client.new("http://dbpedia.org/sparql", { graph: "http://dbpedia.org" })
48
+ ```
49
+
50
+
51
+ ### Querying a `RDF::Repository` instance
52
+
53
+ ```ruby
54
+ require 'rdf/trig'
55
+ repository = RDF::Repository.load("http://example/dataset.trig")
56
+ sparql = SPARQL::Client.new(repository)
57
+ ```
40
58
 
41
- # ASK WHERE { ?s ?p ?o }
42
- result = sparql.ask.whether([:s, :p, :o]).true?
59
+ ### Executing a boolean query and outputting the result
43
60
 
44
- puts result.inspect #=> true or false
61
+ ```ruby
62
+ # ASK WHERE { ?s ?p ?o }
63
+ result = sparql.ask.whether([:s, :p, :o]).true?
64
+ puts result.inspect #=> true or false
65
+ ```
45
66
 
46
67
  ### Executing a tuple query and iterating over the returned solutions
47
68
 
48
- # SELECT * WHERE { ?s ?p ?o } OFFSET 100 LIMIT 10
49
- query = sparql.select.where([:s, :p, :o]).offset(100).limit(10)
69
+ ```ruby
70
+ # SELECT * WHERE { ?s ?p ?o } OFFSET 100 LIMIT 10
71
+ query = sparql.select.where([:s, :p, :o]).offset(100).limit(10)
50
72
 
51
- query.each_solution do |solution|
52
- puts solution.inspect
53
- end
73
+ query.each_solution do |solution|
74
+ puts solution.inspect
75
+ end
76
+ ```
54
77
 
55
78
  ### Executing a graph query and iterating over the returned statements
56
79
 
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
80
 
60
- query.each_statement do |statement|
61
- puts statement.inspect
62
- end
81
+ ```ruby
82
+ # CONSTRUCT { ?s ?p ?o } WHERE { ?s ?p ?o } LIMIT 10
83
+ query = sparql.construct([:s, :p, :o]).where([:s, :p, :o]).limit(10)
84
+
85
+ query.each_statement do |statement|
86
+ puts statement.inspect
87
+ end
88
+ ```
63
89
 
64
90
  ### Executing an arbitrary textual SPARQL query string
65
91
 
66
- result = sparql.query("ASK WHERE { ?s ?p ?o }")
92
+ ```ruby
93
+ result = sparql.query("ASK WHERE { ?s ?p ?o }")
67
94
 
68
- puts result.inspect #=> true or false
95
+ puts result.inspect #=> true or false
96
+ ```
69
97
 
70
98
  ### Inserting data into a graph
71
99
 
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
- sparql.insert_data(data)
100
+ ```ruby
101
+ # INSERT DATA { <http://example.org/jhacker> <http://xmlns.com/foaf/0.1/name> "J. Random Hacker" .}
102
+ data = RDF::Graph.new do |graph|
103
+ graph << [RDF::URI('http://example.org/jhacker'), RDF::Vocab::FOAF.name, "J. Random Hacker"]
104
+ end
105
+ sparql.insert_data(data)
106
+ ```
77
107
 
78
108
  ### Deleting data from a graph
79
109
 
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
- sparql.delete_data(data)
110
+ ```ruby
111
+ # DELETE DATA { <http://example.org/jhacker> <http://xmlns.com/foaf/0.1/name> "J. Random Hacker" .}
112
+ data = RDF::Graph.new do |graph|
113
+ graph << [RDF::URI('http://example.org/jhacker'), RDF::Vocab::FOAF.name, "J. Random Hacker"]
114
+ end
115
+ sparql.delete_data(data)
116
+ ```
85
117
 
86
118
  ## Documentation
87
119
 
88
- * {SPARQL::Client}
89
- * {SPARQL::Client::Query}
90
- * {SPARQL::Client::Repository}
91
- * {SPARQL::Client::Update}
120
+ * [SPARQL::Client](https://www.rubydoc.info/github/ruby-rdf/sparql-client/SPARQL/Client)
121
+ * [SPARQL::Client::Query](https://www.rubydoc.info/github/ruby-rdf/sparql-client/SPARQL/Client/Query)
122
+ * [SPARQL::Client::Repository](https://www.rubydoc.info/github/ruby-rdf/sparql-client/SPARQL/Client/Repository)
123
+ * [SPARQL::Client::Update](https://www.rubydoc.info/github/ruby-rdf/sparql-client/SPARQL/Client/Update)
92
124
 
93
125
  ## Dependencies
94
126
 
95
- * [Ruby](http://ruby-lang.org/) (>= 2.2.2)
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) (>= 2.0)
99
- * Soft dependency on [Nokogiri](http://rubygems.org/gems/nokogiri) (>= 1.6)
127
+ * [Ruby](https://ruby-lang.org/) (>= 2.4)
128
+ * [RDF.rb](https://rubygems.org/gems/rdf) (~> 3.1)
129
+ * [Net::HTTP::Persistent](https://rubygems.org/gems/net-http-persistent) (~> 4.0, >= 4.0.1)
130
+ * Soft dependency on [SPARQL](https://rubygems.org/gems/sparql) (~> 3.1)
131
+ * Soft dependency on [Nokogiri](https://rubygems.org/gems/nokogiri) (>= 1.11)
100
132
 
101
133
  ## Installation
102
134
 
103
- The recommended installation method is via [RubyGems](http://rubygems.org/).
135
+ The recommended installation method is via [RubyGems](https://rubygems.org/).
104
136
  To install the latest official release of the `SPARQL::Client` gem, do:
105
137
 
106
138
  % [sudo] gem install sparql-client
@@ -114,31 +146,31 @@ To get a local working copy of the development repository, do:
114
146
  Alternatively, download the latest development version as a tarball as
115
147
  follows:
116
148
 
117
- % wget http://github.com/ruby-rdf/sparql-client/tarball/master
149
+ % wget https://github.com/ruby-rdf/sparql-client/tarball/master
118
150
 
119
151
  ## Mailing List
120
152
 
121
- * <http://lists.w3.org/Archives/Public/public-rdf-ruby/>
153
+ * <https://lists.w3.org/Archives/Public/public-rdf-ruby/>
122
154
 
123
155
  ## Authors
124
156
 
125
- * [Arto Bendiken](http://github.com/bendiken) - <http://ar.to/>
126
- * [Ben Lavender](http://github.com/bhuga) - <http://bhuga.net/>
127
- * [Gregg Kellogg](http://github.com/gkellogg) - <http://greggkellogg.net/>
157
+ * [Arto Bendiken](https://github.com/artob) - <https://ar.to/>
158
+ * [Ben Lavender](https://github.com/bhuga) - <https://bhuga.net/>
159
+ * [Gregg Kellogg](https://github.com/gkellogg) - <https://greggkellogg.net/>
128
160
 
129
161
  ## Contributors
130
162
 
131
- * [Christoph Badura](http://github.com/bad) - <http://github.com/bad>
132
- * [James Hetherington](http://github.com/jamespjh) - <http://twitter.com/jamespjh>
133
- * [Gabriel Horner](http://github.com/cldwalker) - <http://tagaholic.me/>
134
- * [Nicholas Humfrey](http://github.com/njh) - <http://www.aelius.com/njh/>
135
- * [Fumihiro Kato](http://github.com/fumi) - <http://fumi.me/>
136
- * [David Nielsen](http://github.com/drankard) - <http://github.com/drankard>
137
- * [Thamaraiselvan Poomalai](http://github.com/selvan) - <http://softonaut.blogspot.com/>
138
- * [Michael Sokol](http://github.com/mikaa123) - <http://sokolmichael.com/>
139
- * [Yves Raimond](http://github.com/moustaki) - <http://moustaki.org/>
140
- * [Thomas Feron](http://github.com/thoferon) - <http://github.com/thoferon>
141
- * [Nick Gottlieb](http://github.com/ngottlieb) - <http://www.nicholasgottlieb.com>
163
+ * [Christoph Badura](https://github.com/bad) - <https://github.com/bad>
164
+ * [James Hetherington](https://github.com/jamespjh) - <https://twitter.com/jamespjh>
165
+ * [Gabriel Horner](https://github.com/cldwalker) - <https://tagaholic.me/>
166
+ * [Nicholas Humfrey](https://github.com/njh) - <https://www.aelius.com/njh/>
167
+ * [Fumihiro Kato](https://github.com/fumi) - <https://fumi.me/>
168
+ * [David Nielsen](https://github.com/drankard) - <https://github.com/drankard>
169
+ * [Thamaraiselvan Poomalai](https://github.com/selvan) - <https://softonaut.blogspot.com/>
170
+ * [Michael Sokol](https://github.com/mikaa123) - <https://sokolmichael.com/>
171
+ * [Yves Raimond](https://github.com/moustaki) - <https://moustaki.org/>
172
+ * [Thomas Feron](https://github.com/thoferon) - <https://github.com/thoferon>
173
+ * [Nick Gottlieb](https://github.com/ngottlieb) - <https://www.nicholasgottlieb.com>
142
174
 
143
175
  ## Contributing
144
176
  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.
@@ -153,31 +185,32 @@ This repository uses [Git Flow](https://github.com/nvie/gitflow) to mange develo
153
185
  list in the the `README`. Alphabetical order applies.
154
186
  * Do note that in order for us to merge any non-trivial changes (as a rule
155
187
  of thumb, additions larger than about 15 lines of code), we need an
156
- explicit [public domain dedication][PDD] on record from you.
188
+ explicit [public domain dedication][PDD] on record from you,
189
+ which you will be asked to agree to on the first commit to a repo within the organization.
190
+ Note that the agreement applies to all repos in the [Ruby RDF](https://github.com/ruby-rdf/) organization.
157
191
 
158
192
  ## Resources
159
193
 
160
- * <http://ruby-rdf.github.com/sparql-client/>
161
- * <http://github.com/ruby-rdf/sparql-client>
162
- * <http://rubygems.org/gems/sparql-client>
163
- * <http://raa.ruby-lang.org/project/sparql-client/>
164
- * <http://www.ohloh.net/p/rdf>
194
+ * <https://ruby-rdf.github.com/sparql-client/>
195
+ * <https://github.com/ruby-rdf/sparql-client>
196
+ * <https://rubygems.org/gems/sparql-client>
197
+ * <https://raa.ruby-lang.org/project/sparql-client/>
198
+ * <https://www.ohloh.net/p/rdf>
165
199
 
166
200
  ## License
167
201
 
168
202
  This is free and unencumbered public domain software. For more information,
169
- see <http://unlicense.org/> or the accompanying {file:UNLICENSE} file.
170
-
171
- [Ruby]: http://ruby-lang.org/
172
- [RDF]: http://www.w3.org/RDF/
173
- [SPARQL]: http://en.wikipedia.org/wiki/SPARQL
174
- [SPARQL JSON]: http://www.w3.org/TR/rdf-sparql-json-res/
175
- [RDF.rb]: http://rubygems.org/gems/rdf
176
- [RDF.rb model]: http://blog.datagraph.org/2010/03/rdf-for-ruby
177
- [RDF::Repository]: http://rubydoc.info/github/ruby-rdf/rdf/RDF/Repository
178
- [DSL]: http://en.wikipedia.org/wiki/Domain-specific_language
203
+ see <https://unlicense.org/> or the accompanying {file:UNLICENSE} file.
204
+
205
+ [Ruby]: https://ruby-lang.org/
206
+ [RDF]: https://www.w3.org/RDF/
207
+ [SPARQL]: https://en.wikipedia.org/wiki/SPARQL
208
+ [SPARQL JSON]: https://www.w3.org/TR/rdf-sparql-json-res/
209
+ [RDF.rb]: https://rubygems.org/gems/rdf
210
+ [RDF::Repository]: https://rubydoc.info/github/ruby-rdf/rdf/RDF/Repository
211
+ [DSL]: https://en.wikipedia.org/wiki/Domain-specific_language
179
212
  "domain-specific language"
180
- [YARD]: http://yardoc.org/
181
- [YARD-GS]: http://rubydoc.info/docs/yard/file/docs/GettingStarted.md
182
- [PDD]: http://unlicense.org/#unlicensing-contributions
183
- [Backports]: http://rubygems.org/gems/backports
213
+ [YARD]: https://yardoc.org/
214
+ [YARD-GS]: https://rubydoc.info/docs/yard/file/docs/GettingStarted.md
215
+ [PDD]: https://unlicense.org/#unlicensing-contributions
216
+ [Backports]: https://rubygems.org/gems/backports
data/UNLICENSE CHANGED
@@ -21,4 +21,4 @@ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21
21
  ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
22
  OTHER DEALINGS IN THE SOFTWARE.
23
23
 
24
- For more information, please refer to <http://unlicense.org/>
24
+ For more information, please refer to <https://unlicense.org/>
data/VERSION CHANGED
@@ -1 +1 @@
1
- 2.2.1
1
+ 3.1.2
@@ -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'
@@ -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, 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,9 @@ 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'])
417
445
  else nil
418
446
  end
419
447
  end
@@ -421,7 +449,7 @@ module SPARQL
421
449
  ##
422
450
  # @param [String, Array<Array<String>>] csv
423
451
  # @return [<RDF::Query::Solutions>]
424
- # @see http://www.w3.org/TR/sparql11-results-csv-tsv/
452
+ # @see https://www.w3.org/TR/sparql11-results-csv-tsv/
425
453
  def self.parse_csv_bindings(csv, nodes = {})
426
454
  require 'csv' unless defined?(::CSV)
427
455
  csv = CSV.parse(csv.to_s) unless csv.is_a?(Array)
@@ -445,7 +473,7 @@ module SPARQL
445
473
  ##
446
474
  # @param [String, Array<Array<String>>] tsv
447
475
  # @return [<RDF::Query::Solutions>]
448
- # @see http://www.w3.org/TR/sparql11-results-csv-tsv/
476
+ # @see https://www.w3.org/TR/sparql11-results-csv-tsv/
449
477
  def self.parse_tsv_bindings(tsv, nodes = {})
450
478
  tsv = tsv.lines.map {|l| l.chomp.split("\t")} unless tsv.is_a?(Array)
451
479
  vars = tsv.shift.map {|h| h.sub(/^\?/, '')}
@@ -474,7 +502,7 @@ module SPARQL
474
502
  ##
475
503
  # @param [String, IO, Nokogiri::XML::Node, REXML::Element] xml
476
504
  # @return [<RDF::Query::Solutions>]
477
- # @see http://www.w3.org/TR/rdf-sparql-json-res/#results
505
+ # @see https://www.w3.org/TR/rdf-sparql-json-res/#results
478
506
  def self.parse_xml_bindings(xml, nodes = {})
479
507
  xml.force_encoding(::Encoding::UTF_8) if xml.respond_to?(:force_encoding)
480
508
 
@@ -519,7 +547,7 @@ module SPARQL
519
547
  ##
520
548
  # @param [Nokogiri::XML::Element, REXML::Element] value
521
549
  # @return [RDF::Value]
522
- # @see http://www.w3.org/TR/rdf-sparql-json-res/#variable-binding-results
550
+ # @see https://www.w3.org/TR/rdf-sparql-json-res/#variable-binding-results
523
551
  def self.parse_xml_value(value, nodes = {})
524
552
  case value.name.to_sym
525
553
  when :bnode
@@ -529,7 +557,7 @@ module SPARQL
529
557
  when :literal
530
558
  lang = value.respond_to?(:attr) ? value.attr('xml:lang') : value.attributes['xml:lang']
531
559
  datatype = value.respond_to?(:attr) ? value.attr('datatype') : value.attributes['datatype']
532
- RDF::Literal.new(value.text, :language => lang, :datatype => datatype)
560
+ RDF::Literal.new(value.text, language: lang, datatype: datatype)
533
561
  else nil
534
562
  end
535
563
  end
@@ -538,12 +566,12 @@ module SPARQL
538
566
  # @param [Net::HTTPSuccess] response
539
567
  # @param [Hash{Symbol => Object}] options
540
568
  # @return [RDF::Enumerable]
541
- def parse_rdf_serialization(response, options = {})
542
- options = {:content_type => response.content_type} unless options[:content_type]
569
+ def parse_rdf_serialization(response, **options)
570
+ options = {content_type: response.content_type} unless options[:content_type]
543
571
  if reader = RDF::Reader.for(options)
544
572
  reader.new(response.body)
545
573
  else
546
- raise RDF::ReaderError, "no suitable rdf reader was found."
574
+ raise RDF::ReaderError, "no RDF reader was found for #{options}."
547
575
  end
548
576
  end
549
577
 
@@ -615,7 +643,7 @@ module SPARQL
615
643
  RDF::Statement.from(pattern).to_triple.each_with_index.map do |v, i|
616
644
  if i == 1
617
645
  SPARQL::Client.serialize_predicate(v)
618
- else
646
+ else
619
647
  SPARQL::Client.serialize_value(v, use_vars)
620
648
  end
621
649
  end
@@ -658,11 +686,7 @@ module SPARQL
658
686
  value = ENV['https_proxy']
659
687
  proxy_url = URI.parse(value) unless value.nil? || value.empty?
660
688
  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
689
+ klass = Net::HTTP::Persistent.new(name: self.class.to_s, proxy: proxy_url)
666
690
  klass.keep_alive = @options[:keep_alive] || 120
667
691
  klass.read_timeout = @options[:read_timeout] || 60
668
692
  klass
@@ -673,10 +697,16 @@ module SPARQL
673
697
  #
674
698
  # @param [String, #to_s] query
675
699
  # @param [Hash{String => String}] headers
700
+ # HTTP Request headers
701
+ #
702
+ # 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.
703
+ #
704
+ # Defaults `User-Agent` header, unless one is specified.
676
705
  # @yield [response]
677
706
  # @yieldparam [Net::HTTPResponse] response
678
707
  # @return [Net::HTTPResponse]
679
- # @see http://www.w3.org/TR/sparql11-protocol/#query-operation
708
+ # @raise [IOError] if connection is closed
709
+ # @see https://www.w3.org/TR/sparql11-protocol/#query-operation
680
710
  def request(query, headers = {}, &block)
681
711
  # Make sure an appropriate Accept header is present
682
712
  headers['Accept'] ||= if (query.respond_to?(:expects_statements?) ?
@@ -686,6 +716,7 @@ module SPARQL
686
716
  else
687
717
  RESULT_ALL
688
718
  end
719
+ headers['User-Agent'] ||= "Ruby SPARQL::Client/#{SPARQL::Client::VERSION}"
689
720
 
690
721
  request = send("make_#{request_method(query)}_request", query, headers)
691
722
 
@@ -693,6 +724,7 @@ module SPARQL
693
724
 
694
725
  pre_http_hook(request) if respond_to?(:pre_http_hook)
695
726
 
727
+ raise IOError, "Client has been closed" unless @http
696
728
  response = @http.request(::URI.parse(url.to_s), request)
697
729
 
698
730
  post_http_hook(response) if respond_to?(:post_http_hook)
@@ -701,8 +733,8 @@ module SPARQL
701
733
  if response.kind_of? Net::HTTPRedirection
702
734
  response = @http.request(::URI.parse(response['location']), request)
703
735
  else
704
- return block_given? ? block.call(response) : response
705
- end
736
+ return block_given? ? block.call(response) : response
737
+ end
706
738
  end
707
739
  raise ServerError, "Infinite redirect at #{url}. Redirected more than 10 times."
708
740
  end
@@ -722,10 +754,11 @@ module SPARQL
722
754
  # @param [String, #to_s] query
723
755
  # @param [Hash{String => String}] headers
724
756
  # @return [Net::HTTPRequest]
725
- # @see http://www.w3.org/TR/sparql11-protocol/#query-via-get
757
+ # @see https://www.w3.org/TR/sparql11-protocol/#query-via-get
726
758
  def make_get_request(query, headers = {})
727
759
  url = self.url.dup
728
- url.query_values = (url.query_values || {}).merge(:query => query.to_s)
760
+ url.query_values = (url.query_values || {}).merge(query: query.to_s)
761
+ set_url_default_graph url unless @options[:graph].nil?
729
762
  request = Net::HTTP::Get.new(url.request_uri, self.headers.merge(headers))
730
763
  request
731
764
  end
@@ -736,27 +769,60 @@ module SPARQL
736
769
  # @param [String, #to_s] query
737
770
  # @param [Hash{String => String}] headers
738
771
  # @return [Net::HTTPRequest]
739
- # @see http://www.w3.org/TR/sparql11-protocol/#query-via-post-direct
740
- # @see http://www.w3.org/TR/sparql11-protocol/#query-via-post-urlencoded
772
+ # @see https://www.w3.org/TR/sparql11-protocol/#query-via-post-direct
773
+ # @see https://www.w3.org/TR/sparql11-protocol/#query-via-post-urlencoded
741
774
  def make_post_request(query, headers = {})
742
775
  if @alt_endpoint.nil?
743
- endpoint = url.request_uri
776
+ url = self.url.dup
777
+ set_url_default_graph url unless @options[:graph].nil?
778
+ endpoint = url.request_uri
744
779
  else
745
780
  endpoint = @alt_endpoint
746
781
  end
782
+
747
783
  request = Net::HTTP::Post.new(endpoint, self.headers.merge(headers))
748
784
  case (self.options[:protocol] || DEFAULT_PROTOCOL).to_s
749
785
  when '1.1'
750
786
  request['Content-Type'] = 'application/sparql-' + (@op || :query).to_s
751
787
  request.body = query.to_s
752
788
  when '1.0'
753
- request.set_form_data((@op || :query) => query.to_s)
789
+ form_data = {(@op || :query) => query.to_s}
790
+ form_data.merge!(
791
+ {:'default-graph-uri' => @options[:graph]}
792
+ ) if !@options[:graph].nil? && (@op.eql? :query)
793
+ form_data.merge!(
794
+ {:'using-graph-uri' => @options[:graph]}
795
+ ) if !@options[:graph].nil? && (@op.eql? :update)
796
+ request.set_form_data(form_data)
754
797
  else
755
798
  raise ArgumentError, "unknown SPARQL protocol version: #{self.options[:protocol].inspect}"
756
799
  end
757
800
  request
758
801
  end
759
802
 
803
+ ##
804
+ # Setup url query parameter to use a specified default graph
805
+ #
806
+ # @see https://www.w3.org/TR/sparql11-protocol/#query-operation
807
+ # @see https://www.w3.org/TR/sparql11-protocol/#update-operation
808
+ def set_url_default_graph url
809
+ if @options[:graph].is_a? Array
810
+ graphs = @options[:graph].map {|graph|
811
+ CGI::escape(graph)
812
+ }
813
+ else
814
+ graphs = CGI::escape(@options[:graph])
815
+ end
816
+ case @op
817
+ when :query
818
+ url.query_values = (url.query_values || {})
819
+ .merge(:'default-graph-uri' => graphs)
820
+ when :update
821
+ url.query_values = (url.query_values || {})
822
+ .merge(:'using-graph-uri' => graphs)
823
+ end
824
+ end
825
+
760
826
  # 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.
761
827
  class QueryElement
762
828
  attr_reader :elements