class RDF::OrderedRepo

Sub-class of RDF::Repository with order-preserving properties.

Constants

DEFAULT_GRAPH

Public Class Methods

new(uri: nil, title: nil, **options, &block) click to toggle source

Initializes this repository instance.

@param [URI, to_s] uri (nil) @param [String, to_s] title (nil) @param [Hash{Symbol => Object}] options @option options [Boolean] :with_graph_name (true)

Indicates that the repository supports named graphs, otherwise,
only the default graph is supported.

@option options [Boolean] :with_validity (true)

Indicates that the repository supports named validation.

@option options [Boolean] :transaction_class (DEFAULT_TX_CLASS)

Specifies the RDF::Transaction implementation to use in this Repository.

@yield [repository] @yieldparam [Repository] repository

Calls superclass method
# File lib/rdf/ordered_repo.rb, line 24
def initialize(uri: nil, title: nil, **options, &block)
  @data = options.delete(:data) || {}
  super do
    if block_given?
      case block.arity
        when 1 then block.call(self)
        else instance_eval(&block)
      end
    end
  end
end

Public Instance Methods

apply_changeset(changeset) click to toggle source

@see Mutable#apply_changeset

# File lib/rdf/ordered_repo.rb, line 127
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
count() click to toggle source

@private @see RDF::Countable#count

# File lib/rdf/ordered_repo.rb, line 63
def count
  count = 0
  @data.each do |_, ss|
    ss.each do |_, ps|
      ps.each { |_, os| count += os.size }
    end
  end
  count
end
each(&block)
Alias for: each_statement
each_graph() { |graph(graph_name: (gn == DEFAULT_GRAPH ? nil : gn), data: self)| ... } click to toggle source

@private @see RDF::Enumerable#each_graph

# File lib/rdf/ordered_repo.rb, line 90
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
each_statement() { |statement(s, p, o, merge(graph_name: equal?(DEFAULT_GRAPH) ? nil : g))| ... } click to toggle source

@private @see RDF::Enumerable#each_statement

# File lib/rdf/ordered_repo.rb, line 109
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
Also aliased as: each
graph_names(options = nil, &block) click to toggle source

@private @see RDF::Enumerable#each_graph

# File lib/rdf/ordered_repo.rb, line 83
def graph_names(options = nil, &block)        
  @data.keys.reject { |g| g == DEFAULT_GRAPH }.to_a
end
has_graph?(graph) click to toggle source

@private @see RDF::Enumerable#has_graph?

# File lib/rdf/ordered_repo.rb, line 76
def has_graph?(graph)
  @data.has_key?(graph)
end
has_statement?(statement) click to toggle source

@private @see RDF::Enumerable#has_statement?

# File lib/rdf/ordered_repo.rb, line 102
def has_statement?(statement)
  has_statement_in?(@data, statement)
end
isolation_level() click to toggle source

@see RDF::Dataset#isolation_level

# File lib/rdf/ordered_repo.rb, line 143
def isolation_level
  :serializable
end
supports?(feature) click to toggle source

Returns `true` if this respository supports the given `feature`.

This repository supports list_terms.

Calls superclass method
# File lib/rdf/ordered_repo.rb, line 40
def supports?(feature)
  case feature.to_sym
  when :rdfstar          then true
  when :snapshots        then false
  else super
  end
end
to_query() click to toggle source

Creates a query from the statements in this repository, turning blank nodes into non-distinguished variables. This can be used to determine if this repository is logically a subset of another repository.

@return [RDF::Query]

# File lib/rdf/ordered_repo.rb, line 52
def to_query
  RDF::Query.new do |query|
    each do |statement|
      query.pattern RDF::Query::Pattern.from(statement, ndvars: true)
    end
  end
end

Protected Instance Methods

clear_statements() click to toggle source

@private @see RDF::Mutable#clear

# File lib/rdf/ordered_repo.rb, line 223
def clear_statements
  @data = @data.clear
end
data() click to toggle source

@private @return [Hash]

# File lib/rdf/ordered_repo.rb, line 230
def data
  @data
end
data=(hash) click to toggle source

@private @return [Hash]

# File lib/rdf/ordered_repo.rb, line 237
def data=(hash)
  @data = hash
end
delete_statement(statement) click to toggle source

@private @see RDF::Mutable#delete

# File lib/rdf/ordered_repo.rb, line 216
def delete_statement(statement)
  @data = delete_from(@data, statement)
end
insert_statement(statement) click to toggle source

@private @see RDF::Mutable#insert

# File lib/rdf/ordered_repo.rb, line 209
def insert_statement(statement)
  @data = insert_to(@data, statement)
end
query_pattern(pattern, **options) { |statement(s, p, o, merge(graph_name: equal?(DEFAULT_GRAPH) ? nil : c))| ... } click to toggle source

Match elements with `eql?`, not `==`

`graph_name` of `false` matches default graph. Unbound variable matches non-false graph name.

Matches terms which are native lists.

@private @see RDF::Queryable#query_pattern

# File lib/rdf/ordered_repo.rb, line 159
def query_pattern(pattern, **options, &block)
  if block_given?
    graph_name  = pattern.graph_name
    subject     = pattern.subject
    predicate   = pattern.predicate
    object      = pattern.object

    cs = @data.has_key?(graph_name) ? { graph_name => @data[graph_name] } : @data

    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.has_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.has_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

delete_from(data, statement) click to toggle source

@private @return [Hash] a new, updated hash

# File lib/rdf/ordered_repo.rb, line 277
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
has_statement_in?(data, statement) click to toggle source

@private @see has_statement

# File lib/rdf/ordered_repo.rb, line 246
def has_statement_in?(data, statement)
  s, p, o, g = statement.to_quad
  g ||= DEFAULT_GRAPH

  data.has_key?(g) &&
    data[g].has_key?(s) &&
    data[g][s].has_key?(p) &&
    data[g][s][p].has_key?(o)
end
insert_to(data, statement) click to toggle source

@private @return [Hash] a new, updated hash

# File lib/rdf/ordered_repo.rb, line 259
def insert_to(data, statement)
  raise ArgumentError, "Statement #{statement.inspect} is incomplete" if statement.incomplete?

  unless has_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