Class: RDF::Query::Solution

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/rdf/query/solution.rb

Overview

An RDF query solution.

Examples:

Iterating over every binding in the solution

solution.each_binding  { |name, value| puts value.inspect }
solution.each_variable { |variable| puts variable.value.inspect }

Iterating over every value in the solution

solution.each_value    { |value| puts value.inspect }

Checking whether a variable is bound or unbound

solution.bound?(:title)
solution.unbound?(:mbox)

Retrieving the value of a bound variable

solution[:mbox]
solution.mbox

Retrieving all bindings in the solution as a ‘Hash`

solution.to_h       #=> {mbox: "[email protected]", ...}

Since:

  • 0.3.0

Constant Summary collapse

INSTANCE_METHODS =

Temporarily remember instance method for deprecation message in ‘method_missing`.

Since:

  • 0.3.0

instance_methods

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Enumerable

#canonicalize, #canonicalize!, #dump, #each_graph, #each_object, #each_predicate, #each_quad, #each_statement, #each_subject, #each_term, #each_triple, #enum_graph, #enum_object, #enum_predicate, #enum_quad, #enum_statement, #enum_subject, #enum_term, #enum_triple, #graph?, #graph_names, #invalid?, #object?, #objects, #predicate?, #predicates, #project_graph, #quad?, #quads, #statement?, #statements, #subject?, #subjects, #supports?, #term?, #terms, #to_set, #triple?, #triples, #valid?, #validate!

Methods included from Util::Aliasing::LateBound

#alias_method

Methods included from Countable

#count, #empty?

Constructor Details

#initialize(bindings = {}) {|solution| ... } ⇒ Solution

Initializes the query solution.

Parameters:

  • bindings (Hash{Symbol => RDF::Term}) (defaults to: {})

Yields:

  • (solution)

Since:

  • 0.3.0



42
43
44
45
46
47
48
49
50
51
# File 'lib/rdf/query/solution.rb', line 42

def initialize(bindings = {}, &block)
  @bindings = bindings.to_h

  if block_given?
    case block.arity
      when 1 then block.call(self)
      else instance_eval(&block)
    end
  end
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#binding(name) ⇒ RDF::Term (protected)

Return the binding for this name

Parameters:

  • name (Symbol)

Returns:

Since:

  • 0.3.0



347
348
349
350
351
352
353
354
355
356
357
358
359
# File 'lib/rdf/query/solution.rb', line 347

def method_missing(name, *args, &block)
  if args.empty? && @bindings.key?(name.to_sym)
    if INSTANCE_METHODS.include?(name)
      warn "[DEPRECATION] RDF::Query::Solution##{name} is an overridden instance method.\n" +
           "Its use as a solution accessor is deprecated and will be removed in a future version.\n" +
           "Use #[] for safe access.\n" +
           "Called from #{Gem.location_of_caller.join(':')}"
    end
    @bindings[name.to_sym]
  else
    super # raises NoMethodError
  end
end

Instance Attribute Details

#bindingsObject (readonly)

Since:

  • 0.3.0



54
55
56
# File 'lib/rdf/query/solution.rb', line 54

def bindings
  @bindings
end

Instance Method Details

#==(other) ⇒ Object

Equals of solution

Since:

  • 0.3.0



329
330
331
# File 'lib/rdf/query/solution.rb', line 329

def ==(other)
  other.is_a?(Solution) && @bindings == other.bindings
end

#[](name) ⇒ RDF::Term

Returns the value of the variable ‘name`.

Parameters:

  • name (Symbol, #to_sym)

    the variable name

Returns:

Since:

  • 0.3.0



192
193
194
# File 'lib/rdf/query/solution.rb', line 192

def [](name)
  @bindings[name.to_sym]
end

#[]=(name, value) ⇒ RDF::Term

Binds or rebinds the variable ‘name` to the given `value`.

