sparql 0.0.2 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|