sparql 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. data/AUTHORS +3 -0
  2. data/CREDITS +0 -0
  3. data/README.markdown +103 -53
  4. data/UNLICENSE +24 -0
  5. data/VERSION +1 -0
  6. data/bin/sparql +87 -0
  7. data/lib/sparql.rb +105 -22
  8. data/lib/sparql/algebra.rb +369 -0
  9. data/lib/sparql/algebra/evaluatable.rb +37 -0
  10. data/lib/sparql/algebra/expression.rb +284 -0
  11. data/lib/sparql/algebra/extensions.rb +159 -0
  12. data/lib/sparql/algebra/operator.rb +492 -0
  13. data/lib/sparql/algebra/operator/add.rb +34 -0
  14. data/lib/sparql/algebra/operator/and.rb +65 -0
  15. data/lib/sparql/algebra/operator/asc.rb +29 -0
  16. data/lib/sparql/algebra/operator/ask.rb +46 -0
  17. data/lib/sparql/algebra/operator/base.rb +46 -0
  18. data/lib/sparql/algebra/operator/bgp.rb +26 -0
  19. data/lib/sparql/algebra/operator/bound.rb +48 -0
  20. data/lib/sparql/algebra/operator/compare.rb +84 -0
  21. data/lib/sparql/algebra/operator/construct.rb +85 -0
  22. data/lib/sparql/algebra/operator/dataset.rb +77 -0
  23. data/lib/sparql/algebra/operator/datatype.rb +42 -0
  24. data/lib/sparql/algebra/operator/desc.rb +17 -0
  25. data/lib/sparql/algebra/operator/describe.rb +71 -0
  26. data/lib/sparql/algebra/operator/distinct.rb +50 -0
  27. data/lib/sparql/algebra/operator/divide.rb +43 -0
  28. data/lib/sparql/algebra/operator/equal.rb +32 -0
  29. data/lib/sparql/algebra/operator/exprlist.rb +52 -0
  30. data/lib/sparql/algebra/operator/filter.rb +71 -0
  31. data/lib/sparql/algebra/operator/graph.rb +28 -0
  32. data/lib/sparql/algebra/operator/greater_than.rb +32 -0
  33. data/lib/sparql/algebra/operator/greater_than_or_equal.rb +33 -0
  34. data/lib/sparql/algebra/operator/is_blank.rb +35 -0
  35. data/lib/sparql/algebra/operator/is_iri.rb +37 -0
  36. data/lib/sparql/algebra/operator/is_literal.rb +36 -0
  37. data/lib/sparql/algebra/operator/join.rb +67 -0
  38. data/lib/sparql/algebra/operator/lang.rb +29 -0
  39. data/lib/sparql/algebra/operator/lang_matches.rb +53 -0
  40. data/lib/sparql/algebra/operator/left_join.rb +95 -0
  41. data/lib/sparql/algebra/operator/less_than.rb +32 -0
  42. data/lib/sparql/algebra/operator/less_than_or_equal.rb +32 -0
  43. data/lib/sparql/algebra/operator/minus.rb +31 -0
  44. data/lib/sparql/algebra/operator/multiply.rb +34 -0
  45. data/lib/sparql/algebra/operator/not.rb +35 -0
  46. data/lib/sparql/algebra/operator/not_equal.rb +26 -0
  47. data/lib/sparql/algebra/operator/or.rb +65 -0
  48. data/lib/sparql/algebra/operator/order.rb +69 -0
  49. data/lib/sparql/algebra/operator/plus.rb +31 -0
  50. data/lib/sparql/algebra/operator/prefix.rb +45 -0
  51. data/lib/sparql/algebra/operator/project.rb +46 -0
  52. data/lib/sparql/algebra/operator/reduced.rb +47 -0
  53. data/lib/sparql/algebra/operator/regex.rb +70 -0
  54. data/lib/sparql/algebra/operator/same_term.rb +46 -0
  55. data/lib/sparql/algebra/operator/slice.rb +60 -0
  56. data/lib/sparql/algebra/operator/str.rb +35 -0
  57. data/lib/sparql/algebra/operator/subtract.rb +32 -0
  58. data/lib/sparql/algebra/operator/union.rb +55 -0
  59. data/lib/sparql/algebra/query.rb +99 -0
  60. data/lib/sparql/algebra/sxp_extensions.rb +35 -0
  61. data/lib/sparql/algebra/version.rb +20 -0
  62. data/lib/sparql/extensions.rb +102 -0
  63. data/lib/sparql/grammar.rb +298 -0
  64. data/lib/sparql/grammar/lexer.rb +609 -0
  65. data/lib/sparql/grammar/parser.rb +1383 -0
  66. data/lib/sparql/grammar/parser/meta.rb +1801 -0
  67. data/lib/sparql/results.rb +220 -0
  68. data/lib/sparql/version.rb +20 -0
  69. metadata +232 -62
  70. data/Rakefile +0 -22
  71. data/coverage/index.html +0 -252
  72. data/coverage/lib-sparql-execute_sparql_rb.html +0 -621
  73. data/coverage/lib-sparql_rb.html +0 -622
  74. data/lib/sparql/execute_sparql.rb +0 -27
  75. data/lib/sparql/sparql.treetop +0 -159
  76. data/sparql.gemspec +0 -16
  77. data/spec/spec.opts +0 -2
  78. data/spec/spec_helper.rb +0 -24
  79. data/spec/unit/graph_parsing_spec.rb +0 -76
  80. data/spec/unit/iri_parsing_spec.rb +0 -46
  81. data/spec/unit/prefixed_names_parsing_spec.rb +0 -40
  82. data/spec/unit/primitives_parsing_spec.rb +0 -26
  83. data/spec/unit/sparql_parsing_spec.rb +0 -72
  84. data/spec/unit/variables_parsing_spec.rb +0 -36
