class SHACL::Shapes

The set of shapes loaded from a graph.

Constants

SHAPES_FRAME

Attributes

loaded_graphs[R]

The graphs which have been loaded as shapes

@return [Array<RDF::URI>]

shape_json[R]

The JSON used to instantiate shapes

@return [Array<Hash>]

Public Class Methods

from_graph(graph, loaded_graphs: [], **options) click to toggle source

Initializes the shapes from `graph`loading `owl:imports` until all references are loaded.

The shapes come from the following:

  • Instances of `sh:NodeShape` or `sh:PropertyShape`

  • resources that have any of the properties `sh:targetClass`, `sh:targetNode`, `sh:targetObjectsOf`, or `sh:targetSubjectsOf`.

@param [RDF::Graph] graph @param [Array<RDF::URI>] loaded_graphs = [] @param [Hash{Symbol => Object}] options @return [Shapes] @raise [SHACL::Error]

# File lib/shacl/shapes.rb, line 34
def self.from_graph(graph, loaded_graphs: [], **options)
  @loded_graphs = loaded_graphs

  import_count = 0
  while (imports = graph.query({predicate: RDF::OWL.imports}).map(&:object)).count > import_count
    # Load each imported graph
    imports.each do |ref|
      graph.load(imports)
      loaded_graphs << ref
      import_count += 1
    end
  end

  # Serialize the graph as framed JSON-LD and initialize patterns, recursively.
  shape_json = JSON::LD::API.fromRdf(graph, useNativeTypes: true) do |expanded|
    JSON::LD::API.frame(expanded, SHAPES_FRAME, omitGraph: false, embed: '@always', expanded: true)
  end['@graph']

  # Create an array of the framed shapes
  shapes = self.new(shape_json.map {|o| Algebra.from_json(o, **options)})
  shapes.instance_variable_set(:@shape_json, shape_json)
  shapes
end
from_queryable(queryable, **options) click to toggle source

Retrieve shapes from a sh:shapesGraph reference within the queryable

@param [RDF::Queryable] queryable

The data graph which may contain references to the shapes graph

@param [Hash{Symbol => Object}] options @return [Shapes] @raise [SHACL::Error]

# File lib/shacl/shapes.rb, line 66
def self.from_queryable(queryable, **options)
  # Query queryable to find one ore more shapes graphs
  graphs = queryable.query({predicate: RDF::Vocab::SHACL.shapesGraph}).objects
  graph = RDF::Graph.new do |g|
    graphs.each {|iri| g.load(iri)}
  end
  from_graph(graph, loaded_graphs: graphs, **options)
end

Public Instance Methods

execute(graph, depth: 0, **options) click to toggle source

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

@param [RDF::Queryable] graph @return [Hash{RDF::Term => Array<ValidationResult>}] Returns ValidationResults, a hash of focus nodes to the results of their associated shapes @param [Hash{Symbol => Object}] options @option options [RDF::Term] :focus

An explicit focus node, overriding any defined on the top-level shaps.

@return [SHACL::ValidationReport]

# File lib/shacl/shapes.rb, line 84
def execute(graph, depth: 0, **options)
  self.each do |shape|
    shape.graph = graph
    shape.each_descendant do |op|
      op.graph = graph
    end
  end

  # Execute all shapes against their target nodes
  ValidationReport.new(self.map do |shape|
    nodes = Array(options.fetch(:focus, shape.targetNodes))
    nodes.map do |node|
      shape.conforms(node, depth: depth + 1)
    end
  end.flatten)
end
to_sxp() click to toggle source
# File lib/shacl/shapes.rb, line 105
def to_sxp
  to_sxp_bin.to_sxp
end
to_sxp_bin() click to toggle source
Calls superclass method
# File lib/shacl/shapes.rb, line 101
def to_sxp_bin
  [:shapes, super]
end