Parameters:

  • name (Symbol, #to_sym)

    the variable name

  • value (RDF::Term)

Returns:

Since:

  • 0.3.0



204
205
206
# File 'lib/rdf/query/solution.rb', line 204

def []=(name, value)
  @bindings[name.to_sym] = value.is_a?(RDF::Term) ? value : RDF::Literal(value)
end

#bound?(name) ⇒ Boolean

Returns ‘true` if the variable `name` is bound in this solution.

Parameters:

  • name (Symbol, #to_sym)

    the variable name

Returns:

  • (Boolean)

    ‘true` or `false`

Since:

  • 0.3.0



172
173
174
# File 'lib/rdf/query/solution.rb', line 172

def bound?(name)
  !unbound?(name)
end

#compatible?(other) ⇒ Boolean

Compatible Mappings

Two solution mappings u1 and u2 are compatible if, for every variable v in dom(u1) and in dom(u2), u1(v) = u2(v).

Parameters:

Returns:

  • (Boolean)

See Also:

Since:

  • 0.3.0



268
269
270
271
272
# File 'lib/rdf/query/solution.rb', line 268

def compatible?(other)
  @bindings.all? do |k, v|
    !other.to_h.key?(k) || other[k].eql?(v)
  end
end

#disjoint?(other) ⇒ Boolean

Disjoint mapping

A solution is disjoint with another solution if it shares no common variables in their domains.

Parameters:

Returns:

  • (Boolean)

See Also:

Since:

  • 0.3.0



282
283
284
285
286
# File 'lib/rdf/query/solution.rb', line 282

def disjoint?(other)
  @bindings.none? do |k, v|
    v && other.to_h.key?(k) && other[k].eql?(v)
  end
end

#dupRDF::Statement

Duplicate solution, preserving patterns

Returns:

Since:

  • 0.3.0



255
256
257
# File 'lib/rdf/query/solution.rb', line 255

def dup
  merge({})
end

#each_binding {|name, value| ... } ⇒ Enumerator Also known as: each

Enumerates over every variable binding in this solution.

Yields:

  • (name, value)

Yield Parameters:

Returns:

Since:

  • 0.3.0



63
64
65
66
# File 'lib/rdf/query/solution.rb', line 63

def each_binding(&block)
  @bindings.each(&block) if block_given?
  enum_binding
end

#each_name {|name| ... } ⇒ Enumerator Also known as: each_key

Enumerates over every variable name in this solution.

Yields:

  • (name)

Yield Parameters:

  • name (Symbol)

Returns:

Since:

  • 0.3.0



84
85
86
87
# File 'lib/rdf/query/solution.rb', line 84

def each_name(&block)
  @bindings.each_key(&block) if block_given?
  enum_name
end

#each_value {|value| ... } ⇒ Enumerator

Enumerates over every variable value in this solution.

Yields:

  • (value)

Yield Parameters:

Returns:

Since:

  • 0.3.0



105
106
107
108
# File 'lib/rdf/query/solution.rb', line 105

def each_value(&block)
  @bindings.each_value(&block) if block_given?
  enum_value
end

#each_variable {|variable| ... } ⇒ Enumerator

Enumerates over every variable in this solution.

Yields:

  • (variable)

Yield Parameters:

Returns:

Since:

  • 0.3.0



148
149
150
151
152
153
154
155
# File 'lib/rdf/query/solution.rb', line 148

def each_variable
  if block_given?
    @bindings.each do |name, value|
      yield Variable.new(name, value)
    end
  end
  enum_variable
end

#enum_bindingEnumerator<RDF::Resource>

Returns an enumerator for #each_binding.

Returns:

See Also:

Since:

  • 0.3.0



74
75
76
# File 'lib/rdf/query/solution.rb', line 74

def enum_binding
  enum_for(:each_binding)
end

#enum_nameEnumerator<RDF::Resource>

Returns an enumerator for #each_name.

Returns:

See Also:

Since:

  • 0.3.0



95
96
97
# File 'lib/rdf/query/solution.rb', line 95

def enum_name
  enum_for(:each_name)
end

#enum_valueEnumerator<RDF::Resource>

Returns an enumerator for #each_value.

Returns:

See Also:

Since:

  • 0.3.0



115
116
117
# File 'lib/rdf/query/solution.rb', line 115

def enum_value
  enum_for(:each_value)
end

#enum_variableEnumerator<RDF::Resource>

Returns an enumerator for #each_variable.

Returns:

See Also:

Since:

  • 0.3.0



162
163
164
# File 'lib/rdf/query/solution.rb', line 162

def enum_variable
  enum_for(:each_variable)
end

#eql?(other) ⇒ Boolean

Equivalence of solution

Returns:

  • (Boolean)

Since:

  • 0.3.0



323
324
325
# File 'lib/rdf/query/solution.rb', line 323

def eql?(other)
  other.is_a?(Solution) && @bindings.eql?(other.bindings)
end

#hashInteger

Integer hash of this solution

Returns:

  • (Integer)

Since:

  • 0.3.0



317
318
319
# File 'lib/rdf/query/solution.rb', line 317

def hash
  @bindings.hash
end

#inspectString

Returns:

  • (String)

Since:

  • 0.3.0



335
336
337
# File 'lib/rdf/query/solution.rb', line 335

def inspect
  sprintf("#<%s:%#0x(%s)>", self.class.name, __id__, @bindings.inspect)
end

#isomorphic_with?(other) ⇒ Boolean

Isomorphic Mappings Two solution mappings u1 and u2 are isomorphic if, for every variable v in dom(u1) and in dom(u2), u1(v) = u2(v).

Parameters:

Returns:

  • (Boolean)

Since:

  • 0.3.0



296
297
298
299
300
# File 'lib/rdf/query/solution.rb', line 296

def isomorphic_with?(other)
  @bindings.all? do |k, v|
    !other.to_h.key?(k) || other[k].eql?(v)
  end
end

#merge(other) ⇒ RDF::Query::Solution

Merges the bindings from the given ‘other` query solution with a copy of this one.

Parameters:

Returns:

Since:

  • 0.3.0



248
249
250
# File 'lib/rdf/query/solution.rb', line 248

def merge(other)
  self.class.new(@bindings.dup).merge!(other)
end

#merge!(other) ⇒ void

This method returns an undefined value.

Merges the bindings from the given ‘other` query solution into this one, overwriting any existing ones having the same name.

## RDF-star

If merging a binding for a statement to a pattern, merge their embedded solutions.

Parameters:

Since:

  • 0.3.0



221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
# File 'lib/rdf/query/solution.rb', line 221

def merge!(other)
  @bindings.merge!(other.to_h) do |key, v1, v2|
    # Don't merge a pattern over a statement
    # This happens because JOIN does a reverse merge,
    # and a pattern is set in v2.
    v2.is_a?(Pattern) ? v1 : v2
  end
  # Merge bindings from patterns
  embedded_solutions = []
  @bindings.each do |k, v|
    if v.is_a?(Pattern) && other[k].is_a?(RDF::Statement)
      embedded_solutions << v.solution(other[k])
    end
  end
  # Merge embedded solutions
  embedded_solutions.each {|soln| merge!(soln)}
  self
end

#to_aArray<Array(Symbol, RDF::Term)>

Returns:

Since:

  • 0.3.0



304
305
306
# File 'lib/rdf/query/solution.rb', line 304

def to_a
  @bindings.to_a
end

#to_hHash{Symbol => RDF::Term}

Returns:

Since:

  • 0.3.0



310
311
312
# File 'lib/rdf/query/solution.rb', line 310

def to_h
  @bindings.dup
end

#unbound?(name) ⇒ Boolean

Returns ‘true` if the variable `name` is unbound in this solution.

Parameters:

  • name (Symbol, #to_sym)

    the variable name

Returns:

  • (Boolean)

    ‘true` or `false`

Since:

  • 0.3.0



182
183
184
# File 'lib/rdf/query/solution.rb', line 182

def unbound?(name)
  @bindings[name.to_sym].nil?
end

#variable?Boolean #variable?(variables) ⇒ Object Also known as: variables?, has_variables?

‘variables`.

@param  [Array<Symbol, #to_sym>] variables
@return [Boolean]

Overloads:

  • #variable?Boolean

    Returns ‘false`.

    Returns:

    • (Boolean)
  • #variable?(variables) ⇒ Object

    Returns ‘true` if this solution contains bindings for any of the given

Since:

  • 0.3.0



131
132
133
134
135
136
137
138
# File 'lib/rdf/query/solution.rb', line 131

def variable?(*args)
  case args.length
  when 0 then false
  when 1
    args.first.any? { |variable| bound?(variable) }
  else raise ArgumentError("wrong number of arguments (given #{args.length}, expected 0 or 1)")
  end
end