shex 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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>
@@ -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
@@ -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> .
@@ -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
@@ -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,6 @@
1
+ module ShEx::Algebra
2
+ ##
3
+ class Annotation < Operator
4
+ NAME = :annotation
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module ShEx::Algebra
2
+ ##
3
+ class Base < Operator::Binary
4
+ NAME = :base
5
+ end
6
+ 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