sparql-client 0.0.0.pre → 0.0.1

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.
data/README CHANGED
@@ -0,0 +1,99 @@
1
+ SPARQL Client for RDF.rb
2
+ ========================
3
+
4
+ This is a pure-Ruby implementation of a [SPARQL][] client for [RDF.rb][].
5
+
6
+ * <http://github.com/bendiken/sparql-client>
7
+
8
+ Features
9
+ --------
10
+
11
+ * Queries SPARQL HTTP endpoints.
12
+
13
+ Examples
14
+ --------
15
+
16
+ require 'sparql/client'
17
+
18
+ sparql = SPARQL::Client.new('http://dbpedia.org/sparql')
19
+
20
+ ### Executing a boolean query
21
+
22
+ result = sparql.query('ASK WHERE { ?s ?p ?o }')
23
+
24
+ puts result.inspect #=> true or false
25
+
26
+ ### Executing a tuple query
27
+
28
+ result = sparql.query('SELECT * WHERE { ?s ?p ?o } LIMIT 10')
29
+
30
+ result.each do |bindings|
31
+ puts bindings.inspect
32
+ end
33
+
34
+ ### Executing a graph query
35
+
36
+ result = sparql.query('CONSTRUCT { ?s ?p ?o } WHERE { ?s ?p ?o } LIMIT 10')
37
+
38
+ result.each_statement do |statement|
39
+ puts statement.inspect
40
+ end
41
+
42
+ Documentation
43
+ -------------
44
+
45
+ <http://sparql.rubyforge.org/>
46
+
47
+ * {SPARQL::Client}
48
+
49
+ Dependencies
50
+ ------------
51
+
52
+ * [RDF.rb](http://rubygems.org/gems/rdf) (>= 0.1.5)
53
+ * [JSON](http://rubygems.org/gems/json_pure) (>= 1.2.3)
54
+
55
+ Installation
56
+ ------------
57
+
58
+ The recommended installation method is via [RubyGems](http://rubygems.org/).
59
+ To install the latest official release of the `SPARQL::Client` gem, do:
60
+
61
+ % [sudo] gem install sparql-client
62
+
63
+ Download
64
+ --------
65
+
66
+ To get a local working copy of the development repository, do:
67
+
68
+ % git clone git://github.com/bendiken/sparql-client.git
69
+
70
+ Alternatively, you can download the latest development version as a tarball
71
+ as follows:
72
+
73
+ % wget http://github.com/bendiken/sparql-client/tarball/master
74
+
75
+ Resources
76
+ ---------
77
+
78
+ * <http://sparql.rubyforge.org/>
79
+ * <http://github.com/bendiken/sparql-client>
80
+ * <http://rubygems.org/gems/sparql-client>
81
+ * <http://rubyforge.org/projects/sparql/>
82
+ * <http://raa.ruby-lang.org/project/sparql-client/>
83
+ * <http://www.ohloh.net/p/rdf>
84
+
85
+ Authors
86
+ -------
87
+
88
+ * [Arto Bendiken](mailto:arto.bendiken@gmail.com) - <http://ar.to/>
89
+ * [Ben Lavender](mailto:blavender@gmail.com) - <http://bhuga.net/>
90
+
91
+ License
92
+ -------
93
+
94
+ `SPARQL::Client` is free and unencumbered public domain software. For more
95
+ information, see <http://unlicense.org/> or the accompanying UNLICENSE file.
96
+
97
+ [RDF]: http://www.w3.org/RDF/
98
+ [SPARQL]: http://en.wikipedia.org/wiki/SPARQL
99
+ [RDF.rb]: http://rdf.rubyforge.org/
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.0.pre
1
+ 0.0.1
@@ -1,8 +1,201 @@
1
+ require 'net/http'
2
+ require 'rdf'
3
+ require 'rdf/ntriples'
1
4
  require 'sparql/version'
2
5
 
3
6
  module SPARQL
4
7
  ##
8
+ # A SPARQL client for RDF.rb.
5
9
  class Client
6
- # TODO
10
+ RESULT_BOOL = 'text/boolean'.freeze # Sesame-specific
11
+ RESULT_JSON = 'application/sparql-results+json'.freeze
12
+ RESULT_XML = 'application/sparql-results+xml'.freeze
13
+ ACCEPT_JSON = {'Accept' => RESULT_JSON}.freeze
14
+ ACCEPT_XML = {'Accept' => RESULT_XML}.freeze
15
+
16
+ attr_reader :url
17
+ attr_reader :options
18
+
19
+ ##
20
+ # @param [String, #to_s] url
21
+ # @param [Hash{Symbol => Object}] options
22
+ def initialize(url, options = {}, &block)
23
+ @url, @options = RDF::URI.new(url.to_s), options
24
+ @headers = {'Accept' => "#{RESULT_XML}, #{RESULT_JSON}, text/plain"}
25
+
26
+ if block_given?
27
+ case block.arity
28
+ when 1 then block.call(self)
29
+ else instance_eval(&block)
30
+ end
31
+ end
32
+ end
33
+
34
+ ##
35
+ # Executes a SPARQL query.
36
+ #
37
+ # @param [String, #to_s] url
38
+ # @param [Hash{Symbol => Object}] options
39
+ def query(query, options = {})
40
+ get(query.to_s) do |response|
41
+ case response
42
+ when Net::HTTPClientError
43
+ abort response.inspect # FIXME
44
+ when Net::HTTPServerError
45
+ abort response.inspect # FIXME
46
+ when Net::HTTPSuccess
47
+ parse_response(response)
48
+ end
49
+ end
50
+ end
51
+
52
+ ##
53
+ # @param [Net::HTTPSuccess] response
54
+ # @return [Object]
55
+ def parse_response(response)
56
+ case content_type = response.content_type
57
+ when RESULT_BOOL # Sesame-specific
58
+ response.body == 'true'
59
+ when RESULT_JSON
60
+ parse_json_bindings(response.body)
61
+ when RESULT_XML
62
+ parse_xml_bindings(response.body)
63
+ else
64
+ parse_rdf_serialization(response)
65
+ end
66
+ end
67
+
68
+ ##
69
+ # @param [String, Hash] json
70
+ # @return [Enumerable<RDF::Query::Solution>]
71
+ # @see http://www.w3.org/TR/rdf-sparql-json-res/#results
72
+ def parse_json_bindings(json)
73
+ require 'json' unless defined?(::JSON)
74
+ json = JSON.parse(json.to_s) unless json.is_a?(Hash)
75
+
76
+ case
77
+ when json['boolean']
78
+ json['boolean']
79
+ when json['results']
80
+ json['results']['bindings'].map do |row|
81
+ row = row.inject({}) do |cols, (name, value)|
82
+ cols.merge(name => parse_json_value(value))
83
+ end
84
+ RDF::Query::Solution.new(row)
85
+ end
86
+ end
87
+ end
88
+
89
+ ##
90
+ # @param [Hash{String => String}] value
91
+ # @return [RDF::Value]
92
+ # @see http://www.w3.org/TR/rdf-sparql-json-res/#variable-binding-results
93
+ def parse_json_value(value)
94
+ case value['type'].to_sym
95
+ when :bnode
96
+ @nodes ||= {}
97
+ @nodes[id = value['value']] ||= RDF::Node.new(id)
98
+ when :uri
99
+ RDF::URI.new(value['value'])
100
+ when :literal
101
+ RDF::Literal.new(value['value'], :language => value['xml:lang'])
102
+ when :'typed-literal'
103
+ RDF::Literal.new(value['value'], :datatype => value['datatype'])
104
+ else nil
105
+ end
106
+ end
107
+
108
+ ##
109
+ # @param [String, REXML::Element] xml
110
+ # @return [Enumerable<RDF::Query::Solution>]
111
+ # @see http://www.w3.org/TR/rdf-sparql-json-res/#results
112
+ def parse_xml_bindings(xml)
113
+ require 'rexml/document' unless defined?(::REXML::Document)
114
+ xml = REXML::Document.new(xml).root unless xml.is_a?(REXML::Element)
115
+
116
+ case
117
+ when boolean = xml.elements['boolean']
118
+ boolean.text == 'true'
119
+ when results = xml.elements['results']
120
+ results.elements.map do |result|
121
+ row = {}
122
+ result.elements.each do |binding|
123
+ name = binding.attributes['name'].to_sym
124
+ value = binding.select { |node| node.kind_of?(::REXML::Element) }.first
125
+ row[name] = parse_xml_value(value)
126
+ end
127
+ RDF::Query::Solution.new(row)
128
+ end
129
+ end
130
+ end
131
+
132
+ ##
133
+ # @param [REXML::Element] value
134
+ # @return [RDF::Value]
135
+ # @see http://www.w3.org/TR/rdf-sparql-json-res/#variable-binding-results
136
+ def parse_xml_value(value)
137
+ case value.name.to_sym
138
+ when :bnode
139
+ @nodes ||= {}
140
+ @nodes[id = value.text] ||= RDF::Node.new(id)
141
+ when :uri
142
+ RDF::URI.new(value.text)
143
+ when :literal
144
+ RDF::Literal.new(value.text, {
145
+ :language => value.attributes['xml:lang'],
146
+ :datatype => value.attributes['datatype'],
147
+ })
148
+ else nil
149
+ end
150
+ end
151
+
152
+ ##
153
+ # @param [Net::HTTPSuccess] response
154
+ # @return [RDF::Enumerable]
155
+ def parse_rdf_serialization(response)
156
+ if reader = RDF::Reader.for(:content_type => response.content_type)
157
+ reader.new(response.body)
158
+ end
159
+ end
160
+
161
+ ##
162
+ # Outputs a developer-friendly representation of this object to `stderr`.
163
+ #
164
+ # @return [void]
165
+ def inspect!
166
+ warn(inspect)
167
+ end
168
+
169
+ ##
170
+ # Returns a developer-friendly representation of this object.
171
+ #
172
+ # @return [String]
173
+ def inspect
174
+ sprintf("#<%s:%#0x(%s)>", self.class.name, __id__, url.to_s)
175
+ end
176
+
177
+ protected
178
+
179
+ ##
180
+ # Performs an HTTP GET request against the SPARQL endpoint.
181
+ #
182
+ # @param [String, #to_s] query
183
+ # @param [Hash{String => String}] headers
184
+ # @yield [response]
185
+ # @yieldparam [Net::HTTPResponse] response
186
+ # @return [Net::HTTPResponse]
187
+ def get(query, headers = {}, &block)
188
+ url = self.url.dup
189
+ url.query_values = {:query => query.to_s}
190
+
191
+ Net::HTTP.start(url.host, url.port) do |http|
192
+ response = http.get(url.path + "?#{url.query}", @headers.merge(headers))
193
+ if block_given?
194
+ block.call(response)
195
+ else
196
+ response
197
+ end
198
+ end
199
+ end
7
200
  end
8
201
  end
@@ -2,8 +2,8 @@ module SPARQL; class Client
2
2
  module VERSION
3
3
  MAJOR = 0
4
4
  MINOR = 0
5
- TINY = 0
6
- EXTRA = :pre
5
+ TINY = 1
6
+ EXTRA = nil
7
7
 
8
8
  STRING = [MAJOR, MINOR, TINY].join('.')
9
9
  STRING << ".#{EXTRA}" if EXTRA
metadata CHANGED
@@ -1,13 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sparql-client
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: true
4
+ prerelease: false
5
5
  segments:
6
6
  - 0
7
7
  - 0
8
- - 0
9
- - pre
10
- version: 0.0.0.pre
8
+ - 1
9
+ version: 0.0.1
11
10
  platform: ruby
12
11
  authors:
13
12
  - Arto Bendiken
@@ -125,13 +124,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
125
124
  version: 1.8.2
126
125
  required_rubygems_version: !ruby/object:Gem::Requirement
127
126
  requirements:
128
- - - ">"
127
+ - - ">="
129
128
  - !ruby/object:Gem::Version
130
129
  segments:
131
- - 1
132
- - 3
133
- - 1
134
- version: 1.3.1
130
+ - 0
131
+ version: "0"
135
132
  requirements: []
136
133
 
137
134
  rubyforge_project: sparql