module RDF::Repository::Implementation
A default Repository
implementation supporting atomic writes and serializable transactions.
@see RDF::Repository
Constants
- DEFAULT_GRAPH
- SerializedTransaction
@deprecated moved to {RDF::Transaction::SerializedTransaction}
Public Class Methods
@private
# File lib/rdf/repository.rb, line 257 def self.extend_object(obj) obj.instance_variable_set(:@data, obj.options.delete(:data) || Hash.new) obj.instance_variable_set(:@tx_class, obj.options.delete(:transaction_class) || RDF::Transaction::SerializedTransaction) super end
Public Instance Methods
# File lib/rdf/repository.rb, line 374 def apply_changeset(changeset) data = @data changeset.deletes.each do |del| if del.constant? data = delete_from(data, del) else # we need this condition to handle wildcard statements query_pattern(del) { |stmt| data = delete_from(data, stmt) } end end changeset.inserts.each { |ins| data = insert_to(data, ins) } @data = data end
@private @see RDF::Countable#count
# File lib/rdf/repository.rb, line 286 def count count = 0 @data.each do |_, ss| ss.each do |_, ps| ps.each { |_, os| count += os.size } end end count end
@private @see RDF::Enumerable#each_graph
# File lib/rdf/repository.rb, line 326 def each_graph(&block) if block_given? @data.each_key do |gn| yield RDF::Graph.new(graph_name: (gn == DEFAULT_GRAPH ? nil : gn), data: self) end end enum_graph end
@private @see RDF::Enumerable#each_statement
# File lib/rdf/repository.rb, line 356 def each_statement(&block) if block_given? @data.each do |g, ss| ss.each do |s, ps| ps.each do |p, os| os.each do |o, object_options| yield RDF::Statement.new(s, p, o, object_options.merge(graph_name: g.equal?(DEFAULT_GRAPH) ? nil : g)) end end end end end enum_statement end
@overload graph?
Returns `false` to indicate that this is not a graph. @return [Boolean]
@overload graph?(name)
Returns `true` if `self` contains the given RDF graph_name. @param [RDF::Resource, false] graph_name Use value `false` to query for the default graph_name @return [Boolean]
# File lib/rdf/repository.rb, line 307 def graph?(*args) case args.length when 0 then false when 1 then @data.key?(args.first) else raise ArgumentError("wrong number of arguments (given #{args.length}, expected 0 or 1)") end end
@private @see RDF::Enumerable#each_graph
# File lib/rdf/repository.rb, line 319 def graph_names(options = nil, &block) @data.keys.reject { |g| g == DEFAULT_GRAPH }.to_a end
@see RDF::Dataset#isolation_level
# File lib/rdf/repository.rb, line 390 def isolation_level :snapshot end
A readable & queryable snapshot of the repository for isolated reads.
@return [Dataset] an immutable Dataset
containing a current snapshot of
the Repository contents.
@see Mutable#snapshot
# File lib/rdf/repository.rb, line 401 def snapshot self.class.new(data: @data).freeze end
@overload statement?
Returns `false` indicating this is not an RDF::Statemenet. @return [Boolean] @see RDF::Value#statement?
@overload statement?(statement)
@private @see RDF::Enumerable#statement?
# File lib/rdf/repository.rb, line 344 def statement?(*args) case args.length when 0 then false when 1 then args.first && statement_in?(@data, args.first) else raise ArgumentError("wrong number of arguments (given #{args.length}, expected 0 or 1)") end end
@private @see RDF::Enumerable#supports?
# File lib/rdf/repository.rb, line 269 def supports?(feature) case feature.to_sym when :graph_name then @options[:with_graph_name] when :validity then @options.fetch(:with_validity, true) when :literal_equality then true when :atomic_write then true when :rdf_full then true when :quoted_triples then true when :base_direction then true when :snapshots then true else false end end
Protected Instance Methods
@private @see RDF::Mutable#clear
# File lib/rdf/repository.rb, line 480 def clear_statements @data = @data.class.new end
@private @return [Hamster::Hash]
# File lib/rdf/repository.rb, line 487 def data @data end
@private @return [Hamster::Hash]
# File lib/rdf/repository.rb, line 494 def data=(hash) @data = hash end
@private @see RDF::Mutable#delete
# File lib/rdf/repository.rb, line 473 def delete_statement(statement) @data = delete_from(@data, statement) end
@private @see RDF::Mutable#insert
# File lib/rdf/repository.rb, line 466 def insert_statement(statement) @data = insert_to(@data, statement) end
Match elements with ‘eql?`, not `==`
‘graph_name` of `false` matches default graph. Unbound variable matches non-false graph name
@private @see RDF::Queryable#query_pattern
# File lib/rdf/repository.rb, line 415 def query_pattern(pattern, **options, &block) snapshot = @data if block_given? graph_name = pattern.graph_name subject = pattern.subject predicate = pattern.predicate object = pattern.object cs = snapshot.key?(graph_name) ? { graph_name => snapshot[graph_name] } : snapshot cs.each do |c, ss| next unless graph_name.nil? || graph_name == DEFAULT_GRAPH && !c || graph_name.eql?(c) ss = if subject.nil? || subject.is_a?(RDF::Query::Variable) ss elsif subject.is_a?(RDF::Query::Pattern) # Match subjects which are statements matching this pattern ss.keys.select {|s| s.statement? && subject.eql?(s)}.inject({}) do |memo, st| memo.merge(st => ss[st]) end elsif ss.key?(subject) { subject => ss[subject] } else [] end ss.each do |s, ps| ps = if predicate.nil? || predicate.is_a?(RDF::Query::Variable) ps elsif ps.key?(predicate) { predicate => ps[predicate] } else [] end ps.each do |p, os| os.each do |o, object_options| next unless object.nil? || object.eql?(o) yield RDF::Statement.new(s, p, o, object_options.merge(graph_name: c.equal?(DEFAULT_GRAPH) ? nil : c)) end end end end else enum_for(:query_pattern, pattern, **options) end end
Private Instance Methods
@private @return [Hamster::Hash] a new, updated hamster hash
# File lib/rdf/repository.rb, line 535 def delete_from(data, statement) if has_statement_in?(data, statement) s, p, o, g = statement.to_quad g = DEFAULT_GRAPH unless supports?(:graph_name) g ||= DEFAULT_GRAPH os = data[g][s][p].dup.delete_if {|k,v| k == o} ps = os.empty? ? data[g][s].dup.delete_if {|k,v| k == p} : data[g][s].merge(p => os) ss = ps.empty? ? data[g].dup.delete_if {|k,v| k == s} : data[g].merge(s => ps) return ss.empty? ? data.dup.delete_if {|k,v| k == g} : data.merge(g => ss) end data end
@private @return [Hamster::Hash] a new, updated hamster hash
# File lib/rdf/repository.rb, line 517 def insert_to(data, statement) raise ArgumentError, "Statement #{statement.inspect} is incomplete" if statement.incomplete? unless statement_in?(data, statement) s, p, o, c = statement.to_quad c ||= DEFAULT_GRAPH data = data.has_key?(c) ? data.dup : data.merge(c => {}) data[c] = data[c].has_key?(s) ? data[c].dup : data[c].merge(s => {}) data[c][s] = data[c][s].has_key?(p) ? data[c][s].dup : data[c][s].merge(p => {}) data[c][s][p] = data[c][s][p].merge(o => statement.options) end data end
@private @see statement?
# File lib/rdf/repository.rb, line 503 def statement_in?(data, statement) s, p, o, g = statement.to_quad g ||= DEFAULT_GRAPH data.key?(g) && data[g].key?(s) && data[g][s].key?(p) && data[g][s][p].key?(o) end