shex 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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