Class: ShEx::Algebra::Schema
- Defined in:
- lib/shex/algebra/schema.rb
Constant Summary collapse
- NAME =
:schema
Constants inherited from Operator
Instance Attribute Summary collapse
-
#extensions ⇒ Hash{String => ShEx::Extension}
readonly
Map of Semantic Action instances.
-
#graph ⇒ RDF::Queryable
Graph to validate.
-
#map ⇒ Hash{RDF::Resource => RDF::Resource}
readonly
Map of nodes to shapes.
Attributes inherited from Operator
#label, #logger, #operands, #options, #schema
Class Method Summary collapse
-
.from_shexj(operator, options = {}) ⇒ Operator
Creates an operator instance from a parsed ShExJ representation.
Instance Method Summary collapse
-
#enter_shape(label, node) {|shape,| ... } ⇒ Satisfiable
Indicate that a shape has been entered with a specific focus node.
-
#execute(focus, graph, map, shapeExterns: [], depth: 0, **options) ⇒ Operand
Match on schema.
-
#external_schemas ⇒ Array<Schema>
Externally loaded schemas, lazily evaluated.
-
#initialize(*operands) ⇒ Object
constructor
Initializes a new operator instance.
-
#satisfies?(focus, graph, map, shapeExterns: [], **options) ⇒ Boolean
Match on schema.
-
#shapes ⇒ Array<Operator>
Shapes as a hash.
-
#start ⇒ Object
Start action, if any.
-
#validate! ⇒ SPARQL::Algebra::Expression
Validate shapes, in addition to other operands.
Methods inherited from Operator
#base_uri, #closed?, #each_descendant, #eql?, #first_ancestor, #focus, #focus=, #inspect, iri, #iri, #json_type, #matched, #matched=, #message, #message=, #not_matched, #not_satisfied, #operand, #parent, #parent=, #satisfiable?, #satisfied, #satisfied=, #satisfy, #semact?, #semantic_actions, #serialize_value, #status, #structure_error, #to_h, #to_json, #to_sxp, #to_sxp_bin, #triple_expression?, #unmatched, #unmatched=, #unsatisfied, #unsatisfied=, #value, value
Constructor Details
#initialize(*operands) ⇒ Object #initialize(*operands, options) ⇒ Object
Initializes a new operator instance.
28 29 30 31 32 33 34 |
# File 'lib/shex/algebra/schema.rb', line 28 def initialize(*operands) super each_descendant do |op| # Set schema everywhere op.schema = self end end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method in the class ShEx::Algebra::Operator
Instance Attribute Details
#extensions ⇒ Hash{String => ShEx::Extension} (readonly)
Map of Semantic Action instances
16 17 18 |
# File 'lib/shex/algebra/schema.rb', line 16 def extensions @extensions end |
#graph ⇒ RDF::Queryable
Graph to validate
8 9 10 |
# File 'lib/shex/algebra/schema.rb', line 8 def graph @graph end |
#map ⇒ Hash{RDF::Resource => RDF::Resource} (readonly)
Map of nodes to shapes
12 13 14 |
# File 'lib/shex/algebra/schema.rb', line 12 def map @map end |
Class Method Details
.from_shexj(operator, options = {}) ⇒ Operator
Creates an operator instance from a parsed ShExJ representation
22 23 24 25 |
# File 'lib/shex/algebra/schema.rb', line 22 def self.from_shexj(operator, = {}) raise ArgumentError unless operator.is_a?(Hash) && operator['type'] == "Schema" super end |
Instance Method Details
#enter_shape(label, node) {|shape,| ... } ⇒ Satisfiable
Indicate that a shape has been entered with a specific focus node. Any future attempt to enter the same shape with the same node raises an exception.
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
# File 'lib/shex/algebra/schema.rb', line 139 def enter_shape(label, node, &block) shape = shapes.detect {|s| s.label == label} structure_error("No shape found for #{label}") unless shape @shapes_entered[label] ||= {} if @shapes_entered[label][node] block.call(false) else @shapes_entered[label][node] = self begin block.call(shape) ensure @shapes_entered[label].delete(node) end end end |
#execute(focus, graph, map, shapeExterns: [], depth: 0, **options) ⇒ Operand
Match on schema. Finds appropriate shape for node, and matches that shape.
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 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/shex/algebra/schema.rb', line 48 def execute(focus, graph, map, shapeExterns: [], depth: 0, **) @graph, @shapes_entered = graph, {} @external_schemas = shapeExterns focus = value(focus) logger = [:logger] || @options[:logger] each_descendant do |op| # Set logging everywhere op.logger = logger end # Initialize Extensions @extensions = {} each_descendant do |op| next unless op.is_a?(SemAct) name = op.operands.first.to_s if ext_class = ShEx::Extension.find(name) @extensions[name] ||= ext_class.new(schema: self, depth: depth, **) end end # 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 graph_focus = graph.enum_term.detect {|t| t.node? && t.id == focus.id} if focus.is_a?(RDF::Node) graph_focus ||= focus # Make sure they're URIs @map = (map || {}).inject({}) {|memo, (k,v)| memo.merge(value(k) => iri(v))} # First, evaluate semantic acts semantic_actions.all? do |op| op.satisfies?([], depth: depth + 1) end # Keep a new Schema, specifically for recording actions satisfied_schema = Schema.new # Next run any start expression if start satisfied_schema.operands << start.satisfies?(focus, depth: depth + 1) end # Add shape result(s) satisfied_shapes = {} satisfied_schema.operands << [:shapes, satisfied_shapes] unless shapes.empty? # Match against all shapes associated with the labels for focus Array(@map[focus]).each do |label| enter_shape(label, focus) do |shape| satisfied_shapes[label] = shape.satisfies?(graph_focus, depth: depth + 1) end end status "schema satisfied", depth: depth satisfied_schema ensure # Close Semantic Action extensions @extensions.values.each {|ext| ext.close(schema: self, depth: depth, **)} end |
#external_schemas ⇒ Array<Schema>
Externally loaded schemas, lazily evaluated
158 159 160 161 162 163 164 165 166 167 168 169 |
# File 'lib/shex/algebra/schema.rb', line 158 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: [:logger]) end schema.graph = graph schema end end |
#satisfies?(focus, graph, map, shapeExterns: [], **options) ⇒ Boolean
Match on schema. Finds appropriate shape for node, and matches that shape.
116 117 118 119 120 |
# File 'lib/shex/algebra/schema.rb', line 116 def satisfies?(focus, graph, map, shapeExterns: [], **) execute(focus, graph, map, .merge(shapeExterns: shapeExterns)) rescue ShEx::NotSatisfied false end |
#shapes ⇒ Array<Operator>
Shapes as a hash
125 126 127 128 129 130 |
# File 'lib/shex/algebra/schema.rb', line 125 def shapes @shapes ||= begin shapes = Array(operands.detect {|op| op.is_a?(Array) && op.first == :shapes}) Array(shapes[1..-1]) end end |
#start ⇒ Object
Start action, if any
173 174 175 |
# File 'lib/shex/algebra/schema.rb', line 173 def start @start ||= operands.detect {|op| op.is_a?(Start)} end |
#validate! ⇒ SPARQL::Algebra::Expression
Validate shapes, in addition to other operands
181 182 183 184 |
# File 'lib/shex/algebra/schema.rb', line 181 def validate! shapes.each {|op| op.validate! if op.respond_to?(:validate!)} super end |