shex 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/AUTHORS +1 -0
- data/CREDITS +0 -0
- data/LICENSE +24 -0
- data/README.md +124 -0
- data/VERSION +1 -0
- data/etc/doap.ttl +33 -0
- data/lib/shex.rb +133 -0
- data/lib/shex/algebra.rb +39 -0
- data/lib/shex/algebra/and.rb +32 -0
- data/lib/shex/algebra/annotation.rb +6 -0
- data/lib/shex/algebra/base.rb +6 -0
- data/lib/shex/algebra/each_of.rb +53 -0
- data/lib/shex/algebra/external.rb +24 -0
- data/lib/shex/algebra/inclusion.rb +59 -0
- data/lib/shex/algebra/node_constraint.rb +148 -0
- data/lib/shex/algebra/not.rb +19 -0
- data/lib/shex/algebra/one_of.rb +50 -0
- data/lib/shex/algebra/operator.rb +274 -0
- data/lib/shex/algebra/or.rb +37 -0
- data/lib/shex/algebra/prefix.rb +6 -0
- data/lib/shex/algebra/satisfiable.rb +44 -0
- data/lib/shex/algebra/schema.rb +125 -0
- data/lib/shex/algebra/semact.rb +38 -0
- data/lib/shex/algebra/shape.rb +93 -0
- data/lib/shex/algebra/shape_ref.rb +46 -0
- data/lib/shex/algebra/start.rb +20 -0
- data/lib/shex/algebra/stem.rb +20 -0
- data/lib/shex/algebra/stem_range.rb +42 -0
- data/lib/shex/algebra/triple_constraint.rb +72 -0
- data/lib/shex/algebra/triple_expression.rb +46 -0
- data/lib/shex/algebra/unary_shape.rb +6 -0
- data/lib/shex/algebra/value.rb +28 -0
- data/lib/shex/meta.rb +7914 -0
- data/lib/shex/parser.rb +801 -0
- data/lib/shex/terminals.rb +106 -0
- metadata +224 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: a8b0ba57a643b21c61dc3ddb8a7b49323c39bc1f
|
4
|
+
data.tar.gz: 82bdcc8715f967354d09e1990f801806778c39b6
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6828f94a4e12c8d344ded59c69ec16e3c1f01990ea53110a1f21f1382eca27a2a1bdb53fa32e61e8c7095f2bdf0d74feb5c60f09e26b93b0626daad690171535
|
7
|
+
data.tar.gz: 6ad0d4ae5c64c2d8076b270f0861749410a983ba2525db7fcabef7b405394af1432fcb63f08f625c75114e8bc8bd11da335e563560aed84290327a0cfb938e37
|
data/AUTHORS
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
* Gregg Kellogg <gregg@kellogg-assoc.com>
|
data/CREDITS
ADDED
File without changes
|
data/LICENSE
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
This is free and unencumbered software released into the public domain.
|
2
|
+
|
3
|
+
Anyone is free to copy, modify, publish, use, compile, sell, or
|
4
|
+
distribute this software, either in source code form or as a compiled
|
5
|
+
binary, for any purpose, commercial or non-commercial, and by any
|
6
|
+
means.
|
7
|
+
|
8
|
+
In jurisdictions that recognize copyright laws, the author or authors
|
9
|
+
of this software dedicate any and all copyright interest in the
|
10
|
+
software to the public domain. We make this dedication for the benefit
|
11
|
+
of the public at large and to the detriment of our heirs and
|
12
|
+
successors. We intend this dedication to be an overt act of
|
13
|
+
relinquishment in perpetuity of all present and future rights to this
|
14
|
+
software under copyright law.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
19
|
+
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
20
|
+
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
21
|
+
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
23
|
+
|
24
|
+
For more information, please refer to <http://unlicense.org>
|
data/README.md
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
# ShEx: Shape Expression language for Ruby
|
2
|
+
|
3
|
+
This is a pure-Ruby library for working with the [Shape Expressions Language][ShExSpec] to validate the shape of [RDF][] graphs.
|
4
|
+
|
5
|
+
<http://ruby-rdf.github.com/shex>
|
6
|
+
|
7
|
+
[![Gem Version](https://badge.fury.io/rb/shex.png)](http://badge.fury.io/rb/shex)
|
8
|
+
[![Build Status](https://travis-ci.org/ruby-rdf/shex.png?branch=master)](http://travis-ci.org/ruby-rdf/shex)
|
9
|
+
[![Coverage Status](https://coveralls.io/repos/ruby-rdf/shex/badge.svg)](https://coveralls.io/r/ruby-rdf/shex)
|
10
|
+
[![Join the chat at https://gitter.im/ruby-rdf/rdf](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/ruby-rdf/rdf?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
11
|
+
|
12
|
+
## Features
|
13
|
+
|
14
|
+
* 100% pure Ruby with minimal dependencies and no bloat.
|
15
|
+
* Fully compatible with [ShEx][ShExSpec] specifications.
|
16
|
+
* 100% free and unencumbered [public domain](http://unlicense.org/) software.
|
17
|
+
|
18
|
+
## Description
|
19
|
+
|
20
|
+
The ShEx gem implements a [ShEx][ShExSpec] Shape Expression engine.
|
21
|
+
|
22
|
+
* `ShEx::Parser` parses ShExC formatted documents generating executable operators which can be serialized as [S-Expressions](http://en.wikipedia.org/wiki/S-expression).
|
23
|
+
* `ShEx::Algebra` executes operators against Any `RDF::Graph`, including compliant [RDF.rb][].
|
24
|
+
|
25
|
+
## Example
|
26
|
+
|
27
|
+
require 'rubygems'
|
28
|
+
require 'rdf/turtle'
|
29
|
+
require 'shex'
|
30
|
+
|
31
|
+
shexc: %(
|
32
|
+
PREFIX doap: <http://usefulinc.com/ns/doap#>
|
33
|
+
PREFIX dc: <http://purl.org/dc/terms/>
|
34
|
+
<TestShape> EXTRA a {
|
35
|
+
a doap:Project;
|
36
|
+
(doap:name;doap:description|dc:title;dc:description)+;
|
37
|
+
doap:category*;
|
38
|
+
doap:developer IRI;
|
39
|
+
doap:implements [<https://shexspec.github.io/spec/>]
|
40
|
+
}
|
41
|
+
)
|
42
|
+
graph = RDF::Graph.load("etc/doap.ttl")
|
43
|
+
schema = ShEx.parse(shexc)
|
44
|
+
map = {
|
45
|
+
"http://rubygems.org/gems/shex" => "TestShape"
|
46
|
+
}
|
47
|
+
schema.satisfies?("http://rubygems.org/gems/shex", graph, map)
|
48
|
+
# => true
|
49
|
+
|
50
|
+
## Documentation
|
51
|
+
|
52
|
+
<http://rubydoc.info/github/ruby-rdf/shex>
|
53
|
+
|
54
|
+
|
55
|
+
## Implementation Notes
|
56
|
+
The ShExC parser uses the [EBNF][] gem to generate first, follow and branch tables, and uses the `Parser` and `Lexer` modules to implement the ShExC parser.
|
57
|
+
|
58
|
+
The parser takes branch and follow tables generated from the [ShEx Grammar](file.shex.html) described in the [specification][ShExSpec]. Branch and Follow tables are specified in the generated {ShEx::Meta}.
|
59
|
+
|
60
|
+
## Dependencies
|
61
|
+
|
62
|
+
* [Ruby](http://ruby-lang.org/) (>= 2.0)
|
63
|
+
* [RDF.rb](http://rubygems.org/gems/rdf) (>= 2.1)
|
64
|
+
|
65
|
+
## Installation
|
66
|
+
|
67
|
+
The recommended installation method is via [RubyGems](http://rubygems.org/).
|
68
|
+
To install the latest official release of RDF.rb, do:
|
69
|
+
|
70
|
+
% [sudo] gem install shex
|
71
|
+
|
72
|
+
## Download
|
73
|
+
|
74
|
+
To get a local working copy of the development repository, do:
|
75
|
+
|
76
|
+
% git clone git://github.com/ruby-rdf/shex.git
|
77
|
+
|
78
|
+
Alternatively, download the latest development version as a tarball as
|
79
|
+
follows:
|
80
|
+
|
81
|
+
% wget http://github.com/ruby-rdf/shex/tarball/master
|
82
|
+
|
83
|
+
## Resources
|
84
|
+
|
85
|
+
* <http://rubydoc.info/github/ruby-rdf/shex>
|
86
|
+
* <http://github.com/ruby-rdf/shex>
|
87
|
+
* <http://rubygems.org/gems/shex>
|
88
|
+
|
89
|
+
## Mailing List
|
90
|
+
|
91
|
+
* <http://lists.w3.org/Archives/Public/public-rdf-ruby/>
|
92
|
+
|
93
|
+
## Author
|
94
|
+
|
95
|
+
* [Gregg Kellogg](http://github.com/gkellogg) - <http://greggkellogg.net/>
|
96
|
+
|
97
|
+
## Contributing
|
98
|
+
|
99
|
+
This repository uses [Git Flow](https://github.com/nvie/gitflow) to mange development and release activity. All submissions _must_ be on a feature branch based on the _develop_ branch to ease staging and integration.
|
100
|
+
|
101
|
+
* Do your best to adhere to the existing coding conventions and idioms.
|
102
|
+
* Don't use hard tabs, and don't leave trailing whitespace on any line.
|
103
|
+
Before committing, run `git diff --check` to make sure of this.
|
104
|
+
* Do document every method you add using [YARD][] annotations. Read the
|
105
|
+
[tutorial][YARD-GS] or just look at the existing code for examples.
|
106
|
+
* Don't touch the `.gemspec` or `VERSION` files. If you need to change them,
|
107
|
+
do so on your private branch only.
|
108
|
+
* Do feel free to add yourself to the `CREDITS` file and the
|
109
|
+
corresponding list in the the `README`. Alphabetical order applies.
|
110
|
+
* Don't touch the `AUTHORS` file. If your contributions are significant
|
111
|
+
enough, be assured we will eventually add you in there.
|
112
|
+
* Do note that in order for us to merge any non-trivial changes (as a rule
|
113
|
+
of thumb, additions larger than about 15 lines of code), we need an
|
114
|
+
explicit [public domain dedication][PDD] on record from you.
|
115
|
+
|
116
|
+
## License
|
117
|
+
|
118
|
+
This is free and unencumbered public domain software. For more information,
|
119
|
+
see <http://unlicense.org/> or the accompanying {file:LICENSE} file.
|
120
|
+
|
121
|
+
[ShExSpec]: https://shexspec.github.io/spec/
|
122
|
+
[RDF]: http://www.w3.org/RDF/
|
123
|
+
[RDF.rb]: http://rubydoc.info/github/ruby-rdf/rdf
|
124
|
+
[EBNF]: http://rubygems.org/gems/ebnf
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
data/etc/doap.ttl
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
|
2
|
+
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
|
3
|
+
@prefix dc: <http://purl.org/dc/terms/> .
|
4
|
+
@prefix earl: <http://www.w3.org/ns/earl#> .
|
5
|
+
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
|
6
|
+
@prefix doap: <http://usefulinc.com/ns/doap#> .
|
7
|
+
@prefix ex: <http://example.org/> .
|
8
|
+
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
|
9
|
+
|
10
|
+
<http://rubygems.org/gems/shex> a doap:Project, earl:TestSubject, earl:Software ;
|
11
|
+
doap:name "ShEx" ;
|
12
|
+
doap:homepage <http://ruby-rdf.github.com/shex> ;
|
13
|
+
doap:license <http://creativecommons.org/licenses/publicdomain/> ;
|
14
|
+
doap:shortdesc "ShEx is a Shape Expression engine for Ruby."@en ;
|
15
|
+
doap:description "ShEx is an Shape Expression engine for the RDF.rb library suite."@en ;
|
16
|
+
doap:created "2016-12-09"^^xsd:date ;
|
17
|
+
doap:programming-language "Ruby" ;
|
18
|
+
doap:implements <https://shexspec.github.io/spec/> ;
|
19
|
+
doap:category <http://dbpedia.org/resource/Resource_Description_Framework>,
|
20
|
+
<http://dbpedia.org/resource/Ruby_(programming_language)> ;
|
21
|
+
doap:download-page <http://rubygems.org/gems/shex> ;
|
22
|
+
doap:mailing-list <http://lists.w3.org/Archives/Public/public-rdf-ruby/> ;
|
23
|
+
doap:bug-database <http://github.com/ruby-rdf/shex/issues> ;
|
24
|
+
doap:blog <http://greggkellogg.net/> ;
|
25
|
+
doap:developer <http://greggkellogg.net/foaf#me> ;
|
26
|
+
doap:maintainer <http://greggkellogg.net/foaf#me> ;
|
27
|
+
doap:documenter <http://greggkellogg.net/foaf#me> ;
|
28
|
+
foaf:maker <http://greggkellogg.net/foaf#me> ;
|
29
|
+
dc:title "ShEx" ;
|
30
|
+
dc:description "ShEx is an Shape Expression engine for the RDF.rb library suite."@en ;
|
31
|
+
dc:date "2016-12-09"^^xsd:date ;
|
32
|
+
dc:creator <http://greggkellogg.net/foaf#me> ;
|
33
|
+
dc:isPartOf <http://rubygems.org/gems/rdf> .
|
data/lib/shex.rb
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
require 'sparql/extensions'
|
2
|
+
|
3
|
+
##
|
4
|
+
# A ShEx runtime for RDF.rb.
|
5
|
+
#
|
6
|
+
# @see https://shexspec.github.io/spec/#shexc
|
7
|
+
module ShEx
|
8
|
+
autoload :Algebra, 'shex/algebra'
|
9
|
+
autoload :Meta, 'shex/meta'
|
10
|
+
autoload :Parser, 'shex/parser'
|
11
|
+
autoload :Terminals, 'shex/terminals'
|
12
|
+
autoload :VERSION, 'shex/version'
|
13
|
+
|
14
|
+
##
|
15
|
+
# Parse the given ShEx `query` string.
|
16
|
+
#
|
17
|
+
# @example parsing a ShExC schema
|
18
|
+
# schema = ShEx.parse(%(
|
19
|
+
# PREFIX ex: <http://schema.example/> ex:IssueShape {ex:state IRI}
|
20
|
+
# ).parse
|
21
|
+
#
|
22
|
+
# @param [IO, StringIO, String, #to_s] expression (ShExC or ShExJ)
|
23
|
+
# @param ['shexc', 'shexj', 'sse'] format ('shexc')
|
24
|
+
# @param [Hash{Symbol => Object}] options
|
25
|
+
# @return [ShEx::Algebra::Schema] The executable parsed expression.
|
26
|
+
# @raise [ShEx::ParseError] when a syntax error is detected
|
27
|
+
# @raise [ShEx::StructureError, ArgumentError] on structural problems with schema
|
28
|
+
def self.parse(expression, format: 'shexc', **options)
|
29
|
+
case format
|
30
|
+
when 'shexc' then Parser.new(expression, options).parse
|
31
|
+
when 'shexj'
|
32
|
+
when 'sse'
|
33
|
+
else raise "Unknown expression format: #{format.inspect}"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
##
|
38
|
+
# Parses input from the given file name or URL.
|
39
|
+
#
|
40
|
+
# @example parsing a ShExC schema
|
41
|
+
# schema = ShEx.parse('foo.shex').parse
|
42
|
+
#
|
43
|
+
# @param [String, #to_s] filename
|
44
|
+
# @param ['shexc', 'shexj', 'sse'] format ('shexc')
|
45
|
+
# @param [Hash{Symbol => Object}] options
|
46
|
+
# any additional options (see `RDF::Reader#initialize` and `RDF::Format.for`)
|
47
|
+
# @yield [ShEx::Algebra::Schema]
|
48
|
+
# @yieldparam [RDF::Reader] reader
|
49
|
+
# @yieldreturn [void] ignored
|
50
|
+
# @return [ShEx::Algebra::Schema] The executable parsed expression.
|
51
|
+
# @raise [ShEx::ParseError] when a syntax error is detected
|
52
|
+
# @raise [ShEx::StructureError, ArgumentError] on structural problems with schema
|
53
|
+
def self.open(filename, format: 'shexc', **options, &block)
|
54
|
+
RDF::Util::File.open_file(filename, options) do |file|
|
55
|
+
self.parse(file, options.merge(format: format))
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
##
|
60
|
+
# Parse and validate the given ShEx `expression` string against `queriable`.
|
61
|
+
#
|
62
|
+
# @example executing a ShExC schema
|
63
|
+
# graph = RDF::Graph.load("etc/doap.ttl")
|
64
|
+
# ShEx.execute('etc/doap.shex', graph, "http://rubygems.org/gems/shex", "")
|
65
|
+
#
|
66
|
+
# @param [IO, StringIO, String, #to_s] expression (ShExC or ShExJ)
|
67
|
+
# @param [RDF::Resource] focus
|
68
|
+
# @param [RDF::Resource] shape
|
69
|
+
# @param ['shexc', 'shexj', 'sse'] format ('shexc')
|
70
|
+
# @param [Hash{Symbol => Object}] options
|
71
|
+
# @return [Boolean] `true` if satisfied, `false` if it does not apply
|
72
|
+
# @raise [ShEx::NotSatisfied] if not satisfied
|
73
|
+
# @raise [ShEx::ParseError] when a syntax error is detected
|
74
|
+
# @raise [ShEx::StructureError, ArgumentError] on structural problems with schema
|
75
|
+
def self.execute(expression, queryable, focus, shape, format: 'shexc', **options)
|
76
|
+
shex = self.parse(expression, options.merge(format: format))
|
77
|
+
queryable = queryable || RDF::Graph.new
|
78
|
+
|
79
|
+
shex.satisfies?(focus, queryable, {focus => shape}, options)
|
80
|
+
end
|
81
|
+
|
82
|
+
class Error < StandardError
|
83
|
+
# The status code associated with this error
|
84
|
+
attr_reader :code
|
85
|
+
|
86
|
+
##
|
87
|
+
# Initializes a new patch error instance.
|
88
|
+
#
|
89
|
+
# @param [String, #to_s] message
|
90
|
+
# @param [Hash{Symbol => Object}] options
|
91
|
+
# @option options [Integer] :code (422)
|
92
|
+
def initialize(message, options = {})
|
93
|
+
@code = options.fetch(:status_code, 422)
|
94
|
+
super(message.to_s)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
|
99
|
+
# Shape expectation not satisfied
|
100
|
+
class StructureError < Error; end
|
101
|
+
|
102
|
+
# Shape expectation not satisfied
|
103
|
+
class NotSatisfied < Error; end
|
104
|
+
|
105
|
+
# Indicates bad syntax found in LD Patch document
|
106
|
+
class ParseError < Error
|
107
|
+
##
|
108
|
+
# The invalid token which triggered the error.
|
109
|
+
#
|
110
|
+
# @return [String]
|
111
|
+
attr_reader :token
|
112
|
+
|
113
|
+
##
|
114
|
+
# The line number where the error occurred.
|
115
|
+
#
|
116
|
+
# @return [Integer]
|
117
|
+
attr_reader :lineno
|
118
|
+
|
119
|
+
##
|
120
|
+
# Initializes a new parser error instance.
|
121
|
+
#
|
122
|
+
# @param [String, #to_s] message
|
123
|
+
# @param [Hash{Symbol => Object}] options
|
124
|
+
# @option options [String] :token (nil)
|
125
|
+
# @option options [Integer] :lineno (nil)
|
126
|
+
# @option options [Integer] :code (400)
|
127
|
+
def initialize(message, options = {})
|
128
|
+
@token = options[:token]
|
129
|
+
@lineno = options[:lineno] || (@token.lineno if @token.respond_to?(:lineno))
|
130
|
+
super(message.to_s, code: options.fetch(:code, 400))
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
data/lib/shex/algebra.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
$:.unshift(File.expand_path("../..", __FILE__))
|
2
|
+
require 'sparql/algebra'
|
3
|
+
require 'sxp'
|
4
|
+
|
5
|
+
module ShEx
|
6
|
+
# Based on the SPARQL Algebra, operators for executing a patch
|
7
|
+
#
|
8
|
+
# @author [Gregg Kellogg](http://greggkellogg.net/)
|
9
|
+
module Algebra
|
10
|
+
autoload :And, 'shex/algebra/and'
|
11
|
+
autoload :Annotation, 'shex/algebra/annotation'
|
12
|
+
autoload :Base, 'shex/algebra/base'
|
13
|
+
autoload :EachOf, 'shex/algebra/each_of'
|
14
|
+
autoload :Inclusion, 'shex/algebra/inclusion'
|
15
|
+
autoload :Not, 'shex/algebra/not'
|
16
|
+
autoload :NodeConstraint, 'shex/algebra/node_constraint'
|
17
|
+
autoload :OneOf, 'shex/algebra/one_of'
|
18
|
+
autoload :Operator, 'shex/algebra/operator'
|
19
|
+
autoload :Or, 'shex/algebra/or'
|
20
|
+
autoload :Prefix, 'shex/algebra/prefix'
|
21
|
+
autoload :Satisfiable, 'shex/algebra/satisfiable'
|
22
|
+
autoload :Schema, 'shex/algebra/schema'
|
23
|
+
autoload :SemAct, 'shex/algebra/semact'
|
24
|
+
autoload :External, 'shex/algebra/external'
|
25
|
+
autoload :ShapeRef, 'shex/algebra/shape_ref'
|
26
|
+
autoload :Shape, 'shex/algebra/shape'
|
27
|
+
autoload :Start, 'shex/algebra/start'
|
28
|
+
autoload :Stem, 'shex/algebra/stem'
|
29
|
+
autoload :StemRange, 'shex/algebra/stem_range'
|
30
|
+
autoload :TripleConstraint, 'shex/algebra/triple_constraint'
|
31
|
+
autoload :TripleExpression, 'shex/algebra/triple_expression'
|
32
|
+
autoload :UnaryShape, 'shex/algebra/unary_shape'
|
33
|
+
autoload :Value, 'shex/algebra/value'
|
34
|
+
|
35
|
+
class NotMatched < ShEx::Error; end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module ShEx::Algebra
|
2
|
+
##
|
3
|
+
class And < Operator
|
4
|
+
include Satisfiable
|
5
|
+
NAME = :and
|
6
|
+
|
7
|
+
def initialize(*args, **options)
|
8
|
+
case
|
9
|
+
when args.length <= 1
|
10
|
+
raise ArgumentError, "wrong number of arguments (given #{args.length}, expected 1..)"
|
11
|
+
end
|
12
|
+
super
|
13
|
+
end
|
14
|
+
|
15
|
+
#
|
16
|
+
# S is a ShapeAnd and for every shape expression se2 in shapeExprs, satisfies(n, se2, G, m).
|
17
|
+
# @param [RDF::Resource] n
|
18
|
+
# @return [Boolean] `true` when satisfied
|
19
|
+
# @raise [ShEx::NotSatisfied] if not satisfied
|
20
|
+
def satisfies?(n)
|
21
|
+
status ""
|
22
|
+
|
23
|
+
# Operand raises NotSatisfied, so no need to check here.
|
24
|
+
operands.select {|o| o.is_a?(Satisfiable)}.each {|op| op.satisfies?(n)}
|
25
|
+
status("satisfied")
|
26
|
+
true
|
27
|
+
rescue ShEx::NotSatisfied => e
|
28
|
+
not_satisfied(e.message)
|
29
|
+
raise
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module ShEx::Algebra
|
2
|
+
##
|
3
|
+
class EachOf < Operator
|
4
|
+
include TripleExpression
|
5
|
+
NAME = :eachOf
|
6
|
+
|
7
|
+
##
|
8
|
+
# expr is an EachOf and there is some partition of T into T1, T2,… such that for every expression expr1, expr2,… in shapeExprs, matches(Tn, exprn, m)...
|
9
|
+
#
|
10
|
+
# @param [Array<RDF::Statement>] t
|
11
|
+
# @return [Array<RDF::Statement>]
|
12
|
+
# @raise NotMatched, ShEx::NotSatisfied
|
13
|
+
def matches(t)
|
14
|
+
status ""
|
15
|
+
results = []
|
16
|
+
statements = t.dup
|
17
|
+
num_iters = 0
|
18
|
+
max = maximum
|
19
|
+
|
20
|
+
while num_iters < max
|
21
|
+
begin
|
22
|
+
matched_this_iter = []
|
23
|
+
operands.select {|o| o.is_a?(TripleExpression)}.all? do |op|
|
24
|
+
matched = op.matches(statements - matched_this_iter)
|
25
|
+
matched_this_iter += matched
|
26
|
+
end
|
27
|
+
results += matched_this_iter
|
28
|
+
statements -= matched_this_iter
|
29
|
+
num_iters += 1
|
30
|
+
status "matched #{results.length} statements after #{num_iters} iterations"
|
31
|
+
rescue NotMatched => e
|
32
|
+
log_recover("eachOf: ignore error: #{e.message}", depth: options.fetch(:depth, 0))
|
33
|
+
break
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# Max violations handled in Shape
|
38
|
+
not_matched "Minimum Cardinality Violation: #{num_iters} < #{minimum}" if
|
39
|
+
num_iters < minimum
|
40
|
+
|
41
|
+
# Last, evaluate semantic acts
|
42
|
+
semantic_actions.all? do |op|
|
43
|
+
op.satisfies?(results)
|
44
|
+
end unless results.empty?
|
45
|
+
|
46
|
+
status "each of satisfied"
|
47
|
+
results
|
48
|
+
rescue NotMatched => e
|
49
|
+
not_matched(e.message)
|
50
|
+
raise
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|