Module: RDF::Enumerable

Extended by:
Util::Aliasing::LateBound
Includes:
Enumerable, Countable
Included in:
Dataset, Enumerator, Graph, List, Query, Query::Solution, Queryable::Enumerator, Reader, Transaction
Defined in:
lib/rdf/mixin/enumerable.rb

Overview

An RDF statement enumeration mixin.

Classes that include this module must implement an #each method that yields RDF statements.

Examples:

Checking whether any statements exist

enumerable.empty?

Checking how many statements exist

enumerable.count

Checking whether a specific statement exists

enumerable.statement?(RDF::Statement(subject, predicate, object))
enumerable.triple?([subject, predicate, object])
enumerable.quad?([subject, predicate, object, graph_name])

Checking whether a specific value exists

enumerable.subject?(RDF::URI("https://rubygems.org/gems/rdf"))
enumerable.predicate?(RDF::RDFS.label)
enumerable.object?(RDF::Literal("A Ruby library for working with Resource Description Framework (RDF) data.", language: :en))
enumerable.graph?(RDF::URI("http://ar.to/#self"))

Enumerating all statements

enumerable.each_statement do |statement|
  puts statement.inspect
end

Enumerating all statements in the form of triples

enumerable.each_triple do |subject, predicate, object|
  puts [subject, predicate, object].inspect
end

Enumerating all statements in the form of quads

enumerable.each_quad do |subject, predicate, object, graph_name|
  puts [subject, predicate, object, graph_name].inspect
end

Enumerating all terms

enumerable.each_subject   { |term| puts term.inspect }
enumerable.each_predicate { |term| puts term.inspect }
enumerable.each_object    { |term| puts term.inspect }
enumerable.each_term      { |term| puts term.inspect }

Obtaining all statements

enumerable.statements  #=> [RDF::Statement(subject1, predicate1, object1), ...]
enumerable.triples     #=> [[subject1, predicate1, object1], ...]
enumerable.quads       #=> [[subject1, predicate1, object1, graph_name1], ...]

Obtaining all unique values

enumerable.subjects(unique: true)    #=> [subject1, subject2, subject3, ...]
enumerable.predicates(unique: true)  #=> [predicate1, predicate2, predicate3, ...]
enumerable.objects(unique: true)     #=> [object1, object2, object3, ...]
enumerable.graph_names(unique: true) #=> [graph_name1, graph_name2, graph_name3, ...]

See Also:

Defined Under Namespace

Classes: Enumerator

Instance Method Summary collapse

Methods included from Util::Aliasing::LateBound

alias_method

Methods included from Countable

#count, #empty?

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#String (protected)

Implements #to_writer for each available instance of Writer, based on the writer symbol.

Returns:

  • (String)

