Class: ShEx::Algebra::OneOf

Inherits:
Operator show all
Includes:
TripleExpression
Defined in:
lib/shex/algebra/one_of.rb

Constant Summary collapse

NAME =
:oneOf

Constants inherited from Operator

ShEx::Algebra::Operator::ARITY

Instance Attribute Summary

Attributes inherited from Operator

#operands, #options, #schema

Instance Method Summary collapse

Methods included from TripleExpression

#maximum, #minimum, #triple_constraints, #triple_expression?

Methods inherited from Operator

#closed?, #each_descendant, #eql?, #first_ancestor, #initialize, #inspect, #not_matched, #not_satisfied, #operand, #parent, #parent=, #satisfiable?, #semact?, #semantic_actions, #status, #structure_error, #to_sxp, #to_sxp_bin, #triple_expression?, #validate!

Constructor Details

This class inherits a constructor from ShEx::Algebra::Operator

Instance Method Details

#matches(t) ⇒ Array<RDF::Statement]

‘expr` is a OneOf and there is some shape expression `se2` in shapeExprs such that a `matches(T, se2, m)`…

Parameters:

  • t (Array<RDF::Statement>)

Returns:

  • (Array<RDF::Statement])

    Array<RDF::Statement]



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/shex/algebra/one_of.rb', line 12

def matches(t)
  results = []
  statements = t.dup
  num_iters = 0
  max = maximum

  # OneOf is greedy, and consumes triples from every sub-expression, although only one is requred it succeed. Cardinality is somewhat complicated, as if two expressions match, this works for either a cardinality of one or two. Or two passes with just one match on each pass.
  status ""
  while num_iters < max
    matched_something = operands.select {|o| o.is_a?(TripleExpression)}.any? do |op|
      begin
        matched = op.matches(statements)
        results += matched
        statements -= matched
        status "matched #{t.first.to_sxp}"
      rescue NotMatched => e
        log_recover("oneOf: ignore error: #{e.message}", depth: options.fetch(:depth, 0))
        false
      end
    end
    break unless matched_something
    num_iters += 1
    status "matched #{results.length} statements after #{num_iters} iterations"
  end

  # Max violations handled in Shape
  not_matched "Minimum Cardinality Violation: #{num_iters} < #{minimum}" if
    num_iters < minimum

  # Last, evaluate semantic acts
  semantic_actions.all? do |op|
    op.satisfies?(results)
  end unless results.empty?

  status "one of satisfied"
  results
end