sparql 0.0.2 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +101 -7
- data/VERSION +1 -1
- data/bin/sparql +7 -2
- data/lib/rack/sparql.rb +38 -0
- data/lib/rack/sparql/conneg.rb +127 -0
- data/lib/sinatra/sparql.rb +116 -0
- data/lib/sinatra/sparql/extensions.rb +19 -0
- data/lib/sparql.rb +2 -3
- data/lib/sparql/algebra.rb +1 -1
- data/lib/sparql/algebra/expression.rb +7 -2
- data/lib/sparql/algebra/extensions.rb +13 -7
- data/lib/sparql/algebra/operator.rb +3 -3
- data/lib/sparql/algebra/operator/dataset.rb +14 -1
- data/lib/sparql/grammar/parser.rb +8 -3
- data/lib/sparql/results.rb +57 -9
- metadata +95 -36
data/README.markdown
CHANGED
@@ -1,20 +1,67 @@
|
|
1
1
|
# SPARQL for RDF.rb
|
2
2
|
|
3
|
-
This is a [Ruby][] implementation of
|
3
|
+
This is a [Ruby][] implementation of [SPARQL][] for [RDF.rb][].
|
4
4
|
|
5
5
|
## Features
|
6
6
|
|
7
7
|
* 100% free and unencumbered [public domain](http://unlicense.org/) software.
|
8
8
|
* [SPARQL 1.0][] query parsing and execution
|
9
|
-
* SPARQL results as [XML][SPARQL XML]
|
9
|
+
* SPARQL results as [XML][SPARQL XML], [JSON][SPARQL JSON] or HTML.
|
10
10
|
* SPARQL CONSTRUCT or DESCRIBE serialized based on Format, Extension of Mime Type
|
11
|
-
using available RDF Writers (see [Linked Data]
|
11
|
+
using available RDF Writers (see [Linked Data][])
|
12
12
|
* SPARQL Client for accessing remote SPARQL endpoints.
|
13
|
-
*
|
14
|
-
* Compatible with
|
13
|
+
* [Rack][] and [Sinatra][] middleware to perform [HTTP content negotiation][conneg] for result formats
|
14
|
+
* Compatible with any [Rack][] or [Sinatra][] application and any Rack-based framework.
|
15
|
+
* Helper method for describing [SPARQL Service Description][SSD]
|
16
|
+
* Compatible with Ruby 1.9.x.
|
15
17
|
* Compatible with older Ruby versions with the help of the [Backports][] gem.
|
16
18
|
* Supports Unicode query strings both on Ruby 1.8.x and 1.9.x.
|
17
19
|
|
20
|
+
## Description
|
21
|
+
|
22
|
+
The {SPARQL} gem implements [SPARQL 1.0 Query] and provides [Rack][] and [Sinatra][]
|
23
|
+
middleware to provide results using [HTTP Content Negotiation][conneg].
|
24
|
+
|
25
|
+
* {SPARQL::Grammar} implements a [SPARQL 1.0 Query] parser generating [SPARQL S-Expressions (SSE)][SSE].
|
26
|
+
* {SPARQL::Algebra} executes SSE against Any `RDF::Graph` or `RDF::Repository`, including
|
27
|
+
compliant [RDF.rb][] repository adaptors such as [RDF::DO][] and [RDF::Mongo][].
|
28
|
+
* {Rack::SPARQL} and {Sinatra::SPARQL} provide middleware components to format results
|
29
|
+
using an appropriate format based on [HTTP content negotiation][conneg].
|
30
|
+
|
31
|
+
### Middleware
|
32
|
+
|
33
|
+
`Rack::SPARQL` is a superset of [Rack::LinkedData][] to allow content negotiated results
|
34
|
+
to be returned any `RDF::Enumerable` or `RDF::Query::Solutions` compatible results.
|
35
|
+
You would typically return an instance of `RDF::Graph`, `RDF::Repository` or `RDF::Query::Solutions`
|
36
|
+
from your Rack application, and let the `Rack::SPARQL::ContentNegotiation` middleware
|
37
|
+
take care of serializing your response into whatever format the HTTP
|
38
|
+
client requested and understands.
|
39
|
+
|
40
|
+
`Sinatra::SPARQL` is a thin Sinatra-specific wrapper around the
|
41
|
+
{Rack::SPARQL} middleware, which implements SPARQL
|
42
|
+
content negotiation for Rack applications.
|
43
|
+
|
44
|
+
The middleware queries [RDF.rb][] for the MIME content types of known RDF
|
45
|
+
serialization formats, so it will work with whatever serialization plugins
|
46
|
+
that are currently available for RDF.rb. (At present, this includes support
|
47
|
+
for N-Triples, N-Quads, Turtle, RDF/XML, RDF/JSON, JSON-LD, RDFa, TriG and TriX.)
|
48
|
+
|
49
|
+
### Remote datasets
|
50
|
+
|
51
|
+
A SPARQL query containing `FROM` or `FROM NAMED` will load the referenced IRI unless the repository
|
52
|
+
already contains a context with that same IRI. This is performed using [RDF.rb][] `RDF::Util::File.open_file`
|
53
|
+
passing HTTP Accept headers for various available RDF formats. For best results, require [Linked Data][] to enable
|
54
|
+
a full set of RDF formats in the `GET` request. Also, consider overriding `RDF::Util::File.open_file` with
|
55
|
+
an implementation with support for HTTP Get headers (such as `Net::HTTP`).
|
56
|
+
|
57
|
+
### Result formats
|
58
|
+
|
59
|
+
{SPARQL.serialize_results} may be used on it's own, or in conjunction with {Rack::SPARQL} or {Sinatra::SPARQL}
|
60
|
+
to provide content-negotiated query results. For basic `SELECT` and `ASK` this includes HTML, XML and JSON formats.
|
61
|
+
`DESCRIBE` and `CONSTRUCT` create an `RDF::Graph`, which can be serialized through [HTTP Content Netogiation][conneg]
|
62
|
+
using available RDF writers. For best results, require [Linked Data][] to enable
|
63
|
+
a full set of RDF formats.
|
64
|
+
|
18
65
|
## Examples
|
19
66
|
|
20
67
|
require 'rubygems'
|
@@ -49,6 +96,42 @@ This is a [Ruby][] implementation of the [SPARQL][] algebra for [RDF.rb][].
|
|
49
96
|
sparql --default-graph etc/doap.ttl --sse etc/input.sse
|
50
97
|
sparql --sse -e "(dataset (<etc/doap.ttl>) (bgp (triple ?s ?p ?o))))"
|
51
98
|
|
99
|
+
### Adding SPARQL content negotiation to a Rails 3.x application
|
100
|
+
|
101
|
+
# config/application.rb
|
102
|
+
require 'rack/sparql'
|
103
|
+
|
104
|
+
class Application < Rails::Application
|
105
|
+
config.middleware.use Rack::SPARQL::ContentNegotiation
|
106
|
+
end
|
107
|
+
|
108
|
+
### Adding SPARQL content negotiation to a Rackup application
|
109
|
+
|
110
|
+
#!/usr/bin/env rackup
|
111
|
+
require 'rack/sparql'
|
112
|
+
|
113
|
+
repository = RDF::Repository.new do |graph|
|
114
|
+
graph << [RDF::Node.new, RDF::DC.title, "Hello, world!"]
|
115
|
+
end
|
116
|
+
results = SPARQL.execute("SELECT * WHERE { ?s ?p ?o }", repository)
|
117
|
+
|
118
|
+
use Rack::SPARQL::ContentNegotiation
|
119
|
+
run lambda { |env| [200, {}, results] }
|
120
|
+
|
121
|
+
### Adding SPARQL content negotiation to a classic Sinatra application
|
122
|
+
|
123
|
+
#!/usr/bin/env ruby -rubygems
|
124
|
+
require 'sinatra'
|
125
|
+
require 'sinatra/sparql'
|
126
|
+
|
127
|
+
repository = RDF::Repository.new do |graph|
|
128
|
+
graph << [RDF::Node.new, RDF::DC.title, "Hello, world!"]
|
129
|
+
end
|
130
|
+
|
131
|
+
get '/sparql' do
|
132
|
+
SPARQL.execute("SELECT * WHERE { ?s ?p ?o }", repository)
|
133
|
+
end
|
134
|
+
|
52
135
|
## Documentation
|
53
136
|
|
54
137
|
Full documentation available on [Rubydoc.info][SPARQL doc]
|
@@ -63,15 +146,19 @@ Full documentation available on [Rubydoc.info][SPARQL doc]
|
|
63
146
|
* {SPARQL::Grammar}
|
64
147
|
* {SPARQL::Grammar::Parser}
|
65
148
|
* {SPARQL::Grammar::Lexer}
|
149
|
+
* {Sinatra::SPARQL}
|
150
|
+
* {Rack::SPARQL}
|
151
|
+
* {Rack::SPARQL::ContentNegotiation}
|
66
152
|
|
67
153
|
## Dependencies
|
68
154
|
|
69
155
|
* [Ruby](http://ruby-lang.org/) (>= 1.9) or (>= 1.8.1 with [Backports][])
|
70
|
-
* [RDF.rb](http://rubygems.org/gems/rdf) (>= 0.3.
|
156
|
+
* [RDF.rb](http://rubygems.org/gems/rdf) (>= 0.3.5)
|
71
157
|
* [SPARQL::Client](https://rubygems.org/gems/sparql-client) (>= 0.0.11)
|
72
158
|
* [SXP](https://rubygems.org/gems/sxp) (>= 0.0.15)
|
73
159
|
* [Builder](https://rubygems.org/gems/builder) (>= 3.0.0)
|
74
160
|
* [JSON](https://rubygems.org/gems/json) (>= 1.5.1)
|
161
|
+
* Soft dependency on [Linked Data][]
|
75
162
|
|
76
163
|
## Installation
|
77
164
|
|
@@ -117,6 +204,9 @@ see <http://unlicense.org/> or the accompanying {file:UNLICENSE} file.
|
|
117
204
|
|
118
205
|
[Ruby]: http://ruby-lang.org/
|
119
206
|
[RDF]: http://www.w3.org/RDF/
|
207
|
+
[RDF::DO]: http://rubygems.org/gems/rdf-do
|
208
|
+
[RDF::Mongo]: http://rubygems.org/gems/rdf-mongo
|
209
|
+
[Rack::LinkedData]: http://rubygems.org/gems/rack-linkeddata
|
120
210
|
[YARD]: http://yardoc.org/
|
121
211
|
[YARD-GS]: http://rubydoc.info/docs/yard/file/docs/GettingStarted.md
|
122
212
|
[PDD]: http://lists.w3.org/Archives/Public/public-rdf-ruby/2010May/0013.html
|
@@ -131,8 +221,12 @@ see <http://unlicense.org/> or the accompanying {file:UNLICENSE} file.
|
|
131
221
|
[YARD-GS]: http://rubydoc.info/docs/yard/file/docs/GettingStarted.md
|
132
222
|
[PDD]: http://unlicense.org/#unlicensing-contributions
|
133
223
|
[Backports]: http://rubygems.org/gems/backports
|
224
|
+
[Linked Data]: http://rubygems.org/gems/linkeddata
|
134
225
|
[SPARQL doc]: http://rubydoc.info/github/gkellogg/sparql/frames
|
135
226
|
[SPARQL XML]: http://www.w3.org/TR/rdf-sparql-XMLres/
|
136
227
|
[SPARQL JSON]: http://www.w3.org/TR/rdf-sparql-json-res/
|
137
228
|
[SPARQL Protocol]: http://www.w3.org/TR/rdf-sparql-protocol/
|
138
|
-
[
|
229
|
+
[SSD]: http://www.w3.org/TR/sparql11-service-description/
|
230
|
+
[Rack]: http://rack.rubyforge.org/
|
231
|
+
[Sinatra]: http://www.sinatrarb.com/
|
232
|
+
[conneg]: http://en.wikipedia.org/wiki/Content_negotiation
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0
|
1
|
+
0.1.0
|
data/bin/sparql
CHANGED
@@ -2,7 +2,11 @@
|
|
2
2
|
require 'rubygems'
|
3
3
|
$:.unshift(File.expand_path(File.join(File.dirname(__FILE__), "..", 'lib')))
|
4
4
|
require 'sparql'
|
5
|
-
|
5
|
+
begin
|
6
|
+
require 'linkeddata'
|
7
|
+
rescue LoadError => e
|
8
|
+
require 'rdf/ntriples'
|
9
|
+
end
|
6
10
|
require 'getoptlong'
|
7
11
|
|
8
12
|
def run(input, options = {})
|
@@ -22,12 +26,13 @@ def run(input, options = {})
|
|
22
26
|
end
|
23
27
|
|
24
28
|
if options[:to_sse]
|
25
|
-
puts ("\nSSE:\n" + query.
|
29
|
+
puts ("\nSSE:\n" + query.to_sse)
|
26
30
|
else
|
27
31
|
res = query.execute(options[:graph])
|
28
32
|
puts res.inspect if options[:verbose]
|
29
33
|
puts case res
|
30
34
|
when RDF::Graph then res.dump(:ttl, :base_uri => query.base_uri, :prefixes => query.prefixes)
|
35
|
+
when RDF::Literal then res.inspect
|
31
36
|
else res.map {|s| s.bindings.map {|k,v| "#{k}: #{v}"}}.join("\n")
|
32
37
|
end
|
33
38
|
end
|
data/lib/rack/sparql.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'rack'
|
2
|
+
begin
|
3
|
+
require 'linkeddata'
|
4
|
+
rescue LoadError => e
|
5
|
+
require 'rdf/ntriples'
|
6
|
+
end
|
7
|
+
require 'sparql'
|
8
|
+
|
9
|
+
module Rack
|
10
|
+
module SPARQL
|
11
|
+
autoload :ContentNegotiation, 'rack/sparql/conneg'
|
12
|
+
|
13
|
+
##
|
14
|
+
# Registers all known RDF formats with Rack's MIME types registry.
|
15
|
+
#
|
16
|
+
# Registers both known file extensions and format symbols.
|
17
|
+
#
|
18
|
+
# @param [Hash{Symbol => Object}] options
|
19
|
+
# @option options [Boolean] :overwrite (false)
|
20
|
+
# @return [void]
|
21
|
+
def self.register_mime_types!(options = {})
|
22
|
+
if defined?(Rack::Mime::MIME_TYPES)
|
23
|
+
RDF::Format.each do |format|
|
24
|
+
if !Rack::Mime::MIME_TYPES.has_key?(file_ext = ".#{format.to_sym}") || options[:overwrite]
|
25
|
+
Rack::Mime::MIME_TYPES.merge!(file_ext => format.content_type.first)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
RDF::Format.file_extensions.each do |file_ext, formats|
|
29
|
+
if !Rack::Mime::MIME_TYPES.has_key?(file_ext = ".#{file_ext}") || options[:overwrite]
|
30
|
+
Rack::Mime::MIME_TYPES.merge!(file_ext => formats.first.content_type.first)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
Rack::SPARQL.register_mime_types!
|
@@ -0,0 +1,127 @@
|
|
1
|
+
require 'rack'
|
2
|
+
require 'sparql'
|
3
|
+
|
4
|
+
module Rack; module SPARQL
|
5
|
+
##
|
6
|
+
# Rack middleware for SPARQL content negotiation.
|
7
|
+
#
|
8
|
+
# Uses HTTP Content Negotiation to find an appropriate RDF
|
9
|
+
# format to serialize any result with a body being `RDF::Enumerable`.
|
10
|
+
#
|
11
|
+
# Override content negotiation by setting the :format option to
|
12
|
+
# {#initialize}.
|
13
|
+
#
|
14
|
+
# This endpoint also serves the fuction of Rack::LinkedData, as it will serialize
|
15
|
+
# SPARQL results, which may be RDF Graphs
|
16
|
+
class ContentNegotiation
|
17
|
+
VARY = {'Vary' => 'Accept'}.freeze
|
18
|
+
|
19
|
+
# @return [#call]
|
20
|
+
attr_reader :app
|
21
|
+
|
22
|
+
# @return [Hash{Symbol => Object}]
|
23
|
+
attr_reader :options
|
24
|
+
|
25
|
+
##
|
26
|
+
# @param [#call] app
|
27
|
+
# @param [Hash{Symbol => Object}] options
|
28
|
+
# Other options passed to writer.
|
29
|
+
# @option options [RDF::Format, #to_sym] :format Specific RDF writer format to use
|
30
|
+
def initialize(app, options = {})
|
31
|
+
@app, @options = app, options
|
32
|
+
end
|
33
|
+
|
34
|
+
##
|
35
|
+
# Handles a Rack protocol request.
|
36
|
+
#
|
37
|
+
# If result is `RDF::Literal::Boolean`, `RDF::Query::Results`, or `RDF::Enumerable`
|
38
|
+
# The result is serialized using {SPARQL::Results}
|
39
|
+
#
|
40
|
+
# @param [Hash{String => String}] env
|
41
|
+
# @return [Array(Integer, Hash, #each)]
|
42
|
+
# @see http://rack.rubyforge.org/doc/SPEC.html
|
43
|
+
def call(env)
|
44
|
+
response = app.call(env)
|
45
|
+
case response[2] # the body
|
46
|
+
when RDF::Enumerable, RDF::Query::Solutions, RDF::Literal::Boolean
|
47
|
+
serialize(env, *response)
|
48
|
+
else response
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
##
|
53
|
+
# Serializes a SPARQL query result into a Rack protocol
|
54
|
+
# response using HTTP content negotiation rules or a specified Content-Type.
|
55
|
+
#
|
56
|
+
# @param [Hash{String => String}] env
|
57
|
+
# @param [Integer] status
|
58
|
+
# @param [Hash{String => Object}] headers
|
59
|
+
# @param [RDF::Enumerable] body
|
60
|
+
# @return [Array(Integer, Hash, #each)]
|
61
|
+
# @raise [RDF::WriterError] when no results are generated
|
62
|
+
def serialize(env, status, headers, body)
|
63
|
+
begin
|
64
|
+
serialize_options = {}
|
65
|
+
serialize_options[:content_types] = parse_accept_header(env['HTTP_ACCEPT']) if env.has_key?('HTTP_ACCEPT')
|
66
|
+
serialize_options.merge!(@options)
|
67
|
+
results = ::SPARQL.serialize_results(body, serialize_options)
|
68
|
+
raise RDF::WriterError, "can't serialize results" unless results
|
69
|
+
headers = headers.merge(VARY).merge('Content-Type' => results.content_type) # FIXME: don't overwrite existing Vary headers
|
70
|
+
[status, headers, [results]]
|
71
|
+
rescue RDF::WriterError => e
|
72
|
+
not_acceptable(e.message)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
protected
|
77
|
+
|
78
|
+
##
|
79
|
+
# Parses an HTTP `Accept` header, returning an array of MIME content
|
80
|
+
# types ordered by the precedence rules defined in HTTP/1.1 Section 14.1.
|
81
|
+
#
|
82
|
+
# @param [String, #to_s] header
|
83
|
+
# @return [Array<String>]
|
84
|
+
# @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1
|
85
|
+
def parse_accept_header(header)
|
86
|
+
entries = header.to_s.split(',')
|
87
|
+
entries.map { |e| accept_entry(e) }.sort_by(&:last).map(&:first)
|
88
|
+
end
|
89
|
+
|
90
|
+
def accept_entry(entry)
|
91
|
+
type, *options = entry.delete(' ').split(';')
|
92
|
+
quality = 0 # we sort smallest first
|
93
|
+
options.delete_if { |e| quality = 1 - e[2..-1].to_f if e.start_with? 'q=' }
|
94
|
+
[type, [quality, type.count('*'), 1 - options.size]]
|
95
|
+
end
|
96
|
+
|
97
|
+
##
|
98
|
+
# Outputs an HTTP `406 Not Acceptable` response.
|
99
|
+
#
|
100
|
+
# @param [String, #to_s] message
|
101
|
+
# @return [Array(Integer, Hash, #each)]
|
102
|
+
def not_acceptable(message = nil)
|
103
|
+
http_error(406, message, VARY)
|
104
|
+
end
|
105
|
+
|
106
|
+
##
|
107
|
+
# Outputs an HTTP `4xx` or `5xx` response.
|
108
|
+
#
|
109
|
+
# @param [Integer, #to_i] code
|
110
|
+
# @param [String, #to_s] message
|
111
|
+
# @param [Hash{String => String}] headers
|
112
|
+
# @return [Array(Integer, Hash, #each)]
|
113
|
+
def http_error(code, message = nil, headers = {})
|
114
|
+
message = http_status(code) + (message.nil? ? "\n" : " (#{message})\n")
|
115
|
+
[code, {'Content-Type' => 'text/plain; charset=utf-8'}.merge(headers), [message]]
|
116
|
+
end
|
117
|
+
|
118
|
+
##
|
119
|
+
# Returns the standard HTTP status message for the given status `code`.
|
120
|
+
#
|
121
|
+
# @param [Integer, #to_i] code
|
122
|
+
# @return [String]
|
123
|
+
def http_status(code)
|
124
|
+
[code, Rack::Utils::HTTP_STATUS_CODES[code]].join(' ')
|
125
|
+
end
|
126
|
+
end # class ContentNegotiation
|
127
|
+
end; end # module Rack::SPARQL
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
require 'sinatra/sparql/extensions'
|
3
|
+
require 'rack/sparql'
|
4
|
+
|
5
|
+
module Sinatra
|
6
|
+
##
|
7
|
+
# The Sinatra::SPARQL module adds Rack::SPARQL} middleware support for responding to
|
8
|
+
# SPARQL requests. It is the responsibility of the application to manage
|
9
|
+
# the SPARQL endpoint and perform the query. The query results are then sent
|
10
|
+
# as the response body. {Rack::SPARQL} middleware uses content negotiation
|
11
|
+
# to format the results appropriately.
|
12
|
+
# @see http://www.sinatrarb.com/extensions.html
|
13
|
+
module SPARQL
|
14
|
+
##
|
15
|
+
# Helper methods.
|
16
|
+
module Helpers
|
17
|
+
##
|
18
|
+
# This is useful when a GET request is performed against a SPARQL endpoint and
|
19
|
+
# no query is performed. Provide a set of datasets, including a default dataset
|
20
|
+
# along with optional triple count, dump location, and description of the dataset.
|
21
|
+
#
|
22
|
+
# The results are serialized using content negotiation. For text/html, authors
|
23
|
+
# should generate RDFa for the serivce description directly.
|
24
|
+
#
|
25
|
+
# @param [Hash{Symbol => Object}] options
|
26
|
+
# @option options [RDF::Enumerable] :repository
|
27
|
+
# An enumerable, typically a type of `RDF::Repository` containing the dataset used for
|
28
|
+
# queries against the service.
|
29
|
+
# @option options [RDF::URI, #to_s] :endpoint
|
30
|
+
# URI of the service endpoint, defaults to "/sparql" in the current realm.
|
31
|
+
# @return [RDF::Graph]
|
32
|
+
#
|
33
|
+
# @see http://www.w3.org/TR/sparql11-service-description
|
34
|
+
# @see http://www.w3.org/TR/void/
|
35
|
+
def service_description(options = {})
|
36
|
+
repository = options[:repository]
|
37
|
+
|
38
|
+
g = RDF::Graph.new
|
39
|
+
sd = RDF::URI("http://www.w3.org/ns/sparql-service-description#")
|
40
|
+
void = RDF::URI("http://rdfs.org/ns/void#")
|
41
|
+
|
42
|
+
node = RDF::Node.new
|
43
|
+
g << [node, RDF.type, sd.join("#Service")]
|
44
|
+
g << [node, sd.join("#endpoint"), options[:endpoint] || url("/sparql")]
|
45
|
+
g << [node, sd.join("#supportedLanguage"), sd.join("#SPARQL10Query")]
|
46
|
+
|
47
|
+
# Result formats, both RDF and SPARQL Results.
|
48
|
+
# FIXME: We should get this from the avaliable serializers
|
49
|
+
g << [node, sd.join("#resultFormat"), RDF::URI("http://www.w3.org/ns/formats/RDF_XML")]
|
50
|
+
g << [node, sd.join("#resultFormat"), RDF::URI("http://www.w3.org/ns/formats/Turtle")]
|
51
|
+
g << [node, sd.join("#resultFormat"), RDF::URI("http://www.w3.org/ns/formats/RDFa")]
|
52
|
+
g << [node, sd.join("#resultFormat"), RDF::URI("http://www.w3.org/ns/formats/N-Triples")]
|
53
|
+
g << [node, sd.join("#resultFormat"), RDF::URI("http://www.w3.org/ns/formats/SPARQL_RESULTS_XML")]
|
54
|
+
g << [node, sd.join("#resultFormat"), RDF::URI("http://www.w3.org/ns/formats/SPARQL_RESULTS_JSON")]
|
55
|
+
|
56
|
+
# Features
|
57
|
+
g << [node, sd.join("#feature"), sd.join("#DereferencesURIs")]
|
58
|
+
|
59
|
+
# Datasets
|
60
|
+
ds = RDF::Node.new
|
61
|
+
g << [node, sd.join("#defaultDataset"), ds]
|
62
|
+
g << [ds, RDF.type, sd.join("#Dataset")]
|
63
|
+
|
64
|
+
# Contexts
|
65
|
+
if repository.is_a?(RDF::Enumerable)
|
66
|
+
contexts = {}
|
67
|
+
repository.each do |statement|
|
68
|
+
contexts[statement.context] ||= 0
|
69
|
+
contexts[statement.context] += 1
|
70
|
+
end
|
71
|
+
|
72
|
+
contexts.each do |name, count|
|
73
|
+
bn = RDF::Node.new
|
74
|
+
if name
|
75
|
+
# Add named contexts as namedGraphs
|
76
|
+
g << [ds, sd.join("#namedGraph"), bn]
|
77
|
+
g << [bn, RDF.type, sd.join("#NamedGraph")]
|
78
|
+
g << [bn, sd.join("#name"), name]
|
79
|
+
graph = RDF::Node.new
|
80
|
+
g << [bn, sd.join("#graph"), graph]
|
81
|
+
bn = graph
|
82
|
+
else
|
83
|
+
# Default graph
|
84
|
+
g << [ds, sd.join("#defaultGraph"), bn]
|
85
|
+
g << [bn, RDF.type, sd.join("#Graph")]
|
86
|
+
end
|
87
|
+
g << [bn, void.join("#triples"), count]
|
88
|
+
end
|
89
|
+
end
|
90
|
+
g
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
##
|
95
|
+
# * Registers Rack::SPARQL::ContentNegotiation
|
96
|
+
# * adds helpers
|
97
|
+
# * includes SPARQL, RDF and LinkedData
|
98
|
+
# * defines `sparql_options`, which are passed to the Rack middleware
|
99
|
+
# available as `settings.sparql_options` and as options within
|
100
|
+
# the {Rack::SPARQL} middleware.
|
101
|
+
#
|
102
|
+
# @param [Sinatra::Base] app
|
103
|
+
# @return [void]
|
104
|
+
def self.registered(app)
|
105
|
+
options = {}
|
106
|
+
app.set :sparql_options, options
|
107
|
+
app.use(Rack::SPARQL::ContentNegotiation, options)
|
108
|
+
app.helpers(Sinatra::SPARQL::Helpers)
|
109
|
+
app.send(:include, ::SPARQL)
|
110
|
+
app.send(:include, ::RDF)
|
111
|
+
app.send(:include, ::LinkedData)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
Sinatra.register(Sinatra::SPARQL)
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# Patch Sinatra::Response#finish to not calculate Content-Length unless
|
2
|
+
# all members of an array are strings
|
3
|
+
class Sinatra::Response
|
4
|
+
def finish
|
5
|
+
if status.to_i / 100 == 1
|
6
|
+
headers.delete "Content-Length"
|
7
|
+
headers.delete "Content-Type"
|
8
|
+
elsif RDF::Query::Solutions === body
|
9
|
+
# Don't calculate content-length here
|
10
|
+
elsif Array === body and not [204, 304].include?(status.to_i)
|
11
|
+
headers["Content-Length"] = body.inject(0) { |l, p| l + Rack::Utils.bytesize(p) }.to_s
|
12
|
+
end
|
13
|
+
|
14
|
+
# Rack::Response#finish sometimes returns self as response body. We don't want that.
|
15
|
+
status, headers, result = super
|
16
|
+
result = body if result == self
|
17
|
+
[status, headers, result]
|
18
|
+
end
|
19
|
+
end
|
data/lib/sparql.rb
CHANGED
@@ -44,12 +44,11 @@ module SPARQL
|
|
44
44
|
# presumed to be existant in `queryable` or are loaded into `queryable` depending
|
45
45
|
# on the presense and value of the :load_datasets option.
|
46
46
|
#
|
47
|
-
# Attempting to load into an immutable `queryable` will result in a
|
47
|
+
# Attempting to load into an immutable `queryable` will result in a TypeError.
|
48
48
|
#
|
49
49
|
# @example
|
50
50
|
# repository = RDF::Repository.new
|
51
51
|
# results = SPARQL.execute("SELECT * WHERE { ?s ?p ?o }", repository)
|
52
|
-
# result = parser.parse
|
53
52
|
#
|
54
53
|
# @param [IO, StringIO, String, #to_s] query
|
55
54
|
# @param [Hash{Symbol => Object}] options
|
@@ -80,7 +79,7 @@ module SPARQL
|
|
80
79
|
solutions = query.execute(queryable)
|
81
80
|
rescue SPARQL::Grammar::Parser::Error => e
|
82
81
|
raise MalformedQuery, e.message
|
83
|
-
rescue
|
82
|
+
rescue TypeError => e
|
84
83
|
raise QueryRequestRefused, e.message
|
85
84
|
end
|
86
85
|
|
data/lib/sparql/algebra.rb
CHANGED
@@ -189,7 +189,7 @@ module SPARQL
|
|
189
189
|
# Some very simple optimizations are currently implemented for `FILTER`
|
190
190
|
# expressions. Use the following to obtain optimized SSE forms:
|
191
191
|
#
|
192
|
-
# Expression.parse(sse).optimize.
|
192
|
+
# Expression.parse(sse).optimize.to_sxp_bin
|
193
193
|
#
|
194
194
|
# ## Constant comparison folding
|
195
195
|
#
|
@@ -239,7 +239,7 @@ module SPARQL; module Algebra
|
|
239
239
|
#
|
240
240
|
# @return [Array] `self`
|
241
241
|
# @see http://openjena.org/wiki/SSE
|
242
|
-
def
|
242
|
+
def to_sxp_bin
|
243
243
|
self
|
244
244
|
end
|
245
245
|
|
@@ -274,7 +274,12 @@ module SPARQL; module Algebra
|
|
274
274
|
message = args.join(": ")
|
275
275
|
message = message + yield if block_given?
|
276
276
|
depth = options[:depth] || 0
|
277
|
-
|
277
|
+
case options[:debug]
|
278
|
+
when Array
|
279
|
+
options[:debug] << "#{' ' * depth}#{message}"
|
280
|
+
else
|
281
|
+
$stderr.puts("#{' ' * depth}#{message}")
|
282
|
+
end
|
278
283
|
end
|
279
284
|
|
280
285
|
def debug(*args, &block)
|
@@ -4,12 +4,18 @@ require 'json'
|
|
4
4
|
# Extensions for Ruby's `Object` class.
|
5
5
|
class Object
|
6
6
|
##
|
7
|
-
# Returns the SXP representation of this object, defaults to `self'.
|
7
|
+
# Returns the SXP binary representation of this object, defaults to `self'.
|
8
8
|
#
|
9
9
|
# @return [String]
|
10
|
-
def
|
10
|
+
def to_sxp_bin
|
11
11
|
self
|
12
12
|
end
|
13
|
+
|
14
|
+
##
|
15
|
+
# Make sure the object is in SXP form and transform it to a string form
|
16
|
+
def to_sse
|
17
|
+
self.to_sxp_bin.to_sxp
|
18
|
+
end
|
13
19
|
end
|
14
20
|
|
15
21
|
##
|
@@ -19,8 +25,8 @@ class Array
|
|
19
25
|
# Returns the SXP representation of this object, defaults to `self'.
|
20
26
|
#
|
21
27
|
# @return [String]
|
22
|
-
def
|
23
|
-
map {|x| x.
|
28
|
+
def to_sxp_bin
|
29
|
+
map {|x| x.to_sxp_bin}
|
24
30
|
end
|
25
31
|
|
26
32
|
##
|
@@ -101,8 +107,8 @@ class RDF::Query
|
|
101
107
|
# If Query is named, it's treated as a GroupGraphPattern, otherwise, a BGP
|
102
108
|
#
|
103
109
|
# @return [Array]
|
104
|
-
def
|
105
|
-
res = [:bgp] + patterns.map(&:
|
110
|
+
def to_sxp_bin
|
111
|
+
res = [:bgp] + patterns.map(&:to_sxp_bin)
|
106
112
|
(context ? [:graph, context, res] : res)
|
107
113
|
end
|
108
114
|
end
|
@@ -110,7 +116,7 @@ end
|
|
110
116
|
class RDF::Query::Pattern
|
111
117
|
# Transform Query Pattern into an SXP
|
112
118
|
# @return [Array]
|
113
|
-
def
|
119
|
+
def to_sxp_bin
|
114
120
|
[:triple, subject, predicate, object]
|
115
121
|
end
|
116
122
|
end
|
@@ -323,9 +323,9 @@ module SPARQL; module Algebra
|
|
323
323
|
#
|
324
324
|
# @return [Array]
|
325
325
|
# @see http://openjena.org/wiki/SSE
|
326
|
-
def
|
326
|
+
def to_sxp_bin
|
327
327
|
operator = [self.class.const_get(:NAME)].flatten.first
|
328
|
-
[operator, *(operands || []).map(&:
|
328
|
+
[operator, *(operands || []).map(&:to_sxp_bin)]
|
329
329
|
end
|
330
330
|
|
331
331
|
##
|
@@ -340,7 +340,7 @@ module SPARQL; module Algebra
|
|
340
340
|
end
|
341
341
|
require 'sparql/algebra/sxp_extensions'
|
342
342
|
|
343
|
-
|
343
|
+
to_sxp_bin.to_sxp
|
344
344
|
end
|
345
345
|
|
346
346
|
##
|
@@ -1,3 +1,9 @@
|
|
1
|
+
begin
|
2
|
+
require 'linkeddata'
|
3
|
+
rescue LoadError => e
|
4
|
+
require 'rdf/ntriples'
|
5
|
+
end
|
6
|
+
|
1
7
|
module SPARQL; module Algebra
|
2
8
|
class Operator
|
3
9
|
##
|
@@ -17,6 +23,11 @@ module SPARQL; module Algebra
|
|
17
23
|
include Query
|
18
24
|
|
19
25
|
NAME = [:dataset]
|
26
|
+
# Selected accept headers, from those available
|
27
|
+
ACCEPTS = (%w(text/turtle application/rdf+xml;q=0.8 text/plain;q=0.4).
|
28
|
+
select do |content_type|
|
29
|
+
RDF::Format.content_types.include?(content_type.split(';').first)
|
30
|
+
end << ' */*;q=0.1').join(', ').freeze
|
20
31
|
|
21
32
|
##
|
22
33
|
# Executes this query on the given `queryable` graph or repository.
|
@@ -35,7 +46,9 @@ module SPARQL; module Algebra
|
|
35
46
|
def execute(queryable, options = {})
|
36
47
|
debug(options) {"Dataset"}
|
37
48
|
operand(0).each do |ds|
|
38
|
-
load_opts = {
|
49
|
+
load_opts = {
|
50
|
+
:headers => {"Accept" => ACCEPTS}
|
51
|
+
}
|
39
52
|
case ds
|
40
53
|
when Array
|
41
54
|
# Format is (named <uri>), only need the URI part
|
@@ -95,7 +95,7 @@ module SPARQL; module Grammar
|
|
95
95
|
end
|
96
96
|
|
97
97
|
# @return [String]
|
98
|
-
def
|
98
|
+
def to_sxp_bin
|
99
99
|
@result
|
100
100
|
end
|
101
101
|
|
@@ -260,7 +260,7 @@ module SPARQL; module Grammar
|
|
260
260
|
#
|
261
261
|
# @return [HRDF::URI]
|
262
262
|
def base_uri
|
263
|
-
@options[:base_uri]
|
263
|
+
RDF::URI(@options[:base_uri])
|
264
264
|
end
|
265
265
|
|
266
266
|
##
|
@@ -1089,7 +1089,12 @@ module SPARQL; module Grammar
|
|
1089
1089
|
message = args.join(": ")
|
1090
1090
|
message = message + yield if block_given?
|
1091
1091
|
depth = options[:depth] || @productions.length
|
1092
|
-
|
1092
|
+
case options[:debug]
|
1093
|
+
when Array
|
1094
|
+
options[:debug] << "[#{@lineno}]#{' ' * depth}#{message}"
|
1095
|
+
else
|
1096
|
+
$stderr.puts("[#{@lineno}]#{' ' * depth}#{message}")
|
1097
|
+
end
|
1093
1098
|
end
|
1094
1099
|
|
1095
1100
|
# [1] Query ::= Prologue ( SelectQuery | ConstructQuery | DescribeQuery | AskQuery )
|
data/lib/sparql/results.rb
CHANGED
@@ -118,22 +118,39 @@ module SPARQL
|
|
118
118
|
# @param [RDF::Query::Solutions, RDF::Queryable, Boolean] solutions
|
119
119
|
# Solutions as either a solution set, a Queryable object (such as a graph) or a Boolean value
|
120
120
|
# @param [Hash{Symbol => Object}] options
|
121
|
-
# @option options [:format
|
121
|
+
# @option options [#to_sym] :format
|
122
122
|
# Format of results, one of :html, :json or :xml.
|
123
123
|
# May also be an RDF::Writer format to serialize DESCRIBE or CONSTRUCT results
|
124
|
-
# @option options [:content_type
|
124
|
+
# @option options [String] :content_type
|
125
125
|
# Format of results, one of 'application/sparql-results+json' or 'application/sparql-results+xml'
|
126
126
|
# May also be an RDF::Writer content_type to serialize DESCRIBE or CONSTRUCT results
|
127
|
+
# @option options [Array<String>] :content_types
|
128
|
+
# Similar to :content_type, but takes an ordered array of appropriate content types,
|
129
|
+
# and serializes using the first appropriate type, including wild-cards.
|
127
130
|
# @return [String]
|
128
131
|
# String with serialized results and #content_type
|
132
|
+
# @raise [RDF::WriterError] when inappropriate formatting options are used
|
129
133
|
def serialize_results(solutions, options = {})
|
130
|
-
format = options[:format]
|
131
|
-
content_type = options[:content_type]
|
134
|
+
format = options[:format].to_sym if options[:format]
|
135
|
+
content_type = options[:content_type].to_s.split(';').first
|
136
|
+
content_types = options[:content_types] || ['*/*']
|
132
137
|
format ||= RDF::Query::Solutions::MIME_TYPES.invert[content_type] if content_type
|
133
138
|
|
139
|
+
if !format && !content_type
|
140
|
+
case solutions
|
141
|
+
when RDF::Queryable
|
142
|
+
content_type = first_content_type(content_types, RDF::Format.content_types.keys) || 'text/plain'
|
143
|
+
format = RDF::Writer.for(:content_type => content_type).to_sym
|
144
|
+
else
|
145
|
+
content_type = first_content_type(content_types, RDF::Query::Solutions::MIME_TYPES.values) || 'application/sparql-results+xml'
|
146
|
+
format = RDF::Query::Solutions::MIME_TYPES.invert[content_type]
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
134
150
|
serialization = case solutions
|
135
|
-
when TrueClass, FalseClass
|
136
|
-
|
151
|
+
when TrueClass, FalseClass, RDF::Literal::TRUE, RDF::Literal::FALSE
|
152
|
+
solutions = solutions.object if solutions.is_a?(RDF::Literal)
|
153
|
+
case format
|
137
154
|
when :json
|
138
155
|
require 'json' unless defined?(::JSON)
|
139
156
|
{:boolean => solutions}.to_json
|
@@ -149,18 +166,29 @@ module SPARQL
|
|
149
166
|
content_type = "text/html"
|
150
167
|
xml = ::Builder::XmlMarkup.new(:indent => 2)
|
151
168
|
xml.div(solutions.to_s, :class => "sparql")
|
169
|
+
else
|
170
|
+
raise RDF::WriterError, "Unknown format #{(format || content_type).inspect} for #{solutions.class}"
|
152
171
|
end
|
153
172
|
when RDF::Queryable
|
173
|
+
begin
|
174
|
+
require 'linkeddata'
|
175
|
+
rescue LoadError => e
|
176
|
+
require 'rdf/ntriples'
|
177
|
+
end
|
154
178
|
fmt = RDF::Format.for(format ? format.to_sym : {:content_type => content_type})
|
155
179
|
fmt ||= RDF::NTriples::Format
|
156
180
|
format ||= fmt.to_sym
|
157
|
-
content_type ||= fmt.
|
158
|
-
|
181
|
+
content_type ||= fmt.content_type.first
|
182
|
+
results = solutions.dump(format, options)
|
183
|
+
raise RDF::WriterError, "Unknown format #{fmt.inspect} for #{solutions.class}" unless results
|
184
|
+
results
|
159
185
|
when RDF::Query::Solutions
|
160
|
-
case format
|
186
|
+
case format
|
161
187
|
when :json then solutions.to_json
|
162
188
|
when :xml then solutions.to_xml
|
163
189
|
when :html then solutions.to_html
|
190
|
+
else
|
191
|
+
raise RDF::WriterError, "Unknown format #{(format || content_type).inspect} for #{solutions.class}"
|
164
192
|
end
|
165
193
|
end
|
166
194
|
|
@@ -184,6 +212,26 @@ module SPARQL
|
|
184
212
|
</html>
|
185
213
|
).freeze
|
186
214
|
|
215
|
+
##
|
216
|
+
# Find a content_type from a list using an ordered list of acceptable content types
|
217
|
+
# using wildcard matching
|
218
|
+
#
|
219
|
+
# @param [Array<String>] acceptable
|
220
|
+
# @param [Array<String>] available
|
221
|
+
# @return [String]
|
222
|
+
#
|
223
|
+
# @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1
|
224
|
+
def first_content_type(acceptable, available)
|
225
|
+
return acceptable.first if available.empty?
|
226
|
+
available.flatten!
|
227
|
+
acceptable.each do |pattern|
|
228
|
+
type = available.detect { |t| File.fnmatch(pattern, t) }
|
229
|
+
return type if type
|
230
|
+
end
|
231
|
+
nil
|
232
|
+
end
|
233
|
+
module_function :first_content_type
|
234
|
+
|
187
235
|
##
|
188
236
|
# Serialize error results
|
189
237
|
#
|
metadata
CHANGED
@@ -1,33 +1,32 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sparql
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Gregg Kellogg
|
9
9
|
- Arto Bendiken
|
10
|
-
- Ben Levendar
|
11
10
|
- Pius Uzamere
|
12
11
|
autorequire:
|
13
12
|
bindir: bin
|
14
13
|
cert_chain: []
|
15
|
-
date:
|
14
|
+
date: 2012-01-31 00:00:00.000000000Z
|
16
15
|
dependencies:
|
17
16
|
- !ruby/object:Gem::Dependency
|
18
17
|
name: rdf
|
19
|
-
requirement: &
|
18
|
+
requirement: &2165243520 !ruby/object:Gem::Requirement
|
20
19
|
none: false
|
21
20
|
requirements:
|
22
21
|
- - ! '>='
|
23
22
|
- !ruby/object:Gem::Version
|
24
|
-
version: 0.3.
|
23
|
+
version: 0.3.5
|
25
24
|
type: :runtime
|
26
25
|
prerelease: false
|
27
|
-
version_requirements: *
|
26
|
+
version_requirements: *2165243520
|
28
27
|
- !ruby/object:Gem::Dependency
|
29
28
|
name: builder
|
30
|
-
requirement: &
|
29
|
+
requirement: &2165242720 !ruby/object:Gem::Requirement
|
31
30
|
none: false
|
32
31
|
requirements:
|
33
32
|
- - ! '>='
|
@@ -35,10 +34,10 @@ dependencies:
|
|
35
34
|
version: 3.0.0
|
36
35
|
type: :runtime
|
37
36
|
prerelease: false
|
38
|
-
version_requirements: *
|
37
|
+
version_requirements: *2165242720
|
39
38
|
- !ruby/object:Gem::Dependency
|
40
39
|
name: json
|
41
|
-
requirement: &
|
40
|
+
requirement: &2165241340 !ruby/object:Gem::Requirement
|
42
41
|
none: false
|
43
42
|
requirements:
|
44
43
|
- - ! '>='
|
@@ -46,10 +45,10 @@ dependencies:
|
|
46
45
|
version: 1.5.1
|
47
46
|
type: :runtime
|
48
47
|
prerelease: false
|
49
|
-
version_requirements: *
|
48
|
+
version_requirements: *2165241340
|
50
49
|
- !ruby/object:Gem::Dependency
|
51
50
|
name: sxp
|
52
|
-
requirement: &
|
51
|
+
requirement: &2165240320 !ruby/object:Gem::Requirement
|
53
52
|
none: false
|
54
53
|
requirements:
|
55
54
|
- - ! '>='
|
@@ -57,43 +56,87 @@ dependencies:
|
|
57
56
|
version: 0.0.14
|
58
57
|
type: :runtime
|
59
58
|
prerelease: false
|
60
|
-
version_requirements: *
|
59
|
+
version_requirements: *2165240320
|
61
60
|
- !ruby/object:Gem::Dependency
|
62
61
|
name: sparql-client
|
63
|
-
requirement: &
|
62
|
+
requirement: &2165237360 !ruby/object:Gem::Requirement
|
64
63
|
none: false
|
65
64
|
requirements:
|
66
65
|
- - ! '>='
|
67
66
|
- !ruby/object:Gem::Version
|
68
|
-
version: 0.0.
|
67
|
+
version: 0.0.11
|
69
68
|
type: :runtime
|
70
69
|
prerelease: false
|
71
|
-
version_requirements: *
|
70
|
+
version_requirements: *2165237360
|
72
71
|
- !ruby/object:Gem::Dependency
|
73
72
|
name: rdf-xsd
|
74
|
-
requirement: &
|
73
|
+
requirement: &2165236080 !ruby/object:Gem::Requirement
|
75
74
|
none: false
|
76
75
|
requirements:
|
77
76
|
- - ! '>='
|
78
77
|
- !ruby/object:Gem::Version
|
79
|
-
version: 0.3.
|
78
|
+
version: 0.3.5
|
80
79
|
type: :runtime
|
81
80
|
prerelease: false
|
82
|
-
version_requirements: *
|
81
|
+
version_requirements: *2165236080
|
82
|
+
- !ruby/object:Gem::Dependency
|
83
|
+
name: sinatra
|
84
|
+
requirement: &2165234460 !ruby/object:Gem::Requirement
|
85
|
+
none: false
|
86
|
+
requirements:
|
87
|
+
- - ! '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 1.3.2
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: *2165234460
|
93
|
+
- !ruby/object:Gem::Dependency
|
94
|
+
name: rack
|
95
|
+
requirement: &2165232960 !ruby/object:Gem::Requirement
|
96
|
+
none: false
|
97
|
+
requirements:
|
98
|
+
- - ! '>='
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: 1.4.1
|
101
|
+
type: :development
|
102
|
+
prerelease: false
|
103
|
+
version_requirements: *2165232960
|
104
|
+
- !ruby/object:Gem::Dependency
|
105
|
+
name: rack-test
|
106
|
+
requirement: &2165230920 !ruby/object:Gem::Requirement
|
107
|
+
none: false
|
108
|
+
requirements:
|
109
|
+
- - ! '>='
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: 0.6.1
|
112
|
+
type: :development
|
113
|
+
prerelease: false
|
114
|
+
version_requirements: *2165230920
|
83
115
|
- !ruby/object:Gem::Dependency
|
84
116
|
name: linkeddata
|
85
|
-
requirement: &
|
117
|
+
requirement: &2165224020 !ruby/object:Gem::Requirement
|
86
118
|
none: false
|
87
119
|
requirements:
|
88
120
|
- - ! '>='
|
89
121
|
- !ruby/object:Gem::Version
|
90
|
-
version: 0.3.
|
122
|
+
version: 0.3.5
|
91
123
|
type: :development
|
92
124
|
prerelease: false
|
93
|
-
version_requirements: *
|
125
|
+
version_requirements: *2165224020
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: rdf-spec
|
128
|
+
requirement: &2165221300 !ruby/object:Gem::Requirement
|
129
|
+
none: false
|
130
|
+
requirements:
|
131
|
+
- - ! '>='
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: 0.3.5
|
134
|
+
type: :development
|
135
|
+
prerelease: false
|
136
|
+
version_requirements: *2165221300
|
94
137
|
- !ruby/object:Gem::Dependency
|
95
138
|
name: open-uri-cached
|
96
|
-
requirement: &
|
139
|
+
requirement: &2165218280 !ruby/object:Gem::Requirement
|
97
140
|
none: false
|
98
141
|
requirements:
|
99
142
|
- - ! '>='
|
@@ -101,32 +144,43 @@ dependencies:
|
|
101
144
|
version: 0.0.4
|
102
145
|
type: :development
|
103
146
|
prerelease: false
|
104
|
-
version_requirements: *
|
147
|
+
version_requirements: *2165218280
|
148
|
+
- !ruby/object:Gem::Dependency
|
149
|
+
name: equivalent-xml
|
150
|
+
requirement: &2165215280 !ruby/object:Gem::Requirement
|
151
|
+
none: false
|
152
|
+
requirements:
|
153
|
+
- - ! '>='
|
154
|
+
- !ruby/object:Gem::Version
|
155
|
+
version: 0.2.8
|
156
|
+
type: :development
|
157
|
+
prerelease: false
|
158
|
+
version_requirements: *2165215280
|
105
159
|
- !ruby/object:Gem::Dependency
|
106
160
|
name: nokogiri
|
107
|
-
requirement: &
|
161
|
+
requirement: &2165202460 !ruby/object:Gem::Requirement
|
108
162
|
none: false
|
109
163
|
requirements:
|
110
164
|
- - ! '>='
|
111
165
|
- !ruby/object:Gem::Version
|
112
|
-
version: 1.
|
166
|
+
version: 1.5.0
|
113
167
|
type: :development
|
114
168
|
prerelease: false
|
115
|
-
version_requirements: *
|
169
|
+
version_requirements: *2165202460
|
116
170
|
- !ruby/object:Gem::Dependency
|
117
171
|
name: rspec
|
118
|
-
requirement: &
|
172
|
+
requirement: &2165199020 !ruby/object:Gem::Requirement
|
119
173
|
none: false
|
120
174
|
requirements:
|
121
175
|
- - ! '>='
|
122
176
|
- !ruby/object:Gem::Version
|
123
|
-
version: 2.
|
177
|
+
version: 2.8.0
|
124
178
|
type: :development
|
125
179
|
prerelease: false
|
126
|
-
version_requirements: *
|
180
|
+
version_requirements: *2165199020
|
127
181
|
- !ruby/object:Gem::Dependency
|
128
182
|
name: spira
|
129
|
-
requirement: &
|
183
|
+
requirement: &2165196200 !ruby/object:Gem::Requirement
|
130
184
|
none: false
|
131
185
|
requirements:
|
132
186
|
- - ! '>='
|
@@ -134,18 +188,18 @@ dependencies:
|
|
134
188
|
version: 0.0.12
|
135
189
|
type: :development
|
136
190
|
prerelease: false
|
137
|
-
version_requirements: *
|
191
|
+
version_requirements: *2165196200
|
138
192
|
- !ruby/object:Gem::Dependency
|
139
193
|
name: yard
|
140
|
-
requirement: &
|
194
|
+
requirement: &2165194600 !ruby/object:Gem::Requirement
|
141
195
|
none: false
|
142
196
|
requirements:
|
143
197
|
- - ! '>='
|
144
198
|
- !ruby/object:Gem::Version
|
145
|
-
version: 0.
|
199
|
+
version: 0.7.5
|
146
200
|
type: :development
|
147
201
|
prerelease: false
|
148
|
-
version_requirements: *
|
202
|
+
version_requirements: *2165194600
|
149
203
|
description: ! "\n Implements SPARQL grammar parsing to SPARQL Algebra, SPARQL
|
150
204
|
Algebra processing\n and includes SPARQL Client for accessing remote repositories."
|
151
205
|
email: public-rdf-ruby@w3.org
|
@@ -160,6 +214,10 @@ files:
|
|
160
214
|
- UNLICENSE
|
161
215
|
- VERSION
|
162
216
|
- bin/sparql
|
217
|
+
- lib/rack/sparql/conneg.rb
|
218
|
+
- lib/rack/sparql.rb
|
219
|
+
- lib/sinatra/sparql/extensions.rb
|
220
|
+
- lib/sinatra/sparql.rb
|
163
221
|
- lib/sparql/algebra/evaluatable.rb
|
164
222
|
- lib/sparql/algebra/expression.rb
|
165
223
|
- lib/sparql/algebra/extensions.rb
|
@@ -222,7 +280,7 @@ files:
|
|
222
280
|
- lib/sparql/results.rb
|
223
281
|
- lib/sparql/version.rb
|
224
282
|
- lib/sparql.rb
|
225
|
-
homepage: http://
|
283
|
+
homepage: http://github.com/gkellogg/sparql
|
226
284
|
licenses:
|
227
285
|
- Public Domain
|
228
286
|
post_install_message:
|
@@ -234,7 +292,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
234
292
|
requirements:
|
235
293
|
- - ! '>='
|
236
294
|
- !ruby/object:Gem::Version
|
237
|
-
version: 1.8.
|
295
|
+
version: 1.8.7
|
238
296
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
239
297
|
none: false
|
240
298
|
requirements:
|
@@ -248,3 +306,4 @@ signing_key:
|
|
248
306
|
specification_version: 3
|
249
307
|
summary: SPARQL library for Ruby.
|
250
308
|
test_files: []
|
309
|
+
has_rdoc: false
|