sparql-client 0.0.0.pre → 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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