Class: ShEx::Algebra::Schema

Inherits:
Operator show all
Includes:
Satisfiable
Defined in:
lib/shex/algebra/schema.rb

Constant Summary collapse

NAME =
:schema

Constants inherited from Operator

Operator::ARITY

Instance Attribute Summary collapse

Attributes inherited from Operator

#operands, #options, #schema

Instance Method Summary collapse

Methods included from Satisfiable

#not_satisfies?, #satisfiable?, #triple_expressions

Methods inherited from Operator

#closed?, #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?

Constructor Details

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

Instance Attribute Details

#graphRDF::Queryable

Graph to validate

Returns:

  • (RDF::Queryable)


9
10
11
# File 'lib/shex/algebra/schema.rb', line 9

def graph
  @graph
end

#mapHash{RDF::Resource => RDF::Resource} (readonly)

Map of nodes to shapes

Returns:

  • (Hash{RDF::Resource => RDF::Resource})


13
14
15
# File 'lib/shex/algebra/schema.rb', line 13

def map
  @map
end

Instance Method Details

#each_descendant(depth = 0) {|operator| ... } ⇒ Enumerator

Enumerate via depth-first recursive descent over operands, yielding each operator

Yields:

  • operator

Yield Parameters:

  • operator (Object)

Returns:

  • (Enumerator)


95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/shex/algebra/schema.rb', line 95

def each_descendant(depth = 0, &block)
  if block_given?
    super(depth + 1, &block)
    shapes.values.each do |op|
      op.each_descendant(depth + 1, &block) if op.respond_to?(:each_descendant)

      case block.arity
      when 1 then block.call(op)
      else block.call(depth, op)
      end
    end
  end
  enum_for(:each_descendant)
end

#external_schemasArray<Schema>

Externally loaded schemas, lazily evaluated

Returns:



77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/shex/algebra/schema.rb', line 77

def external_schemas
  @external_schemas = Array(@external_schemas).map do |extern|
    schema = case extern
    when Schema then extern
    else
      status "Load extern #{extern}"
      ShEx.open(extern, logger: options[:logger])
    end
    schema.graph = graph
    schema
  end
end

#satisfies?(n, g, m, shapeExterns: [], **options) ⇒ Boolean

Match on schema. Finds appropriate shape for node, and matches that shape.

FIXME: set of node/shape pairs

Parameters:

  • n (RDF::Resource)
  • g (RDF::Queryable)
  • m (Hash{RDF::Resource => RDF::Resource})
  • shapeExterns (Array<Schema, String>) (defaults to: [])

    ([]) One or more schemas, or paths to ShEx schema resources used for finding external shapes.

Returns:

  • (Boolean)

    ‘true` if satisfied, `false` if it does not apply

Raises:



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/shex/algebra/schema.rb', line 26

def satisfies?(n, g, m, shapeExterns: [], **options)
  @graph = g
  @external_schemas = shapeExterns
  # Make sure they're URIs
  @map = m.inject({}) {|memo, (k,v)| memo.merge(k.to_s => v.to_s)}

  # First, evaluate semantic acts
  semantic_actions.all? do |op|
    op.satisfies?([])
  end

  # Next run any start expression
  if start
    status("start") {"expression: #{start.to_sxp}"}
    start.satisfies?(n)
  end

  label = @map[n.to_s]
  if label && !label.empty?
    shape = shapes[label]
    structure_error("No shape found for #{label}") unless shape

    # If `n` is a Blank Node, we won't find it through normal matching, find an equivalent node in the graph having the same label
    if n.is_a?(RDF::Node)
      nn = graph.enum_term.detect {|t| t.id == n.id}
      n = nn if nn
    end

    shape.satisfies?(n)
  end
  status "schema satisfied"
  true
end

#shapesHash{RDF::Resource => Operator}

Shapes as a hash

Returns:



63
64
65
66
67
68
69
70
71
72
# File 'lib/shex/algebra/schema.rb', line 63

def shapes
  @shapes ||= begin
    shapes = operands.
    detect {|op| op.is_a?(Array) && op.first == :shapes}
    shapes = shapes ? shapes.last : {}
    shapes.inject({}) do |memo, (label, operand)|
      memo.merge(label.to_s => operand)
    end
  end
end

#startObject

Start action, if any



112
113
114
# File 'lib/shex/algebra/schema.rb', line 112

def start
  @start ||= operands.detect {|op| op.is_a?(Start)}
end

#validate!SPARQL::Algebra::Expression

Validate shapes, in addition to other operands

Returns:

  • (SPARQL::Algebra::Expression)

    ‘self`

Raises:

  • (ArgumentError)

    if the value is invalid



120
121
122
123
# File 'lib/shex/algebra/schema.rb', line 120

def validate!
  shapes.values.each {|op| op.validate! if op.respond_to?(:validate!)}
  super
end