See Also:

  • RDF::Enumerable.{RDF{RDF::Writer{RDF::Writer.sym}


818
819
820
821
822
823
824
825
# File 'lib/rdf/mixin/enumerable.rb', line 818

def method_missing(meth, *args)
  writer = RDF::Writer.for(meth.to_s[3..-1].to_sym) if meth.to_s[0,3] == "to_"
  if writer
    writer.buffer(standard_prefixes: true) {|w| w << self}
  else
    super
  end
end

Instance Method Details

#canonicalizeRDF::Enumerable

Note:

This is updated by RDF::Normalize to also canonicalize blank nodes.

Enumerates each statement using its canonical representation.

Returns:



731
732
733
734
735
736
# File 'lib/rdf/mixin/enumerable.rb', line 731

def canonicalize
  this = self
  Enumerable::Enumerator.new do |yielder|
    this.send(:each_statement) {|y| yielder << y.canonicalize}
  end
end

#canonicalize!Object

Mutating canonicalization not supported

Raises:

  • NotImplementedError



742
743
744
# File 'lib/rdf/mixin/enumerable.rb', line 742

def canonicalize!
  raise NotImplementedError, "Canonicalizing enumerables not supported"
end

#dump(*args, **options) ⇒ String

Returns a serialized string representation of self.

Before calling this method you may need to explicitly require a serialization extension for the specified format.

Examples:

Serializing into N-Triples format

require 'rdf/ntriples'
ntriples = enumerable.dump(:ntriples)

Parameters:

  • args (Array<Object>)

    if the last argument is a hash, it is passed as options to Writer.dump.

Returns:

  • (String)

Raises:

See Also:

Since:

  • 0.2.0



803
804
805
806
807
# File 'lib/rdf/mixin/enumerable.rb', line 803

def dump(*args, **options)
  writer = RDF::Writer.for(*args)
  raise RDF::WriterError, "No writer found using #{args.inspect}" unless writer
  writer.dump(self, nil, **options)
end

#each_graph {|graph| ... } #each_graphEnumerator<RDF::Graph>

Iterates the given block for each RDF graph in self.

If no block was given, returns an enumerator.

The order in which graphs are yielded is undefined.

Overloads:

See Also:

Since:

  • 0.1.9



701
702
703
704
705
706
707
708
709
710
711
712
# File 'lib/rdf/mixin/enumerable.rb', line 701

def each_graph
  if block_given?
    yield RDF::Graph.new(graph_name: nil, data: self)
    # FIXME: brute force, repositories should override behavior
    if supports?(:graph_name)
      enum_statement.map(&:graph_name).uniq.compact.each do |graph_name|
        yield RDF::Graph.new(graph_name: graph_name, data: self)
      end
    end
  end
  enum_graph
end

#each_object {|object| ... } #each_objectEnumerator<RDF::Term>

Iterates the given block for each unique RDF object term.

If no block was given, returns an enumerator.

The order in which values are yielded is undefined.

Overloads:

  • #each_object {|object| ... }

    This method returns an undefined value.

    Yields:

    • (object)

      each object term

    Yield Parameters:

    Yield Returns:

    • (void)

      ignored

  • #each_objectEnumerator<RDF::Term>

    Returns:

See Also:



506
507
508
509
510
511
512
513
514
515
516
517
518
# File 'lib/rdf/mixin/enumerable.rb', line 506

def each_object # FIXME: deduplication
  if block_given?
    values = {}
    each_statement do |statement|
      value = statement.object
      unless value.nil? || values.include?(value)
        values[value] = true
        yield value
      end
    end
  end
  enum_object
end

#each_predicate {|predicate| ... } #each_predicateEnumerator<RDF::URI>

Iterates the given block for each unique RDF predicate term.

If no block was given, returns an enumerator.

The order in which values are yielded is undefined.

Overloads:

  • #each_predicate {|predicate| ... }

    This method returns an undefined value.

    Yields:

    • (predicate)

      each predicate term

    Yield Parameters:

    Yield Returns:

    • (void)

      ignored

  • #each_predicateEnumerator<RDF::URI>

    Returns:

See Also:



439
440
441
442
443
444
445
446
447
448
449
450
451
# File 'lib/rdf/mixin/enumerable.rb', line 439

def each_predicate
  if block_given?
    values = {}
    each_statement do |statement|
      value = statement.predicate
      unless value.nil? || values.include?(value.to_s)
        values[value.to_s] = true
        yield value
      end
    end
  end
  enum_predicate
end

#each_quad {|subject, predicate, object, graph_name| ... } #each_quadEnumerator<Array(RDF::Resource, RDF::URI, RDF::Term, RDF::Resource)>

Iterates the given block for each RDF quad.

If no block was given, returns an enumerator.

The order in which quads are yielded is undefined.

Overloads:

See Also:



310
311
312
313
314
315
316
317
# File 'lib/rdf/mixin/enumerable.rb', line 310

def each_quad
  if block_given?
    each_statement do |statement|
      yield(*statement.to_quad)
    end
  end
  enum_quad
end

#each_statement {|statement| ... } #each_statementEnumerator<RDF::Statement>

Iterates the given block for each RDF statement.

If no block was given, returns an enumerator.

The order in which statements are yielded is undefined.

Overloads:

See Also:



182
183
184
185
186
187
188
# File 'lib/rdf/mixin/enumerable.rb', line 182

def each_statement(&block)
  if block_given?
    # Invoke {#each} in the containing class:
    each(&block)
  end
  enum_statement
end

#each_subject {|subject| ... } #each_subjectEnumerator<RDF::Resource>

Iterates the given block for each unique RDF subject term.

If no block was given, returns an enumerator.

The order in which values are yielded is undefined.

Overloads:

See Also:



373
374
375
376
377
378
379
380
381
382
383
384
385
# File 'lib/rdf/mixin/enumerable.rb', line 373

def each_subject
  if block_given?
    values = {}
    each_statement do |statement|
      value = statement.subject
      unless value.nil? || values.include?(value.to_s)
        values[value.to_s] = true
        yield value
      end
    end
  end
  enum_subject
end

#each_term {|term| ... } #each_termEnumerator<RDF::Term>

Iterates the given block for each unique RDF term (subject, predicate, object, or graph_name).

If no block was given, returns an enumerator.

The order in which values are yielded is undefined.

Overloads:

See Also:

Since:

  • 2.0



590
591
592
593
594
595
596
597
598
599
600
601
602
603
# File 'lib/rdf/mixin/enumerable.rb', line 590

def each_term
  if block_given?
    values = {}
    each_statement do |statement|
      statement.terms.each do |value|
        unless values.include?(value.hash)
          values[value.hash] = true
          yield value
        end
      end
    end
  end
  enum_term
end

#each_triple {|subject, predicate, object| ... } #each_tripleEnumerator<Array(RDF::Resource, RDF::URI, RDF::Term)>

Iterates the given block for each RDF triple.

If no block was given, returns an enumerator.

The order in which triples are yielded is undefined.

Overloads:

See Also:



247
248
249
250
251
252
253
254
# File 'lib/rdf/mixin/enumerable.rb', line 247

def each_triple
  if block_given?
    each_statement do |statement|
      yield(*statement.to_triple)
    end
  end
  enum_triple
end

#enum_graphEnumerator<RDF::Graph> Also known as: enum_graphs

Returns an enumerator for #each_graph.

Returns:

See Also:

Since:

  • 0.1.9



720
721
722
# File 'lib/rdf/mixin/enumerable.rb', line 720

def enum_graph
  enum_for(:each_graph)
end

#enum_objectEnumerator<RDF::Term> Also known as: enum_objects

Returns an enumerator for #each_object.

Returns:

See Also:



525
526
527
# File 'lib/rdf/mixin/enumerable.rb', line 525

def enum_object
  enum_for(:each_object)
end

#enum_predicateEnumerator<RDF::URI> Also known as: enum_predicates

Returns an enumerator for #each_predicate.

Returns:

See Also:



458
459
460
# File 'lib/rdf/mixin/enumerable.rb', line 458

def enum_predicate
  enum_for(:each_predicate)
end

#enum_quadEnumerator<Array(RDF::Resource, RDF::URI, RDF::Term, RDF::Resource)> Also known as: enum_quads

Returns an enumerator for #each_quad.



324
325
326
327
328
# File 'lib/rdf/mixin/enumerable.rb', line 324

def enum_quad
  Countable::Enumerator.new do |yielder|
    each_quad {|s, p, o, c| yielder << [s, p, o, c]}
  end
end

#enum_statementEnumerator<RDF::Statement> Also known as: enum_statements

Returns an enumerator for #each_statement. FIXME: enum_for doesn’t seem to be working properly in JRuby 1.7, so specs are marked pending

Returns:

See Also:



197
198
199
200
201
202
203
# File 'lib/rdf/mixin/enumerable.rb', line 197

def enum_statement
  # Ensure that statements are queryable, countable and enumerable
  this = self
  Queryable::Enumerator.new do |yielder|
    this.send(:each_statement) {|y| yielder << y}
  end
end

#enum_subjectEnumerator<RDF::Resource> Also known as: enum_subjects

Returns an enumerator for #each_subject.

Returns:

See Also:



392
393
394
# File 'lib/rdf/mixin/enumerable.rb', line 392

def enum_subject
  enum_for(:each_subject)
end

#enum_termEnumerator<RDF::Term> Also known as: enum_terms

Returns an enumerator for #each_term.

Returns:

See Also:

Since:

  • 2.0



611
612
613
# File 'lib/rdf/mixin/enumerable.rb', line 611

def enum_term
  enum_for(:each_term)
end

#enum_tripleEnumerator<Array(RDF::Resource, RDF::URI, RDF::Term)> Also known as: enum_triples

Returns an enumerator for #each_triple.

Returns:

See Also:



261
262
263
264
265
# File 'lib/rdf/mixin/enumerable.rb', line 261

def enum_triple
  Countable::Enumerator.new do |yielder|
    each_triple {|s, p, o| yielder << [s, p, o]}
  end
end

#graph?(graph_name) ⇒ Boolean Also known as: has_graph?

Returns true if self contains the given RDF graph_name.

Parameters:

  • graph_name (RDF::Resource, false)

    Use value false to query for the default graph_name

Returns:

  • (Boolean)


638
639
640
# File 'lib/rdf/mixin/enumerable.rb', line 638

def graph?(graph_name)
  enum_statement.any? {|s| s.graph_name == graph_name}
end

#graph_names(unique: true) ⇒ Array<RDF::Resource>

Returns all unique RDF graph names, other than the default graph.

Parameters:

  • unique (true) (defaults to: true)

Returns:

See Also:

Since:

  • 2.0



624
625
626
627
628
629
630
# File 'lib/rdf/mixin/enumerable.rb', line 624

def graph_names(unique: true)
  unless unique
    enum_statement.map(&:graph_name).compact # TODO: optimize
  else
    enum_graph.map(&:graph_name).compact
  end
end

#invalid?Boolean

Returns true if value is not valid

Returns:

  • (Boolean)

    true or false

Raises:

  • (NotImplementedError)

    unless enumerable supports validation

Since:

  • 0.2.1



117
118
119
# File 'lib/rdf/mixin/enumerable.rb', line 117

def invalid?
  !valid?
end

#object?(value) ⇒ Boolean Also known as: has_object?

Returns true if self contains the given RDF object term.

Parameters:

Returns:

  • (Boolean)


483
484
485
# File 'lib/rdf/mixin/enumerable.rb', line 483

def object?(value)
  enum_object.include?(value)
end

#objects(unique: true) ⇒ Array<RDF::Term>

Returns all unique RDF object terms.

Parameters:

  • unique (true) (defaults to: true)

Returns:

See Also:



470
471
472
473
474
475
476
# File 'lib/rdf/mixin/enumerable.rb', line 470

def objects(unique: true)
  unless unique
    enum_statement.map(&:object) # TODO: optimize
  else
    enum_object.to_a
  end
end

#predicate?(value) ⇒ Boolean Also known as: has_predicate?

Returns true if self contains the given RDF predicate term.

Parameters:

Returns:

  • (Boolean)


417
418
419
# File 'lib/rdf/mixin/enumerable.rb', line 417

def predicate?(value)
  enum_predicate.include?(value)
end

#predicates(unique: true) ⇒ Array<RDF::URI>

Returns all unique RDF predicate terms.

Parameters:

  • unique (true) (defaults to: true)

Returns:

See Also:



404
405
406
407
408
409
410
# File 'lib/rdf/mixin/enumerable.rb', line 404

def predicates(unique: true)
  unless unique
    enum_statement.map(&:predicate) # TODO: optimize
  else
    enum_predicate.to_a
  end
end

#project_graph(graph_name) {|statement| ... } #project_graph(graph_name) ⇒ Enumerable

Limits statements to be from a specific graph.

If no block was given, returns an enumerator.

The order in which statements are yielded is undefined.

Overloads:

  • #project_graph(graph_name) {|statement| ... }

    This method returns an undefined value.

    Parameters:

    • graph_name (RDF::Resource, nil)

      The name of the graph from which statements are taken. Use nil for the default graph.

    Yields:

    • (statement)

      each statement

    Yield Parameters:

    Yield Returns:

    • (void)

      ignored

  • #project_graph(graph_name) ⇒ Enumerable

    Parameters:

    • graph_name (RDF::Resource, false)

      The name of the graph from which statements are taken. Use false for the default graph.

    Returns:

See Also:

Since:

  • 3.0



668
669
670
671
672
673
674
675
676
677
678
679
680
# File 'lib/rdf/mixin/enumerable.rb', line 668

def project_graph(graph_name)
  if block_given?
    self.each do |statement|
      yield statement if statement.graph_name == graph_name
    end
  else
    # Ensure that statements are queryable, countable and enumerable
    this = self
    Queryable::Enumerator.new do |yielder|
      this.send(:project_graph, graph_name) {|y| yielder << y}
    end
  end
end

#quad?(quad) ⇒ Boolean Also known as: has_quad?

Returns true if self contains the given RDF quad.

Parameters:

Returns:

  • (Boolean)


284
285
286
# File 'lib/rdf/mixin/enumerable.rb', line 284

def quad?(quad)
  quads.include?(quad)
end

#quads(**options) ⇒ Array<Array(RDF::Resource, RDF::URI, RDF::Term, RDF::Resource)>

Returns all RDF quads.

Parameters:

  • options (Hash{Symbol => Boolean})

Returns:

See Also:



275
276
277
# File 'lib/rdf/mixin/enumerable.rb', line 275

def quads(**options)
  enum_statement.map(&:to_quad) # TODO: optimize
end

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

Note:

this instantiates an writer; 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)


831
832
833
834
# File 'lib/rdf/mixin/enumerable.rb', line 831

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

#statement?Boolean #statement?(statement) ⇒ Boolean Also known as: has_statement?, include?

Overloads:

  • #statement?Boolean

    Returns false indicating this is not an RDF::Statemenet.

    Returns:

    • (Boolean)

    See Also:

  • #statement?(statement) ⇒ Boolean

    Returns true if self contains the given RDF statement.

    Parameters:

    Returns:

    • (Boolean)


153
154
155
156
157
158
159
160
# File 'lib/rdf/mixin/enumerable.rb', line 153

def statement?(*args)
  case args.length
  when 0 then false
  when 1
    args.first && !enum_statement.find { |s| s.eql?(args.first) }.nil?        
  else raise ArgumentError("wrong number of arguments (given #{args.length}, expected 0 or 1)")
  end
end

#statements(**options) ⇒ Array<RDF::Statement>

Returns all RDF statements.

Parameters:

  • options (Hash{Symbol => Boolean})

Returns:

See Also:



139
140
141
# File 'lib/rdf/mixin/enumerable.rb', line 139

def statements(**options)
  enum_statement.to_a
end

#subject?(value) ⇒ Boolean Also known as: has_subject?

Returns true if self contains the given RDF subject term.

Parameters:

Returns:

  • (Boolean)


351
352
353
# File 'lib/rdf/mixin/enumerable.rb', line 351

def subject?(value)
  enum_subject.include?(value)
end

#subjects(unique: true) ⇒ Array<RDF::Resource>

Returns all unique RDF subject terms.

Parameters:

  • unique (true) (defaults to: true)

Returns:

See Also:



338
339
340
341
342
343
344
# File 'lib/rdf/mixin/enumerable.rb', line 338

def subjects(unique: true)
  unless unique
    enum_statement.map(&:subject) # TODO: optimize
  else
    enum_subject.to_a
  end
end

#supports?(feature) ⇒ Boolean

Returns true if this enumerable supports the given feature.

Supported features include: * :graph_name supports statements with a graph_name, allowing multiple named graphs * :inference supports RDFS inferrence of queryable contents. * :literal_equality' preserves [term-equality](https://www.w3.org/TR/rdf11-concepts/#dfn-literal-term-equality) for literals. Literals are equal only if their lexical values and datatypes are equal, character by character. Literals may be "inlined" to value-space for efficiency only if:literal_equalityisfalse. *:validityallows a concrete Enumerable implementation to indicate that it does or does not support valididty checking. By default implementations are assumed to support validity checking. *:skolemizesupports [Skolemization](https://www.w3.org/wiki/BnodeSkolemization) of anEnumerable. Implementations supporting this feature must implement a#skolemizemethod, taking a base URI used for minting URIs for BNodes as stable identifiers and a#deskolemizemethod, also taking a base URI used for turning URIs having that prefix back into the same BNodes which were originally skolemized. *:rdf_fullsupports RDF 1.2 Full profile, including support for embedded Triple Terms. *:quoted_triplessupports RDF-star quoted triples. *:base_direction` supports RDF 1.2 directional language-tagged strings.

Parameters:

  • feature (Symbol, #to_sym)

Returns:

  • (Boolean)

Since:

  • 0.3.5



93
94
95
# File 'lib/rdf/mixin/enumerable.rb', line 93

def supports?(feature)
  feature == :validity || feature == :literal_equality
end

#term?Boolean #term?(value) ⇒ Boolean Also known as: has_term?

Overloads:

  • #term?Boolean

    Returns false indicating this is not an RDF::Statemenet.

    Returns:

    • (Boolean)

    See Also:

  • #term?(value) ⇒ Boolean

    Returns true if self contains the given RDF subject term.

    Parameters:

    Returns:

    • (Boolean)

    Since:

    • 2.0



563
564
565
566
567
568
569
# File 'lib/rdf/mixin/enumerable.rb', line 563

def term?(*args)
  case args.length
  when 0 then super
  when 1 then args.first && enum_term.include?(args.first)
  else raise ArgumentError("wrong number of arguments (given #{args.length}, expected 0 or 1)")
  end
end

#terms(unique: true) ⇒ Array<RDF::Resource>

Returns all unique RDF terms (subjects, predicates, objects, and graph_names).

Examples:

finding all Blank Nodes used within an enumerable

enumberable.terms.select(&:node?)

Parameters:

  • unique (true) (defaults to: true)

Returns:

See Also:

  • #each_resource
  • #enum_resource

Since:

  • 2.0



541
542
543
544
545
546
547
548
549
550
# File 'lib/rdf/mixin/enumerable.rb', line 541

def terms(unique: true)
  unless unique
    enum_statement.
      map(&:terms).
      flatten.
      compact
  else
    enum_term.to_a
  end
end

#to_aArray

Returns all RDF statements in self as an array.

Mixes in RDF::Enumerable into the returned object.

Returns:

  • (Array)


752
753
754
# File 'lib/rdf/mixin/enumerable.rb', line 752

def to_a
  super.extend(RDF::Enumerable)
end

#to_hHash

Returns all RDF object terms indexed by their subject and predicate terms.

The return value is a Hash instance that has the structure: {subject => {predicate => [*objects]}}.

Returns:

  • (Hash)


776
777
778
779
780
781
782
783
784
# File 'lib/rdf/mixin/enumerable.rb', line 776

def to_h
  result = {}
  each_statement do |statement|
    result[statement.subject] ||= {}
    values = (result[statement.subject][statement.predicate] ||= [])
    values << statement.object unless values.include?(statement.object)
  end
  result
end

#to_setSet

Returns all RDF statements in self as a set.

Mixes in RDF::Enumerable into the returned object.

Returns:

  • (Set)

Since:

  • 0.2.0



763
764
765
766
# File 'lib/rdf/mixin/enumerable.rb', line 763

def to_set
  require 'set' unless defined?(::Set)
  super.extend(RDF::Enumerable)
end

#triple?(triple) ⇒ Boolean Also known as: has_triple?

Returns true if self contains the given RDF triple.

Parameters:

Returns:

  • (Boolean)


222
223
224
# File 'lib/rdf/mixin/enumerable.rb', line 222

def triple?(triple)
  triples.include?(triple)
end

#triples(**options) ⇒ Array<Array(RDF::Resource, RDF::URI, RDF::Term)>

Returns all RDF triples.

Parameters:

  • options (Hash{Symbol => Boolean})

Returns:

See Also:



213
214
215
# File 'lib/rdf/mixin/enumerable.rb', line 213

def triples(**options)
  enum_statement.map(&:to_triple) # TODO: optimize
end

#valid?Boolean

Returns true if all statements are valid

Returns:

  • (Boolean)

    true or false

Raises:

  • (NotImplementedError)

    unless enumerable supports validation

Since:

  • 0.3.11



103
104
105
106
107
108
109
# File 'lib/rdf/mixin/enumerable.rb', line 103

def valid?
  raise NotImplementedError, "#{self.class} does not support validation" unless supports?(:validity)
  each_statement do |s|
    return false if s.invalid?
  end
  true
end

#validate!RDF::Enumerable Also known as: validate

Default validate! implementation, overridden in concrete classes

Returns:

Raises:

  • (ArgumentError)

    if the value is invalid

Since:

  • 0.3.9



126
127
128
129
# File 'lib/rdf/mixin/enumerable.rb', line 126

def validate!
  raise ArgumentError if supports?(:validity) && invalid?
  self
end