Skip to content

Commit

Permalink
- Support of the ntriples format when POSTING statements
Browse files Browse the repository at this point in the history
- Support of :context, :continueOnError, :commit as insert options
- Use of ENV variable ENV['AG_URL'] for spec
- Rename global_query_options method in query_options

Signed-off-by: Aymeric Brisse <aymeric.brisse@perfect-memory.com>
  • Loading branch information
abrisse committed Apr 5, 2013
1 parent 3725ce2 commit 87fb49d
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 24 deletions.
95 changes: 74 additions & 21 deletions lib/rdf/allegro_graph/abstract_repository.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ class AbstractRepository < RDF::Repository
# We actually stack up pretty well against this list.

attr_reader :resource, :resource_writable
attr_reader :global_query_options
attr_reader :query_options, :insert_options

AUTH_QUERY_OPTIONS = [ :limit, :infer, :offset ]
AUTH_INSERT_OPTIONS = [ :context, :continueOnError, :commit ]

#--------------------------------------------------------------------
# @group RDF::Repository methods
Expand All @@ -41,7 +44,8 @@ def initialize(resource, options={})
@blank_nodes_to_generate = 8
@blank_nodes_local_to_server = {}
@blank_nodes_server_to_local = {}
self.global_query_options = options[:query]
self.query_options = options[:query]
self.insert_options = options[:insert]
end

# Returns true if `feature` is supported.
Expand All @@ -61,8 +65,20 @@ def supports?(feature)
# @param [Hash] options the options to set
#
# http://www.franz.com/agraph/support/documentation/current/http-protocol.html#get-post-repo
def global_query_options=(options)
@global_query_options = filter_query_options(options)
def query_options=(options)
@query_options = filter_query_options(options)
end

# Set the global insert options that will be used at each POST request.
# Current supported options are :context, :continueOnError, :commit.
#
# @param [Hash] options the options to set
#
# http://www.franz.com/agraph/support/documentation/current/http-protocol.html#put-post-statements
def insert_options=(options)
options||={}
@format = options.delete(:format) || :json
@insert_options = filter_insert_options(options)
end

# Returns the amount of statements in the repository, as an integer
Expand Down Expand Up @@ -262,7 +278,7 @@ def raw_query(language, query, query_options={}, &block)
params = {
:query => query,
:queryLn => language.to_s
}.merge!(@global_query_options).merge!(filter_query_options(query_options))
}.merge!(@query_options).merge!(filter_query_options(query_options))

# Run the query and process the results.
json = @resource.request_json(:get, path, :parameters => params,
Expand Down Expand Up @@ -330,9 +346,23 @@ def insert_statements(statements)
#
# Note that specifying deleteDuplicates on repository creation doesn't
# seem to affect this.
json = statements_to_json(statements)
@resource_writable.request_json(:post, path_writable(:statements), :body => json,
:expected_status_code => 204)
case @format
when :json
json = statements_to_json(statements)
@resource_writable.request_json(:post, path_writable(:statements),
:parameters => prepare_filter_insert_options(@insert_options),
:body => json,
:expected_status_code => 204)
when :ntriples
text = statements_to_text_plain(statements)
@resource_writable.request_http(:post, path_writable(:statements),
:parameters => prepare_filter_insert_options(@insert_options),
:body => text,
:expected_status_code => 200,
:headers => { "Content-Type" => "text/plain" })
else
raise "Format #{@format} not supported"
end
end
protected :insert_statements

Expand Down Expand Up @@ -370,7 +400,7 @@ def delete_statements(statements)
# @option options [String] :context Match a specific graph name.
# @return [void]
def clear(options = {})
@resource_writable.statements.delete(options)
@resource_writable.statements.delete(prepare_filter_insert_options(options))
end


Expand Down Expand Up @@ -462,7 +492,16 @@ def statement_to_dict(statement)
# to operate a single statement. Otherwise, we will operate
# on all matching s,p,o triples regardless of context.
:context => serialize(statement.context) || 'null'
}.merge!(@global_query_options)
}.merge!(@query_options)
end

# Convert a list of statements to a text-plain-compatible text.
def statements_to_text_plain(statements)
graph = RDF::Repository.new
statements.each do |s|
graph << s
end
RDF::NTriples::Writer.dump(graph, nil, :encoding => Encoding::ASCII)
end

# Convert a query to SPARQL.
Expand Down Expand Up @@ -562,20 +601,34 @@ def map_from_server(value)
end
end

# Set queries/statements options that will be used at each request
#
# @param [Hash] options options to use. Currently :limit and :infer are supported.
# @return [Hash] the options

# @private
def filter_query_options(options)
options ||= {}
filtered_options = {}
[ :limit, :infer, :offset ].each do |key|
filtered_options.merge! key => options[key] if options.has_key?(key)
end
filtered_options
options||={}
options.select { |k,v| AUTH_QUERY_OPTIONS.include?(k) }
end
protected :filter_query_options

# @private
def filter_insert_options(options)
options||={}
options.select { |k,v| AUTH_INSERT_OPTIONS.include?(k) && v }
end
protected :filter_insert_options

private

def prepare_context(context)
if context.to_s != 'null'
"\"#{context}\""
else
context
end
end

def prepare_filter_insert_options(options)
options = options.dup
options[:context] = prepare_context(options[:context]) if options[:context]
options
end
end
end
24 changes: 22 additions & 2 deletions spec/shared_abstract_repository_examples.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,26 @@
end
end

describe "#insert_statements (protected)" do
let(:statement) { [RDF::Statement.new(RDF::URI("http://ar.to/#someone"), FOAF.mbox, RDF::URI("mailto:someone@gmail.com"))] }

context "with :json format" do
before { @repository.insert_options = { :format => :json } }
it "should use a JSON request to send the statements" do
@repository.resource_writable.should_receive(:request_json).at_least(:once).and_call_original
@repository.send(:insert_statements, statement)
end
end

context "with :ntriples format" do
before { @repository.insert_options = { :format => :ntriples } }
it "should use a HTTP request to send the statements" do
@repository.resource_writable.should_receive(:request_http).at_least(:once).and_call_original
@repository.send(:insert_statements, statement)
end
end
end

describe "#delete_statement (protected)" do
it "deletes a single, valid statement" do
stmt = RDF::Statement.new(RDF::URI("http://ar.to/#self"),
Expand Down Expand Up @@ -79,9 +99,9 @@
end
end

describe "#global_query_options" do
describe "#query_options" do
it "add parameters to each query" do
@repository.global_query_options = { :limit => 1, :offset => 1 }
@repository.query_options = { :limit => 1, :offset => 1 }
s = @repository.sparql_query("SELECT ?person WHERE { ?person a <http://xmlns.com/foaf/0.1/Person> }")
s.should_not include_solution(:person => "http://ar.to/#self")
s.should include_solution(:person => "http://bhuga.net/#ben")
Expand Down
2 changes: 1 addition & 1 deletion spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
# Options that we use to connect to a repository.
REPOSITORY_OPTIONS = {
:id => 'rdf_agraph_test',
:url => "http://#{ENV['AG_USER']}:#{ENV['AG_PASS']}@localhost:10035"
:url => ENV['AG_URL']
}
server = RDF::AllegroGraph::Server.new(REPOSITORY_OPTIONS[:url])
server.repository(REPOSITORY_OPTIONS[:id], :create => true)
Expand Down

0 comments on commit 87fb49d

Please sign in to comment.