data/AUTHORS ADDED
@@ -0,0 +1,3 @@
1
+ * Gregg Kellogg <gregg@kellogg-assoc.com>
2
+ * Arto Bendiken <arto.bendiken@gmail.com>
3
+ * Pius Uzamere <pius@alum.mit.edu>
data/CREDITS ADDED
File without changes
data/README.markdown CHANGED
@@ -1,88 +1,138 @@
1
- sparql Release 0.0.1 (July 17th 2008)
2
- ===================================
1
+ # SPARQL for RDF.rb
3
2
 
4
- **Git**: [http://github.com/pius/sparql](http://github.com/pius/sparql)
5
- **Author**: Pius Uzamere, [The Uyiosa Corporation](http://www.uyiosa.com)
3
+ This is a [Ruby][] implementation of the [SPARQL][] algebra for [RDF.rb][].
6
4
 
7
- **Copyright**: Pius Uzamere © 2008
8
- **License**: The Lesser GNU Public License
5
+ ## Features
9
6
 
7
+ * 100% free and unencumbered [public domain](http://unlicense.org/) software.
8
+ * [SPARQL 1.0][] query parsing and execution
9
+ * SPARQL results as [XML][SPARQL XML] or [JSON][SPARQL JSON].
10
+ * SPARQL CONSTRUCT or DESCRIBE serialized based on Format, Extension of Mime Type
11
+ using available RDF Writers (see [Linked Data](http://rubygems.org/gems/linkeddata))
12
+ * SPARQL Client for accessing remote SPARQL endpoints.
13
+ * Helper method for describing [SPARQL Service Description][]
14
+ * Compatible with Ruby Ruby 1.9.x.
15
+ * Compatible with older Ruby versions with the help of the [Backports][] gem.
16
+ * Supports Unicode query strings both on Ruby 1.8.x and 1.9.x.
10
17
 
11
- SYNOPSIS
12
- --------
18
+ ## Examples
13
19
 
14
- sparql is a library for Ruby that formally implements the [SPARQL grammar](http://www.w3.org/TR/rdf-sparql-query/#grammar) as a parsing expression grammar (PEG). The grammar is implemented in a fantastic syntax language called [Treetop](http://treetop.rubyforge.org).
20
+ require 'rubygems'
21
+ require 'sparql'
15
22
 
23
+ ### Executing a SPARQL query against a repository
16
24
 
17
- FEATURE LIST
18
- ------------
19
-
20
- 1. **As of right now (00:10 EST, July 17, 2008) can parse basic SPARQL statements, check the test cases for precisely what it can support**: When finished, this library will be able to parse arbitrary SPARQL queries and can serve as a maintainable reference implementation in Ruby.
25
+ queryable = RDF::Repository.load("etc/doap.ttl")
26
+ sse = SPARQL.parse("SELECT * WHERE { ?s ?p ?o }")
27
+ sse.execute(queryable)
21
28
 
22
- 2. **Starting point for providing SPARQL endpoints for arbitrary datastores**: When completed, this library will provide hooks that allow a Ruby developer to easily define a translation from SPARQL to another query language or API of their choosing. Ideally, this will be done using a simple YAML configuration file.
29
+ ### Rendering solutions as JSON, XML or HTML
30
+ queryable = RDF::Repository.load("etc/doap.ttl")
31
+ solutions = SPARQL.execute("SELECT * WHERE { ?s ?p ?o }", queryable)
32
+ solutions.to_json #to_xml #to_html
23
33
 
24
- 3. **Fully Composable**: Because parsing expression grammars are closed under composition, you can compose this grammar with other Treetop grammars with relative ease.
34
+ ### Parsing a SPARQL query string to SSE
25
35
 
36
+ sse = SPARQL.parse("SELECT * WHERE { ?s ?p ?o }")
37
+ sse.to_sxp
26
38
 
27
- USAGE
28
- -----
39
+ ### Command line processing
29
40
 
30
- Though this library only parses a small subset of SPARQL and I've not added all of the API methods yet, it **is** ready to start playing with.
41
+ sparql --default-graph etc/doap.ttl etc/from_default.rq
42
+ sparql -e "SELECT * FROM <etc/doap.ttl> WHERE { ?s ?p ?o }"
31
43
 
32
- 1. **Install the Gem**
44
+ # Generate SPARQL Algebra Expression (SSE) format
45
+ sparql --to-sse etc/input.rq
46
+ sparql --to-sse -e "SELECT * WHERE { ?s ?p ?o }"
33
47
 
34
- Make sure you've upgraded to RubyGems 1.2. Then, if you've never installed a gem from GitHub before then do this:
48
+ # Run query using SSE input
49
+ sparql --default-graph etc/doap.ttl --sse etc/input.sse
50
+ sparql --sse -e "(dataset (<etc/doap.ttl>) (bgp (triple ?s ?p ?o))))"
35
51
 
36
- > gem sources -a http://gems.github.com (you only have to do this once)
52
+ ## Documentation
37
53
 
38
- Then:
54
+ Full documentation available on [Rubydoc.info][SPARQL doc]
39
55
 
40
- > sudo gem install pius-sparql
56
+ ### Principle Classes
41
57
 
42
- 2. **Make Sure You've Got the Dependencies installed**
58
+ * {SPARQL}
59
+ * {SPARQL::Algebra}
60
+ * {SPARQL::Algebra::Expression}
61
+ * {SPARQL::Algebra::Query}
62
+ * {SPARQL::Algebra::Operator}
63
+ * {SPARQL::Grammar}
64
+ * {SPARQL::Grammar::Parser}
65
+ * {SPARQL::Grammar::Lexer}
43
66
 
44
- sparql depends on Treetop (http://github.com/nathansobo/treetop).
67
+ ## Dependencies
45
68
 
46
- > sudo gem install treetop
69
+ * [Ruby](http://ruby-lang.org/) (>= 1.9) or (>= 1.8.1 with [Backports][])
70
+ * [RDF.rb](http://rubygems.org/gems/rdf) (>= 0.3.4)
71
+ * [SPARQL::Client](https://rubygems.org/gems/sparql-client) (>= 0.0.11)
72
+ * [SXP](https://rubygems.org/gems/sxp) (>= 0.0.15)
73
+ * [Builder](https://rubygems.org/gems/builder) (>= 3.0.0)
74
+ * [JSON](https://rubygems.org/gems/json) (>= 1.5.1)
47
75
 
48
- 3. **Require the gem in your code, play with it**
76
+ ## Installation
49
77
 
50
- As of this minute, the code won't be that useful to you, as it can only parse a small subset of SPARQL and the translation hooks have not been added yet. That being said, stay tuned. I think development on this is going to move fairly quickly because Treetop is such a joy to write the PEG in.
78
+ The recommended installation method is via [RubyGems](http://rubygems.org/).
79
+ To install the latest official release of the `SPARQL` gem, do:
51
80
 
52
- Anyway, you can get started by doing the following in IRB.
81
+ % [sudo] gem install sparql
53
82
 
54
- > irb(main):001:0> require 'rubygems'
83
+ ## Download
55
84
 
56
- > => true
85
+ To get a local working copy of the development repository, do:
57
86
 
58
- > irb(main):002:0> gem 'pius-sparql'
87
+ % git clone git://github.com/gkellogg/sparql.git
59
88
 
60
- > => true
89
+ ## Mailing List
61
90
 
62
- > irb(main):003:0> require 'sparql'
91
+ * <http://lists.w3.org/Archives/Public/public-rdf-ruby/>
63
92
 
64
- > => true
93
+ ## Authors
65
94
 
66
- > irb(main):004:0> parser = SparqlParser.new
95
+ * [Gregg Kellogg](http://github.com/gkellogg) - <http://kellogg-assoc.com/>
96
+ * [Arto Bendiken](http://github.com/bendiken) - <http://ar.to/>
97
+ * [Pius Uzamere](http://github.com/pius) - <http://pius.me/>
67
98
 
68
- > => #SparqlParser:0x1270bcc @consume_all_input=true
99
+ ## Contributing
69
100
 
70
- > irb(main):005:0> syntaxtree = parser.parse('SELECT ?foo ?bar WHERE { ?x foaf:knows ?y . ?z foaf:name ?y . }')
101
+ * Do your best to adhere to the existing coding conventions and idioms.
102
+ * Don't use hard tabs, and don't leave trailing whitespace on any line.
103
+ * Do document every method you add using [YARD][] annotations. Read the
104
+ [tutorial][YARD-GS] or just look at the existing code for examples.
105
+ * Don't touch the `.gemspec`, `VERSION` or `AUTHORS` files. If you need to
106
+ change them, do so on your private branch only.
107
+ * Do feel free to add yourself to the `CREDITS` file and the corresponding
108
+ list in the the `README`. Alphabetical order applies.
109
+ * Do note that in order for us to merge any non-trivial changes (as a rule
110
+ of thumb, additions larger than about 15 lines of code), we need an
111
+ explicit [public domain dedication][PDD] on record from you.
71
112
 
113
+ ## License
72
114
 
73
- 4. **Read the documentation**
115
+ This is free and unencumbered public domain software. For more information,
116
+ see <http://unlicense.org/> or the accompanying {file:UNLICENSE} file.
74
117
 
75
- Actually, read the tests -- they will show you the forms that are supported. Take a look at lib/sparql/sparql.treetop and get a sense of the grammar. In addition, check out the [formal specification of the SPARQL grammar](http://www.w3.org/TR/rdf-sparql-query/#grammar) so you can see how the Treetop grammar relates to it.
76
-
77
- 5. **Contribute!**
78
-
79
- Fork my repository (http://github.com/pius/sparql), make some changes, and send along a pull request!
80
-
81
- The best way to contribute is to add a test case for a specific SPARQL query that does not parse and then tweak the grammar such that your new test case plus all the others pass.
82
-
83
-
84
- COPYRIGHT
85
- ---------
86
-
87
- sparql was created in 2008 by Pius Uzamere (pius -AT- alum -DOT- mit -DOT- edu) and is
88
- licensed under the LGPL.
118
+ [Ruby]: http://ruby-lang.org/
119
+ [RDF]: http://www.w3.org/RDF/
120
+ [YARD]: http://yardoc.org/
121
+ [YARD-GS]: http://rubydoc.info/docs/yard/file/docs/GettingStarted.md
122
+ [PDD]: http://lists.w3.org/Archives/Public/public-rdf-ruby/2010May/0013.html
123
+ [SPARQL]: http://en.wikipedia.org/wiki/SPARQL
124
+ [SPARQL 1.0]: http://www.w3.org/TR/rdf-sparql-query/
125
+ [SPARQL 1.1]: http://www.w3.org/TR/sparql11-query/
126
+ [SSE]: http://openjena.org/wiki/SSE
127
+ [SXP]: http://sxp.rubyforge.org/
128
+ [grammar]: http://www.w3.org/TR/rdf-sparql-query/#grammar
129
+ [RDF.rb]: http://rdf.rubyforge.org/
130
+ [YARD]: http://yardoc.org/
131
+ [YARD-GS]: http://rubydoc.info/docs/yard/file/docs/GettingStarted.md
132
+ [PDD]: http://unlicense.org/#unlicensing-contributions
133
+ [Backports]: http://rubygems.org/gems/backports
134
+ [SPARQL doc]: http://rubydoc.info/github/gkellogg/sparql/frames
135
+ [SPARQL XML]: http://www.w3.org/TR/rdf-sparql-XMLres/
136
+ [SPARQL JSON]: http://www.w3.org/TR/rdf-sparql-json-res/
137
+ [SPARQL Protocol]: http://www.w3.org/TR/rdf-sparql-protocol/
138
+ [SPARQL Service]: http://www.w3.org/TR/sparql11-service-description/
data/UNLICENSE ADDED
@@ -0,0 +1,24 @@
1
+ This is free and unencumbered software released into the public domain.
2
+
3
+ Anyone is free to copy, modify, publish, use, compile, sell, or
4
+ distribute this software, either in source code form or as a compiled
5
+ binary, for any purpose, commercial or non-commercial, and by any
6
+ means.
7
+
8
+ In jurisdictions that recognize copyright laws, the author or authors
9
+ of this software dedicate any and all copyright interest in the
10
+ software to the public domain. We make this dedication for the benefit
11
+ of the public at large and to the detriment of our heirs and
12
+ successors. We intend this dedication to be an overt act of
13
+ relinquishment in perpetuity of all present and future rights to this
14
+ software under copyright law.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20
+ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21
+ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
23
+
24
+ For more information, please refer to <http://unlicense.org/>
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.2
data/bin/sparql ADDED
@@ -0,0 +1,87 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ $:.unshift(File.expand_path(File.join(File.dirname(__FILE__), "..", 'lib')))
4
+ require 'sparql'
5
+ require 'linkeddata'
6
+ require 'getoptlong'
7
+
8
+ def run(input, options = {})
9
+ if options[:debug]
10
+ puts "input graph:\n#{options[:graph].dump(:n3)}\n" if options[:graph]
11
+ puts "query:\n#{input}\n"
12
+ end
13
+
14
+ if options[:verbose]
15
+ puts ("\nSPARQL:\n" + input)
16
+ end
17
+
18
+ query = if options[:sse]
19
+ SPARQL::Algebra.parse(input, {:debug => options[:debug]})
20
+ else
21
+ SPARQL::Grammar.parse(input, options)
22
+ end
23
+
24
+ if options[:to_sse]
25
+ puts ("\nSSE:\n" + query.to_sxp)
26
+ else
27
+ res = query.execute(options[:graph])
28
+ puts res.inspect if options[:verbose]
29
+ puts case res
30
+ when RDF::Graph then res.dump(:ttl, :base_uri => query.base_uri, :prefixes => query.prefixes)
31
+ else res.map {|s| s.bindings.map {|k,v| "#{k}: #{v}"}}.join("\n")
32
+ end
33
+ end
34
+ end
35
+
36
+ opts = GetoptLong.new(
37
+ ["--debug", GetoptLong::NO_ARGUMENT],
38
+ ["--dump", GetoptLong::NO_ARGUMENT],
39
+ ["--verbose", GetoptLong::NO_ARGUMENT],
40
+ ["--sse", GetoptLong::NO_ARGUMENT],
41
+ ["--to-sse", GetoptLong::NO_ARGUMENT],
42
+ ["--execute", "-e", GetoptLong::REQUIRED_ARGUMENT],
43
+ ["--default-graph", "-g", GetoptLong::REQUIRED_ARGUMENT],
44
+ ["--help", "-?", GetoptLong::NO_ARGUMENT]
45
+ )
46
+
47
+ options = {
48
+ :graph => RDF::Repository.new,
49
+ }
50
+
51
+ input = nil
52
+
53
+ opts.each do |opt, arg|
54
+ case opt
55
+ when '--execute' then input = arg
56
+ when "--default-graph" then options[:graph] = RDF::Graph.load(arg)
57
+ when '--dump' then $dump = true
58
+ when '--sse' then options[:sse] = true
59
+ when '--to-sse' then options[:to_sse] = true
60
+ when '--debug' then options[:debug] = true
61
+ when '--verbose' then options[:verbose] = true
62
+ when "--help"
63
+ puts "Usage: #{$0} [options] file-or-uri ..."
64
+ puts "Options:"
65
+ puts " --execute,-e: Use option argument as the SPARQL input if no files are given"
66
+ puts " --default-graph: Load default graph"
67
+ puts " --dump: Dump raw output, otherwise serialize to SSE"
68
+ puts " --debug: Display detailed debug output"
69
+ puts " --sse: Input is in SSE format"
70
+ puts " --to-sse: Generate SSE instead of running query"
71
+ puts " --debug: Display detailed debug output"
72
+ puts " --verbose: Display details of processing"
73
+ puts " --help,-?: This message"
74
+ exit(0)
75
+ end
76
+ end
77
+
78
+ if ARGV.empty?
79
+ s = input ? input : $stdin.read
80
+ run(s, options)
81
+ else
82
+ ARGV.each do |test_file|
83
+ puts "parse #{test_file}"
84
+ run(RDF::Util::File.open_file(test_file).read, options.merge(:base_uri => RDF::URI(test_file)))
85
+ end
86
+ end
87
+ puts
data/lib/sparql.rb CHANGED
@@ -1,28 +1,111 @@
1
- # This file is part of Sparql.rb.
2
- #
3
- # Sparql.rb is free software: you can redistribute it and/or modify
4
- # it under the terms of the GNU Lesser General Public License as published by
5
- # the Free Software Foundation, either version 3 of the License, or
6
- # (at your option) any later version.
7
- #
8
- # Sparql.rb is distributed in the hope that it will be useful,
9
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
- # GNU Lesser General Public License for more details.
12
- #
13
- # You should have received a copy of the GNU Lesser General Public License
14
- # along with Sparql.rb. If not, see <http://www.gnu.org/licenses/>.
1
+ require 'sparql/extensions'
15
2
 
3
+ ##
4
+ # A SPARQL for RDF.rb.
5
+ #
6
+ # @see http://www.w3.org/TR/rdf-sparql-query
7
+ module SPARQL
8
+ autoload :Algebra, 'sparql/algebra'
9
+ autoload :Grammar, 'sparql/grammar'
10
+ autoload :Results, 'sparql/results'
11
+ autoload :VERSION, 'sparql/version'
16
12
 
17
- require 'rubygems'
18
- require 'pathname'
13
+ # @see http://rubygems.org/gems/sparql-client
14
+ autoload :Client, 'sparql/client'
19
15
 
20
- class Pathname
21
- def /(path)
22
- (self + path).expand_path
16
+ ##
17
+ # Parse the given SPARQL `query` string.
18
+ #
19
+ # @example
20
+ # parser = SPARQL.parse("SELECT * WHERE { ?s ?p ?o }")
21
+ # result = parser.parse
22
+ #
23
+ # @param [IO, StringIO, String, #to_s] query
24
+ # @param [Hash{Symbol => Object}] options
25
+ # @return [SPARQL::Query]
26
+ # The resulting query may be executed against
27
+ # a `queryable` object such as an RDF::Graph
28
+ # or RDF::Repository.
29
+ # @raise [Parser::Error] on invalid input
30
+ def self.parse(query, options = {})
31
+ query = Grammar::Parser.new(query, options).parse
23
32
  end
24
- end # class Pathname
25
33
 
26
- dir = Pathname(__FILE__).dirname.expand_path / 'sparql'
34
+ ##
35
+ # Parse and execute the given SPARQL `query` string against `queriable`.
36
+ #
37
+ # Requires a queryable object (such as an RDF::Repository), into which the dataset will be loaded.
38
+ #
39
+ # Optionally takes a list of URIs to load as default or named graphs
40
+ # into `queryable`.
41
+ #
42
+ # Note, if default or named graphs are specified as options (protocol elements),
43
+ # or the query references specific default or named graphs the graphs are either
44
+ # presumed to be existant in `queryable` or are loaded into `queryable` depending
45
+ # on the presense and value of the :load_datasets option.
46
+ #
47
+ # Attempting to load into an immutable `queryable` will result in a RDF::TypeError.
48
+ #
49
+ # @example
50
+ # repository = RDF::Repository.new
51
+ # results = SPARQL.execute("SELECT * WHERE { ?s ?p ?o }", repository)
52
+ # result = parser.parse
53
+ #
54
+ # @param [IO, StringIO, String, #to_s] query
55
+ # @param [Hash{Symbol => Object}] options
56
+ # @option options [RDF::Queryable] :queryable
57
+ # @option options [RDF::URI, String, Array<RDF::URI, String>] :load_datasets
58
+ # One or more URIs used to initialize a new instance of `queryable` in the default context.
59
+ # @option options [RDF::URI, String, Array<RDF::URI, String>] :default_graph_uri
60
+ # One or more URIs used to initialize a new instance of `queryable` in the default context.
61
+ # @option options [RDF::URI, String, Array<RDF::URI, String>] :named_graph_uri
62
+ # One or more URIs used to initialize the `queryable` as a named context.
63
+ # @return [RDF::Graph, RDF::Query::Solutions, Boolean]
64
+ # Note, results may be used with SPARQL.serialize_results to obtain appropriate
65
+ # output encoding.
66
+ # @raise [SPARQL::MalformedQuery] on invalid input
67
+ def self.execute(query, queryable, options = {})
68
+ query = self.parse(query, options)
69
+ queryable = queryable || RDF::Repository.new
70
+
71
+ if options.has_key?(:load_datasets)
72
+ queryable = queryable.class.new
73
+ [options[:default_graph_uri]].flatten.each do |uri|
74
+ queryable.load(uri)
75
+ end
76
+ [options[:named_graph_uri]].flatten.each do |uri|
77
+ queryable.load(uri, :context => uri)
78
+ end
79
+ end
80
+ solutions = query.execute(queryable)
81
+ rescue SPARQL::Grammar::Parser::Error => e
82
+ raise MalformedQuery, e.message
83
+ rescue RDF::TypeError => e
84
+ raise QueryRequestRefused, e.message
85
+ end
86
+
87
+ ##
88
+ # MalformedQuery
89
+ #
90
+ # When the value of the query type is not a legal sequence of characters in the language defined by the
91
+ # SPARQL grammar, the MalformedQuery or QueryRequestRefused fault message must be returned. According to the
92
+ # Fault Replaces Message Rule, if a WSDL fault is returned, including MalformedQuery, an Out Message must not
93
+ # be returned.
94
+ class MalformedQuery < Exception
95
+ def title
96
+ "Malformed Query".freeze
97
+ end
98
+ end
99
+
100
+ ##
101
+ # QueryRequestRefused
102
+ #
103
+ # returned when a client submits a request that the service refuses to process.
104
+ class QueryRequestRefused < Exception
105
+ def title
106
+ "Query Request Refused".freeze
107
+ end
108
+ end
109
+ end
27
110
 
28
- require dir / 'execute_sparql'
111
+ require 'sparql/extensions'