Class: SHACL::Shapes
- Inherits:
-
Array
- Object
- Array
- SHACL::Shapes
- Includes:
- RDF::Util::Logger
- Defined in:
- lib/shacl/shapes.rb
Overview
The set of shapes loaded from a graph.
Constant Summary collapse
- SHAPES_FRAME =
JSON.parse(%({ "@context": { "id": "@id", "type": {"@id": "@type", "@container": "@set"}, "@vocab": "http://www.w3.org/ns/shacl#", "owl": "http://www.w3.org/2002/07/owl#", "rdfs": "http://www.w3.org/2000/01/rdf-schema#", "shacl": "http://www.w3.org/ns/shacl#", "sh": "http://www.w3.org/ns/shacl#", "xsd": "http://www.w3.org/2001/XMLSchema#", "and": {"@type": "@id"}, "annotationProperty": {"@type": "@id"}, "class": {"@type": "@id"}, "comment": "http://www.w3.org/2000/01/rdf-schema#comment", "condition": {"@type": "@id"}, "datatype": {"@type": "@vocab"}, "declare": {"@type": "@id"}, "disjoint": {"@type": "@id"}, "entailment": {"@type": "@id"}, "equals": {"@type": "@id"}, "ignoredProperties": {"@type": "@id", "@container": "@list"}, "imports": {"@id": "owl:imports", "@type": "@id"}, "in": {"@type": "@none", "@container": "@list"}, "inversePath": {"@type": "@id"}, "label": "http://www.w3.org/2000/01/rdf-schema#label", "languageIn": {"@container": "@list"}, "lessThan": {"@type": "@id"}, "lessThanOrEquals": {"@type": "@id"}, "namespace": {"@type": "xsd:anyURI"}, "nodeKind": {"@type": "@vocab"}, "or": {"@type": "@id"}, "path": {"@type": "@none"}, "prefixes": {"@type": "@id"}, "property": {"@type": "@id"}, "severity": {"@type": "@vocab"}, "sparql": {"@type": "@id"}, "targetClass": {"@type": "@id"}, "targetNode": {"@type": "@none"}, "xone": {"@type": "@id"} }, "and": {}, "class": {}, "datatype": {}, "in": {"@embed": "@never"}, "node": {}, "nodeKind": {}, "not": {}, "or": {}, "property": {}, "sparql": {}, "targetClass": {}, "targetNode": {}, "targetObjectsOf": {}, "xone": {}, "targetSubjectsOf": {} })).freeze
- COMPONENTS_FRAME =
JSON.parse(%({ "@context": { "id": "@id", "type": {"@id": "@type", "@container": "@set"}, "@vocab": "http://www.w3.org/ns/shacl#", "owl": "http://www.w3.org/2002/07/owl#", "rdfs": "http://www.w3.org/2000/01/rdf-schema#", "shacl": "http://www.w3.org/ns/shacl#", "sh": "http://www.w3.org/ns/shacl#", "xsd": "http://www.w3.org/2001/XMLSchema#", "and": {"@type": "@id"}, "annotationProperty": {"@type": "@id"}, "class": {"@type": "@id"}, "comment": "http://www.w3.org/2000/01/rdf-schema#comment", "condition": {"@type": "@id"}, "datatype": {"@type": "@vocab"}, "declare": {"@type": "@id"}, "disjoint": {"@type": "@id"}, "entailment": {"@type": "@id"}, "equals": {"@type": "@id"}, "ignoredProperties": {"@type": "@id", "@container": "@list"}, "imports": {"@id": "owl:imports", "@type": "@id"}, "in": {"@type": "@none", "@container": "@list"}, "inversePath": {"@type": "@id"}, "label": "http://www.w3.org/2000/01/rdf-schema#label", "languageIn": {"@container": "@list"}, "lessThan": {"@type": "@id"}, "lessThanOrEquals": {"@type": "@id"}, "namespace": {"@type": "xsd:anyURI"}, "nodeKind": {"@type": "@vocab"}, "or": {"@type": "@id"}, "path": {"@type": "@id"}, "prefixes": {"@type": "@id"}, "property": {"@type": "@id"}, "severity": {"@type": "@vocab"}, "sparql": {"@type": "@id"}, "targetClass": {"@type": "@id"}, "targetNode": {"@type": "@none"}, "xone": {"@type": "@id"} }, "@type": "ConstraintComponent" })).freeze
Instance Attribute Summary collapse
-
#loaded_graphs ⇒ Array<RDF::URI>
readonly
The graphs which have been loaded as shapes.
-
#shape_json ⇒ Array<Hash>
readonly
The JSON used to instantiate shapes.
-
#shapes_graph ⇒ RDF::Graph
readonly
The original shapes graph.
Class Method Summary collapse
-
.from_graph(graph, loaded_graphs: [], **options) ⇒ Shapes
Initializes the shapes from
graph
loadingowl:imports
until all references are loaded. -
.from_queryable(queryable, **options) ⇒ Shapes
Retrieve shapes from a sh:shapesGraph reference within the queryable.
Instance Method Summary collapse
-
#execute(graph, depth: 0, **options) ⇒ Hash{RDF::Term => Array<ValidationResult>}, SHACL::ValidationReport
Match on schema.
-
#to_sxp(**options) ⇒ String
Transform Shapes into an SXP.
- #to_sxp_bin ⇒ Object
Instance Attribute Details
#loaded_graphs ⇒ Array<RDF::URI> (readonly)
The graphs which have been loaded as shapes
21 22 23 |
# File 'lib/shacl/shapes.rb', line 21 def loaded_graphs @loaded_graphs end |
#shape_json ⇒ Array<Hash> (readonly)
The JSON used to instantiate shapes
26 27 28 |
# File 'lib/shacl/shapes.rb', line 26 def shape_json @shape_json end |
#shapes_graph ⇒ RDF::Graph (readonly)
The original shapes graph
15 16 17 |
# File 'lib/shacl/shapes.rb', line 15 def shapes_graph @shapes_graph end |
Class Method Details
.from_graph(graph, loaded_graphs: [], **options) ⇒ Shapes
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
.
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/shacl/shapes.rb', line 41 def self.from_graph(graph, loaded_graphs: [], **) @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| # Don't try import if the import subject is already in the graph unless graph.subject?(ref) begin [:logger].info('Shapes') {"load import #{ref}"} if [:logger].respond_to?(:info) graph.load(ref) loaded_graphs << ref rescue IOError => e # Skip import [:logger].warn('Shapes') {"load import #{ref}"} if [:logger].respond_to?(:warn) end end import_count += 1 end end # Serialize the graph as framed JSON-LD and initialize patterns, recursively. = JSON::LD::API.fromRdf(graph, useNativeTypes: true) # Node and Property constraints shape_json = JSON::LD::API.frame(, SHAPES_FRAME, omitGraph: false, embed: '@always', expanded: true)['@graph'] # Any defined Constraint Components components = JSON::LD::API.frame(, COMPONENTS_FRAME, omitGraph: false, embed: '@always', expanded: true)['@graph'] # Extract any constraint components and merge to top-level shape_json = components + shape_json # Create an array of the framed shapes shapes = self.new(shape_json.map {|o| Algebra.from_json(o, **)}) shapes.instance_variable_set(:@shape_json, shape_json) shapes.instance_variable_set(:@shapes_graph, graph) shapes end |
.from_queryable(queryable, **options) ⇒ Shapes
Retrieve shapes from a sh:shapesGraph reference within the queryable
96 97 98 99 100 101 102 103 |
# File 'lib/shacl/shapes.rb', line 96 def self.from_queryable(queryable, **) # Query queryable to find one ore more shapes graphs graph_names = queryable.query({predicate: RDF::Vocab::SHACL.shapesGraph}).objects graph = RDF::Graph.new(graph_name: graph_names.first, data: RDF::Repository.new) do |g| graph_names.each {|iri| g.load(iri, graph_name: graph_names.first)} end from_graph(graph, loaded_graphs: graph_names, **) end |
Instance Method Details
#execute(graph, depth: 0, **options) ⇒ Hash{RDF::Term => Array<ValidationResult>}, SHACL::ValidationReport
Match on schema. Finds appropriate shape for node, and matches that shape.
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/shacl/shapes.rb', line 116 def execute(graph, depth: 0, **) self.each do |shape| shape.graph = graph shape.shapes_graph = shapes_graph shape.each_descendant do |op| op.instance_variable_set(:@logger, [:logger]) if [:logger] && op.respond_to?(:execute) op.graph = graph if op.respond_to?(:graph=) op.shapes_graph = shapes_graph if op.respond_to?(:shapes_graph=) end end # Execute all shapes against their target nodes ValidationReport.new(self.map do |shape| nodes = Array(.fetch(:focus, shape.targetNodes)) nodes.map do |node| shape.conforms(node, depth: depth + 1) end end.flatten) end |
#to_sxp(**options) ⇒ String
Transform Shapes into an SXP.
145 146 147 |
# File 'lib/shacl/shapes.rb', line 145 def to_sxp(**) to_sxp_bin.to_sxp(**) end |
#to_sxp_bin ⇒ Object
137 138 139 |
# File 'lib/shacl/shapes.rb', line 137 def to_sxp_bin [:shapes, super] end |