Module: RDF::Mutable

Extended by:
Util::Aliasing::LateBound
Includes:
Readable, Writable
Included in:
Changeset, Graph, Repository, Transaction
Defined in:
lib/rdf/mixin/mutable.rb

Overview

Classes that include this module must implement the methods #insert_statement, #delete_statement and #each_statement.

See Also:

Instance Method Summary collapse

Methods included from Util::Aliasing::LateBound

alias_method

Methods included from Writable

#insert_graph, #insert_reader, #insert_statement, #insert_statements, #writable?

Methods included from Readable

#readable?

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#String

Implements #from_reader for each available instance of Reader, based on the reader symbol.

Arguments are passed to Reader.new.

Returns:

  • (String)

See Also:

  • RDF::Mutable.{RDF{RDF::Reader{RDF::Reader.sym}


255
256
257
258
259
260
261
262
# File 'lib/rdf/mixin/mutable.rb', line 255

def method_missing(meth, *args)
  reader = RDF::Reader.for(meth.to_s[5..-1].to_sym) if meth.to_s[0,5] == "from_"
  if reader
    self << reader.new(*args)
  else
    super
  end
end

Instance Method Details

#<<(data) ⇒ Mutable

Inserts RDF data into self.

Parameters:

Returns:

Raises:

  • (TypeError)

    if self is immutable

See Also:



68
69
70
71
72
# File 'lib/rdf/mixin/mutable.rb', line 68

def <<(data)
  raise TypeError.new("#{self} is immutable") if immutable?

  super # RDF::Writable#<<
end

#apply_changeset(changeset) ⇒ Boolean

Applies the given changeset

If #supports?(:atomic_write) is true, this must apply the changeset atomically. Otherwise, it should offer an efficient implementation of a combined delete/insert of the changeset.

Parameters:

Returns:

  • (Boolean)

    true if the changeset has been applied



210
211
212
# File 'lib/rdf/mixin/mutable.rb', line 210

def apply_changeset(changeset)
  delete_insert(changeset.deletes, changeset.inserts)
end

#clearMutable Also known as: clear!

Deletes all RDF statements from self.

Returns:

Raises:

  • (TypeError)

    if self is immutable



232
233
234
235
236
237
238
239
240
241
242
# File 'lib/rdf/mixin/mutable.rb', line 232

def clear
  raise TypeError.new("#{self} is immutable") if immutable?

  if respond_to?(:clear_statements, true)
    clear_statements
  else
    delete_statements(self)
  end

  return self
end

#delete(*statements) ⇒ self #delete(statements) ⇒ self Also known as: delete!

Note:

using splat argument syntax with excessive arguments provided

Deletes RDF statements from self. If any statement contains a Query::Variable, it is considered to be a pattern, and used to query self to find matching statements to delete.

significantly affects performance. Use Enumerator form for large numbers of statements.

Overloads:

  • #delete(*statements) ⇒ self

    Parameters:

    Returns:

    • (self)

    Raises:

    • (TypeError)

      if self is immutable

  • #delete(statements) ⇒ self

    Parameters:

    Returns:

    • (self)

    Raises:

    • (TypeError)

      if self is immutable

Raises:

  • (TypeError)


154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/rdf/mixin/mutable.rb', line 154

def delete(*statements)
  raise TypeError.new("#{self} is immutable") if immutable?

  statements.map! do |value|
    case
      when value.respond_to?(:each_statement)
        delete_statements(value)
        nil
      when (statement = Statement.from(value)).constant?
        statement
      else
        delete_statements(query(value))
        nil
    end
  end
  statements.compact!
  delete_statements(statements) unless statements.empty?

  return self
end

#delete_insert(deletes, inserts) ⇒ Mutable Also known as: delete_insert!

Note:

in the base implementation, this is equivalent to calling #delete and #insert sequentially. This method is preferred to take advantage of (e.g.) RDF::Repositories that can execute the operation in a single request.

Performs a set of deletes and inserts as a combined operation.

Parameters:

Returns:

Raises:

  • (TypeError)

    if self is immutable

See Also:



192
193
194
195
196
197
# File 'lib/rdf/mixin/mutable.rb', line 192

def delete_insert(deletes, inserts)
  deletes.respond_to?(:each_statement) ? delete(deletes) : delete(*deletes)
  inserts.respond_to?(:each_statement) ? insert(inserts) : insert(*inserts)

  self
end

#delete_statement(statement) (protected)

This method is abstract.

This method returns an undefined value.

Deletes an RDF statement from the underlying storage.

Subclasses of Repository must implement this method, except if they are immutable.

Parameters:

Raises:

  • (NotImplementedError)


302
303
304
# File 'lib/rdf/mixin/mutable.rb', line 302

def delete_statement(statement)
  raise NotImplementedError.new("#{self.class}#delete_statement")
end

#delete_statements(statements) (protected)

This method returns an undefined value.

Deletes the given RDF statements from the underlying storage.

Defaults to invoking #delete_statement for each given statement.

Subclasses of Repository may wish to override this method if they are capable of more efficiently deleting multiple statements at once.

Parameters:



286
287
288
289
290
291
# File 'lib/rdf/mixin/mutable.rb', line 286

def delete_statements(statements)
  each = statements.respond_to?(:each_statement) ? :each_statement : :each
  statements.__send__(each) do |statement|
    delete_statement(statement)
  end
end

#immutable?Boolean

Returns true if self is immutable.

Returns:

  • (Boolean)

See Also:



27
28
29
# File 'lib/rdf/mixin/mutable.rb', line 27

def immutable?
  !mutable?
end

#insert(*statements) ⇒ self #insert(statements) ⇒ self

Note:

using splat argument syntax with excessive arguments provided

Inserts RDF statements into self.

significantly affects performance. Use Enumerator form for large numbers of statements.

Overloads:

  • #insert(*statements) ⇒ self

    Parameters:

    Returns:

    • (self)

    Raises:

    • (TypeError)

      if self is immutable

  • #insert(statements) ⇒ self

    Parameters:

    Returns:

    • (self)

    Raises:

    • (TypeError)

      if self is immutable

Raises:

  • (TypeError)

See Also:



92
93
94
95
96
# File 'lib/rdf/mixin/mutable.rb', line 92

def insert(*statements)
  raise TypeError.new("#{self} is immutable") if immutable?

  super # RDF::Writable#insert
end

#load(url, graph_name: nil, **options) Also known as: load!

This method returns an undefined value.

Loads RDF statements from the given file or URL into self.

Parameters:

  • url (String, #to_s)
  • options (Hash{Symbol => Object})

    Options from Reader.open

Options Hash (**options):

  • :graph_name (RDF::Resource)

    Set set graph name of each loaded statement

Raises:

  • (TypeError)


40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/rdf/mixin/mutable.rb', line 40

def load(url, graph_name: nil, **options)
  raise TypeError.new("#{self} is immutable") if immutable?

  Reader.open(url, {base_uri: url}.merge(options)) do |reader|
    if graph_name
      statements = []
      reader.each_statement do |statement|
        statement.graph_name = graph_name
        statements << statement
      end
      insert_statements(statements)
      statements.size
    else
      insert_statements(reader)
      nil
    end
  end
end

#mutable?Boolean

Returns true if self is mutable.

Returns:

  • (Boolean)

See Also:



18
19
20
# File 'lib/rdf/mixin/mutable.rb', line 18

def mutable?
  writable?
end

#respond_to_missing?(name, include_private = false) ⇒ Boolean

Note:

this instantiates an entire reader; it could probably be done more efficiently by refactoring RDF::Reader and/or RDF::Format to expose a list of valid format symbols.

Returns:

  • (Boolean)


268
269
270
271
# File 'lib/rdf/mixin/mutable.rb', line 268

def respond_to_missing?(name, include_private = false)
  return RDF::Reader.for(name.to_s[5..-1].to_sym) if name.to_s[0,5] == 'from_'
  super 
end

#snapshotDataset

A readable & queryable snapshot of the repository for isolated reads.

This method must be implemented when #supports(:snapshots) is true.

Returns:

  • (Dataset)

    an immutable Dataset containing a current snapshot of the Repository contents.

Raises:

  • (NotImplementederror)

    when snapshots aren't implemented for the class



223
224
225
# File 'lib/rdf/mixin/mutable.rb', line 223

def snapshot
  raise NotImplementedError, "#{self.class} does not implement snapshots"
end

#update(*statements) ⇒ self #update(statements) ⇒ self Also known as: update!

Note:

using splat argument syntax with excessive arguments provided

Updates RDF statements in self.

#update([subject, predicate, object]) is equivalent to #delete([subject, predicate, nil]) followed by #insert([subject, predicate, object]) unless object is nil.

significantly affects performance. Use Enumerator form for large numbers of statements.

Overloads:

  • #update(*statements) ⇒ self

    Parameters:

    Returns:

    • (self)

    Raises:

    • (TypeError)

      if self is immutable

  • #update(statements) ⇒ self

    Parameters:

    Returns:

    • (self)

    Raises:

    • (TypeError)

      if self is immutable

Raises:

  • (TypeError)


118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/rdf/mixin/mutable.rb', line 118

def update(*statements)
  raise TypeError.new("#{self} is immutable") if immutable?
  statements = statements[0] if statements.length == 1 && statements[0].is_a?(Enumerable)

  statements.each do |statement|
    if (statement = Statement.from(statement))
      if statement.has_object?
        delete_insert([[statement.subject, statement.predicate, nil]], [statement])
      else
        delete([statement.subject, statement.predicate, nil])
      end
    end
  end
end