class SHACL::Algebra::NodeShape
Constants
- NAME
Public Instance Methods
conforms(node, depth: 0, **options)
click to toggle source
Validates the specified `node` within `graph`, a list of {ValidationResult}.
A node conforms if it is not deactivated and all of its operands conform.
@param [RDF::Term] node @param [Hash{Symbol => Object}] options @return [Array<SHACL::ValidationResult>]
Returns one or more validation results for each operand.
# File lib/shacl/algebra/node_shape.rb, line 16 def conforms(node, depth: 0, **options) return [] if deactivated? options = id ? options.merge(shape: id) : options options = options.merge(severity: RDF::Vocab::SHACL.Violation) log_debug(NAME, depth: depth) {SXP::Generator.string({id: id, node: node}.to_sxp_bin)} # Add some instance options to the argument options = %i{ flags qualifiedMinCount qualifiedMaxCount qualifiedValueShapesDisjoint severity }.inject(options) do |memo, sym| @options[sym] ? memo.merge(sym => @options[sym]) : memo end # Evaluate against builtins builtin_results = @options.map do |k, v| self.send("builtin_#{k}".to_sym, v, node, nil, [node], depth: depth + 1, **options) if self.respond_to?("builtin_#{k}".to_sym) end.flatten.compact # Handle closed shapes # FIXME: this only considers URI paths, not property paths closed_results = [] if @options[:closed] shape_paths = operands.select {|o| o.is_a?(PropertyShape)}.map(&:path) shape_properties = shape_paths.select {|p| p.is_a?(RDF::URI)} shape_properties += Array(@options[:ignoredProperties]) closed_results = graph.query({subject: node}).map do |statement| next if shape_properties.include?(statement.predicate) not_satisfied(focus: node, value: statement.object, path: statement.predicate, message: "closed node has extra property", resultSeverity: options.fetch(:severity), component: RDF::Vocab::SHACL.ClosedConstraintComponent, **options) end.compact end # Evaluate against operands op_results = operands.map do |op| res = op.conforms(node, focus: options.fetch(:focusNode, node), depth: depth + 1, **options) if op.is_a?(NodeShape) && !res.all?(&:conform?) # Special case for embedded NodeShape not_satisfied(focus: node, value: node, message: "node does not conform to #{op.id}", resultSeverity: options.fetch(:severity), component: RDF::Vocab::SHACL.NodeConstraintComponent, **options) else res end end.flatten.compact builtin_results + closed_results + op_results end