rdf-reasoner 0.5.2 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 60eee91f9020b95645e085da0bdb5f300639bb393d11b8e197bbe982e1ee8bcd
4
- data.tar.gz: 3f281de995bbae445decd9ad8840306d477b9fd47f88289c7fdbcb812c47234b
3
+ metadata.gz: 76b5e839eb5062fe5242c877013f8586bf3aabb3ebb52eef3d124130eb7e1a2a
4
+ data.tar.gz: 8103c9212976dd3917d8d2f590456b2d88a9331a3d3b2d0395be43e89bd51868
5
5
  SHA512:
6
- metadata.gz: 181413e24899b1b0a27d6d53e3a3f74c651f3acd990266fc75fe6cc15d3d1b8ebcceb42fbd23dd1a47a9461de263bf4e1bdc70c4f8ab81bc3a924ce71c8529b8
7
- data.tar.gz: 1423ab5bc2f0e474ba001f61cf72a881be09d3ef90be4cd5fd81abbc8d091fc83bd2a032445eb04967f0b334e7ab291046945cd81b69cafb9651a3266b70ed83
6
+ metadata.gz: e83c1542bd875748049d5c2faa321a6dbd9ec46a1ac63c8f6e3fb6ad75db04ecaff1037e0c5019fcec650edd4d9e834fb02c4e29997204eec2f16df398eb915c
7
+ data.tar.gz: 20120ecee4e8a7ea2a31e37ac136103057ae1474d1123551073a3382ca9c24e69fc802b92f97c8990805c072a6a98b6b70cac15a65bd65efced877a1a4c70afd
data/README.md CHANGED
@@ -1,4 +1,13 @@
1
- # rdf-reasoner
1
+ # RDF::Reasoner
2
+
3
+ A partial RDFS/OWL/schema.org reasoner for [RDF.rb][].
4
+
5
+ [![Gem Version](https://badge.fury.io/rb/rdf-reasoner.png)](https://badge.fury.io/rb/rdf-reasoner)
6
+ [![Build Status](https://github.com/ruby-rdf/rdf-reasoner/workflows/CI/badge.svg?branch=develop)](https://github.com/ruby-rdf/rdf-reasoner/actions?query=workflow%3ACI)
7
+ [![Coverage Status](https://coveralls.io/repos/ruby-rdf/rdf-reasoner/badge.svg?branch=develop)](https://coveralls.io/github/ruby-rdf/rdf-reasoner?branch=develop)
8
+ [![Gitter chat](https://badges.gitter.im/ruby-rdf/rdf.png)](https://gitter.im/ruby-rdf/rdf)
9
+
10
+ ## Description
2
11
 
3
12
  Reasons over RDFS/OWL vocabularies and schema.org to generate statements which are entailed based on base RDFS/OWL rules along with vocabulary information. It can also be used to ask specific questions, such as if a given object is consistent with the vocabulary ruleset. This can be used to implement [SPARQL Entailment][] Regimes and [RDF Schema][] entailment.
4
13
 
@@ -22,6 +31,14 @@ Domain and Range entailment include specific rules for schema.org vocabularies.
22
31
  * If `resource` is of type `schema:Role`, it is range acceptable if it has the same property with an acceptable value.
23
32
  * If `resource` is of type `rdf:List` (must be previously entailed), it is range acceptable if all members of the list are otherwise range acceptable on the same property.
24
33
 
34
+ ### Limiting vocabularies used for reasoning
35
+
36
+ As loading vocabularies can dominate processing time, the `RDF::Vocabulary.limit_vocabs` method can be used to set a specific set of vocabularies over which to reason. For example:
37
+
38
+ RDF::Vocabulary.limit_vocabs(:rdf, :rdf, :schema)
39
+
40
+ will limit the vocabularies which are returned from `RDF::Vocabulary.each`, which is used for reasoning and other operations over vocabularies and terms.
41
+
25
42
  ## Examples
26
43
  ### Determine super-classes of a class
27
44
 
@@ -104,8 +121,8 @@ The `rdf` command-line interface is extended with `entail` and `lint` commands.
104
121
 
105
122
  ## Dependencies
106
123
 
107
- * [Ruby](https://ruby-lang.org/) (>= 2.2.2)
108
- * [RDF.rb](https://rubygems.org/gems/rdf) (~> 3.0)
124
+ * [Ruby](https://ruby-lang.org/) (>= 2.4)
125
+ * [RDF.rb](https://rubygems.org/gems/rdf) (~> 3.1)
109
126
 
110
127
  ## Mailing List
111
128
 
@@ -113,7 +130,7 @@ The `rdf` command-line interface is extended with `entail` and `lint` commands.
113
130
 
114
131
  ## Authors
115
132
 
116
- * [Gregg Kellogg](https://githubhub.com/gkellogg) - <https://greggkellogg.net/>
133
+ * [Gregg Kellogg](https://github.com/gkellogg) - <https://greggkellogg.net/>
117
134
 
118
135
  ## Contributing
119
136
 
@@ -128,7 +145,9 @@ The `rdf` command-line interface is extended with `entail` and `lint` commands.
128
145
  list in the the `README`. Alphabetical order applies.
129
146
  * Do note that in order for us to merge any non-trivial changes (as a rule
130
147
  of thumb, additions larger than about 15 lines of code), we need an
131
- explicit [public domain dedication][PDD] on record from you.
148
+ explicit [public domain dedication][PDD] on record from you,
149
+ which you will be asked to agree to on the first commit to a repo within the organization.
150
+ Note that the agreement applies to all repos in the [Ruby RDF](https://github.com/ruby-rdf/) organization.
132
151
 
133
152
  ## License
134
153
 
@@ -139,7 +158,7 @@ see <https://unlicense.org/> or the accompanying {file:UNLICENSE} file.
139
158
  [RDF]: https://www.w3.org/RDF/
140
159
  [YARD]: https://yardoc.org/
141
160
  [YARD-GS]: https://rubydoc.info/docs/yard/file/docs/GettingStarted.md
142
- [PDD]: https://lists.w3.org/Archives/Public/public-rdf-ruby/2010May/0013.html
161
+ [PDD]: https://unlicense.org/#unlicensing-contributions
143
162
  [SPARQL]: https://en.wikipedia.org/wiki/SPARQL
144
163
  [SPARQL Query]: https://www.w3.org/TR/2013/REC-sparql11-query-20130321/
145
164
  [SPARQL Entailment]:https://www.w3.org/TR/sparql11-entailment/
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5.2
1
+ 0.7.0
data/lib/rdf/reasoner.rb CHANGED
@@ -1,12 +1,11 @@
1
1
  require 'rdf'
2
2
  require 'rdf/reasoner/extensions'
3
- require 'rdf/vocab'
4
3
 
5
4
  module RDF
6
5
  ##
7
6
  # RDFS/OWL reasonsing for RDF.rb.
8
7
  #
9
- # @see http://www.w3.org/TR/2013/REC-sparql11-entailment-20130321/
8
+ # @see https://www.w3.org/TR/2013/REC-sparql11-entailment-20130321/
10
9
  # @author [Gregg Kellogg](https://greggkellogg.net/)
11
10
  module Reasoner
12
11
  require 'rdf/reasoner/format'
@@ -15,7 +14,7 @@ module RDF
15
14
  autoload :Schema, 'rdf/reasoner/schema'
16
15
  autoload :VERSION, 'rdf/reasoner/version'
17
16
 
18
- # See http://www.pelagodesign.com/blog/2009/05/20/iso-8601-date-validation-that-doesnt-suck/
17
+ # See https://www.pelagodesign.com/blog/2009/05/20/iso-8601-date-validation-that-doesnt-suck/
19
18
  #
20
19
  #
21
20
  ISO_8601 = %r(^
@@ -91,7 +91,7 @@ module RDF
91
91
  # Fully entailed types of resource, if not provided, they are queried
92
92
  def domain_compatible?(resource, queryable, options = {})
93
93
  %w(owl rdfs schema).map {|r| "domain_compatible_#{r}?".to_sym}.all? do |meth|
94
- !self.respond_to?(meth) || self.send(meth, resource, queryable, options)
94
+ !self.respond_to?(meth) || self.send(meth, resource, queryable, **options)
95
95
  end
96
96
  end
97
97
 
@@ -233,7 +233,7 @@ module RDF
233
233
  messages = {}
234
234
 
235
235
  # Check for defined classes in known vocabularies
236
- self.query(predicate: RDF.type) do |stmt|
236
+ self.query({predicate: RDF.type}) do |stmt|
237
237
  vocab = RDF::Vocabulary.find(stmt.object)
238
238
  term = (RDF::Vocabulary.find_term(stmt.object) rescue nil) if vocab
239
239
  pname = term ? term.pname : stmt.object.pname
@@ -241,7 +241,7 @@ module RDF
241
241
  # Must be a defined term, not in RDF or RDFS vocabularies
242
242
  if term && term.class?
243
243
  # Warn against using a deprecated term
244
- superseded = term.attributes[:'schema:supersededBy']
244
+ superseded = term.properties[:'http://schema.org/supersededBy']
245
245
  superseded = superseded.pname if superseded.respond_to?(:pname)
246
246
  (messages[:class] ||= {})[pname] = ["Term is superseded by #{superseded}"] if superseded
247
247
  else
@@ -264,9 +264,9 @@ module RDF
264
264
  end
265
265
 
266
266
  # Must be a defined property
267
- if term && term.property?
267
+ if term.respond_to?(:property?) && term.property?
268
268
  # Warn against using a deprecated term
269
- superseded = term.attributes[:'schema:supersededBy']
269
+ superseded = term.properties[:'http://schema.org/supersededBy']
270
270
  superseded = superseded.pname if superseded.respond_to?(:pname)
271
271
  (messages[:property] ||= {})[pname] = ["Term is superseded by #{superseded}"] if superseded
272
272
  else
@@ -275,7 +275,7 @@ module RDF
275
275
  end
276
276
 
277
277
  # See if type of the subject is in the domain of this predicate
278
- resource_types[stmt.subject] ||= self.query(subject: stmt.subject, predicate: RDF.type).
278
+ resource_types[stmt.subject] ||= self.query({subject: stmt.subject, predicate: RDF.type}).
279
279
  map {|s| (t = (RDF::Vocabulary.find_term(s.object) rescue nil)) && t.entail(:subClassOf)}.
280
280
  flatten.
281
281
  uniq.
@@ -290,7 +290,7 @@ module RDF
290
290
  end
291
291
 
292
292
  # Make sure that if ranges are defined, the object has an appropriate type
293
- resource_types[stmt.object] ||= self.query(subject: stmt.object, predicate: RDF.type).
293
+ resource_types[stmt.object] ||= self.query({subject: stmt.object, predicate: RDF.type}).
294
294
  map {|s| (t = (RDF::Vocabulary.find_term(s.object) rescue nil)) && t.entail(:subClassOf)}.
295
295
  flatten.
296
296
  uniq.
@@ -316,7 +316,7 @@ module RDF
316
316
  def show_resource(resource)
317
317
  if resource.node?
318
318
  resource.to_ntriples + '(' +
319
- self.query(subject: resource, predicate: RDF.type).
319
+ self.query({subject: resource, predicate: RDF.type}).
320
320
  map {|s| s.object.uri? ? s.object.pname : s.object.to_ntriples}
321
321
  .join(',') +
322
322
  ')'
@@ -50,7 +50,7 @@ module RDF::Reasoner
50
50
  if self.predicate == RDF.type
51
51
  if term = (RDF::Vocabulary.find_term(self.object) rescue nil)
52
52
  term._entail_equivalentClass do |t|
53
- statements << RDF::Statement(self.to_h.merge(object: t, inferred: true))
53
+ statements << RDF::Statement(**self.to_h.merge(object: t, inferred: true))
54
54
  end
55
55
  end
56
56
  end
@@ -89,7 +89,7 @@ module RDF::Reasoner
89
89
  statements = []
90
90
  if term = (RDF::Vocabulary.find_term(self.predicate) rescue nil)
91
91
  term._entail_equivalentProperty do |t|
92
- statements << RDF::Statement(self.to_h.merge(predicate: t, inferred: true))
92
+ statements << RDF::Statement(**self.to_h.merge(predicate: t, inferred: true))
93
93
  end
94
94
  end
95
95
  statements.each {|s| yield s} if block_given?
@@ -74,7 +74,7 @@ module RDF::Reasoner
74
74
  if term = (RDF::Vocabulary.find_term(self.object) rescue nil)
75
75
  term._entail_subClassOf do |t|
76
76
  next if t.node? # Don't entail BNodes
77
- statements << RDF::Statement(self.to_h.merge(object: t, inferred: true))
77
+ statements << RDF::Statement(**self.to_h.merge(object: t, inferred: true))
78
78
  end
79
79
  end
80
80
  #$stderr.puts("subClassf(#{self.predicate.pname}): #{statements.map(&:object).map {|r| r.respond_to?(:pname) ? r.pname : r.to_ntriples}}}")
@@ -122,7 +122,7 @@ module RDF::Reasoner
122
122
 
123
123
  ##
124
124
  # For a Term: yield or return inferred subPropertyOf relationships by recursively applying to named super classes to get a complete set of classes in the ancestor chain of this class
125
- # For a Statement: yield or return inferred statements having a subPropertyOf relationship to predicate of this statement
125
+ # For a Statement: yield or return inferred statements having a subPropertyOf relationship to predicate of this statements
126
126
  # @private
127
127
  def _entail_subPropertyOf
128
128
  case self
@@ -143,7 +143,7 @@ module RDF::Reasoner
143
143
  statements = []
144
144
  if term = (RDF::Vocabulary.find_term(self.predicate) rescue nil)
145
145
  term._entail_subPropertyOf do |t|
146
- statements << RDF::Statement(self.to_h.merge(predicate: t, inferred: true))
146
+ statements << RDF::Statement(**self.to_h.merge(predicate: t, inferred: true))
147
147
  end
148
148
  #$stderr.puts("subPropertyOf(#{self.predicate.pname}): #{statements.map(&:object).map {|r| r.respond_to?(:pname) ? r.pname : r.to_ntriples}}}")
149
149
  end
@@ -208,7 +208,7 @@ module RDF::Reasoner
208
208
  if term = (RDF::Vocabulary.find_term(self.predicate) rescue nil)
209
209
  term.domain.each do |t|
210
210
  next if t.node? # Don't entail BNodes
211
- statements << RDF::Statement(self.to_h.merge(predicate: RDF.type, object: t, inferred: true))
211
+ statements << RDF::Statement(**self.to_h.merge(predicate: RDF.type, object: t, inferred: true))
212
212
  end
213
213
  end
214
214
  #$stderr.puts("domain(#{self.predicate.pname}): #{statements.map(&:object).map {|r| r.respond_to?(:pname) ? r.pname : r.to_ntriples}}}")
@@ -229,7 +229,7 @@ module RDF::Reasoner
229
229
  if object.resource? && term = (RDF::Vocabulary.find_term(self.predicate) rescue nil)
230
230
  term.range.each do |t|
231
231
  next if t.node? # Don't entail BNodes
232
- statements << RDF::Statement(self.to_h.merge(subject: self.object, predicate: RDF.type, object: t, inferred: true))
232
+ statements << RDF::Statement(**self.to_h.merge(subject: self.object, predicate: RDF.type, object: t, inferred: true))
233
233
  end
234
234
  end
235
235
  #$stderr.puts("range(#{self.predicate.pname}): #{statements.map(&:object).map {|r| r.respond_to?(:pname) ? r.pname : r.to_ntriples}}")
@@ -255,7 +255,7 @@ module RDF::Reasoner
255
255
 
256
256
  # Fully entailed types of the resource
257
257
  types = options.fetch(:types) do
258
- queryable.query(subject: resource, predicate: RDF.type).
258
+ queryable.query({subject: resource, predicate: RDF.type}).
259
259
  map {|s| (t = (RDF::Vocabulary.find_term(s.object)) rescue nil) && t.entail(:subClassOf)}.
260
260
  flatten.
261
261
  uniq.
@@ -290,12 +290,12 @@ module RDF::Reasoner
290
290
  # XSD types are valid if the datatype matches, or they are plain and valid according to the grammar of the range
291
291
  resource.datatype == range ||
292
292
  resource.plain? && RDF::Literal.new(resource.value, datatype: range).valid?
293
- elsif range.start_with?(RDF::Vocab::OGC)
293
+ elsif range.start_with?("http://ogp.me/ns/class#")
294
294
  case range
295
- when RDF::Vocab::OGC.boolean_str
296
- [RDF::Vocab::OGC.boolean_str, RDF::XSD.boolean].include?(resource.datatype) ||
295
+ when RDF::URI("http://ogp.me/ns/class#boolean_str")
296
+ [RDF::URI("http://ogp.me/ns/class#boolean_str"), RDF::XSD.boolean].include?(resource.datatype) ||
297
297
  resource.plain? && RDF::Literal::Boolean.new(resource.value).valid?
298
- when RDF::Vocab::OGC.date_time_str
298
+ when RDF::URI("http://ogp.me/ns/class#date_time_str")
299
299
  # Schema.org date based on ISO 8601, mapped to appropriate XSD types for validation
300
300
  case resource
301
301
  when RDF::Literal::Date, RDF::Literal::Time, RDF::Literal::DateTime, RDF::Literal::Duration
@@ -303,27 +303,27 @@ module RDF::Reasoner
303
303
  else
304
304
  ISO_8601.match(resource.value)
305
305
  end
306
- when RDF::Vocab::OGC.determiner_str
306
+ when RDF::URI("http://ogp.me/ns/class#determiner_str")
307
307
  # The lexical space: "", "the", "a", "an", and "auto".
308
308
  resource.plain? && (%w(the a an auto) + [""]).include?(resource.value)
309
- when RDF::Vocab::OGC.float_str
309
+ when RDF::URI("http://ogp.me/ns/class#float_str")
310
310
  # A string representation of a 64-bit signed floating point number. Example lexical values include "1.234", "-1.234", "1.2e3", "-1.2e3", and "7E-10".
311
- [RDF::Vocab::OGC.float_str, RDF::Literal::Double, RDF::Literal::Float].include?(resource.datatype) ||
311
+ [RDF::URI("http://ogp.me/ns/class#float_str"), RDF::Literal::Double, RDF::Literal::Float].include?(resource.datatype) ||
312
312
  resource.plain? && RDF::Literal::Double.new(resource.value).valid?
313
- when RDF::Vocab::OGC.integer_str
313
+ when RDF::URI("http://ogp.me/ns/class#integer_str")
314
314
  resource.is_a?(RDF::Literal::Integer) ||
315
- [RDF::Vocab::OGC.integer_str].include?(resource.datatype) ||
315
+ [RDF::URI("http://ogp.me/ns/class#integer_str")].include?(resource.datatype) ||
316
316
  resource.plain? && RDF::Literal::Integer.new(resource.value).valid?
317
- when RDF::Vocab::OGC.mime_type_str
317
+ when RDF::URI("http://ogp.me/ns/class#mime_type_str")
318
318
  # Valid mime type strings \(e.g., "application/mp3"\).
319
- [RDF::Vocab::OGC.mime_type_str].include?(resource.datatype) ||
319
+ [RDF::URI("http://ogp.me/ns/class#mime_type_str")].include?(resource.datatype) ||
320
320
  resource.plain? && resource.value =~ %r(^[\w\-\+]+/[\w\-\+]+$)
321
- when RDF::Vocab::OGC.string
321
+ when RDF::URI("http://ogp.me/ns/class#string")
322
322
  resource.plain?
323
- when RDF::Vocab::OGC.url
323
+ when RDF::URI("http://ogp.me/ns/class#url")
324
324
  # A string of Unicode characters forming a valid URL having the http or https scheme.
325
325
  u = RDF::URI(resource.value)
326
- resource.datatype == RDF::Vocab::OGC.url ||
326
+ resource.datatype == RDF::URI("http://ogp.me/ns/class#url") ||
327
327
  resource.datatype == RDF::XSD.anyURI ||
328
328
  resource.simple? && u.valid? && u.scheme.to_s =~ /^https?$/
329
329
  else
@@ -337,7 +337,7 @@ module RDF::Reasoner
337
337
  else
338
338
  # Fully entailed types of the resource
339
339
  types = options.fetch(:types) do
340
- queryable.query(subject: resource, predicate: RDF.type).
340
+ queryable.query({subject: resource, predicate: RDF.type}).
341
341
  map {|s| (t = (RDF::Vocabulary.find_term(s.object) rescue nil)) && t.entail(:subClassOf)}.
342
342
  flatten.
343
343
  uniq.
@@ -24,18 +24,20 @@ module RDF::Reasoner
24
24
  # Fully entailed types of resource, if not provided, they are queried
25
25
  def domain_compatible_schema?(resource, queryable, options = {})
26
26
  raise RDF::Reasoner::Error, "#{self} can't get domains" unless property?
27
- domains = Array(self.domainIncludes) - [RDF::OWL.Thing]
27
+ domains = Array(self.domainIncludes) +
28
+ Array(self.properties[:'https://schema.org/domainIncludes']) -
29
+ [RDF::OWL.Thing]
28
30
 
29
31
  # Fully entailed types of the resource
30
- types = entailed_types(resource, queryable, options) unless domains.empty?
32
+ types = entailed_types(resource, queryable, **options) unless domains.empty?
31
33
 
32
34
  # Every domain must match some entailed type
33
35
  resource_acceptable = Array(types).empty? || domains.any? {|d| types.include?(d)}
34
36
 
35
37
  # Resource may still be acceptable if types include schema:Role, and any any other resource references `resource` using this property
36
38
  resource_acceptable ||
37
- types.include?(RDF::Vocab::SCHEMA.Role) &&
38
- !queryable.query(predicate: self, object: resource).empty?
39
+ (types.include?(RDF::URI("http://schema.org/Role")) || types.include?(RDF::URI("https://schema.org/Role"))) &&
40
+ !queryable.query({predicate: self, object: resource}).empty?
39
41
  end
40
42
 
41
43
  ##
@@ -54,16 +56,23 @@ module RDF::Reasoner
54
56
  # Fully entailed types of resource, if not provided, they are queried
55
57
  def range_compatible_schema?(resource, queryable, options = {})
56
58
  raise RDF::Reasoner::Error, "#{self} can't get ranges" unless property?
57
- if !(ranges = Array(self.rangeIncludes) - [RDF::OWL.Thing]).empty?
59
+ if !(ranges = Array(self.rangeIncludes) +
60
+ Array(self.properties[:'https://schema.org/rangeIncludes']) -
61
+ [RDF::OWL.Thing]).empty?
58
62
  if resource.literal?
59
63
  ranges.any? do |range|
60
64
  case range
61
65
  when RDF::RDFS.Literal then true
62
- when RDF::Vocab::SCHEMA.Text then resource.plain? || resource.datatype == RDF::Vocab::SCHEMA.Text
63
- when RDF::Vocab::SCHEMA.Boolean
64
- [RDF::Vocab::SCHEMA.Boolean, RDF::XSD.boolean].include?(resource.datatype) ||
66
+ when RDF::URI("http://schema.org/Text"), RDF::URI("https://schema.org/Text")
67
+ resource.plain? || resource.datatype == RDF::URI("http://schema.org/Text")
68
+ when RDF::URI("http://schema.org/Boolean"), RDF::URI("https://schema.org/Boolean")
69
+ [
70
+ RDF::URI("http://schema.org/Boolean"),
71
+ RDF::URI("https://schema.org/Boolean"),
72
+ RDF::XSD.boolean
73
+ ].include?(resource.datatype) ||
65
74
  resource.plain? && RDF::Literal::Boolean.new(resource.value).valid?
66
- when RDF::Vocab::SCHEMA.Date
75
+ when RDF::URI("http://schema.org/Date"), RDF::URI("https://schema.org/Date")
67
76
  # Schema.org date based on ISO 8601, mapped to appropriate XSD types for validation
68
77
  case resource
69
78
  when RDF::Literal::Date, RDF::Literal::Time, RDF::Literal::DateTime, RDF::Literal::Duration
@@ -71,35 +80,56 @@ module RDF::Reasoner
71
80
  else
72
81
  ISO_8601.match(resource.value)
73
82
  end
74
- when RDF::Vocab::SCHEMA.DateTime
75
- resource.datatype == RDF::Vocab::SCHEMA.DateTime ||
83
+ when RDF::URI("http://schema.org/DateTime"), RDF::URI("https://schema.org/DateTime")
84
+ resource.datatype == RDF::URI("http://schema.org/DateTime") ||
85
+ resource.datatype == RDF::URI("https://schema.org/DateTime") ||
76
86
  resource.is_a?(RDF::Literal::DateTime) ||
77
87
  resource.plain? && RDF::Literal::DateTime.new(resource.value).valid?
78
- when RDF::Vocab::SCHEMA.Duration
88
+ when RDF::URI("http://schema.org/Duration"), RDF::URI("https://schema.org/Duration")
79
89
  value = resource.value
80
90
  value = "P#{value}" unless value.start_with?("P")
81
- resource.datatype == RDF::Vocab::SCHEMA.Duration ||
91
+ resource.datatype == RDF::URI("http://schema.org/Duration") ||
92
+ resource.datatype == RDF::URI("https://schema.org/Duration") ||
82
93
  resource.is_a?(RDF::Literal::Duration) ||
83
94
  resource.plain? && RDF::Literal::Duration.new(value).valid?
84
- when RDF::Vocab::SCHEMA.Time
85
- resource.datatype == RDF::Vocab::SCHEMA.Time ||
95
+ when RDF::URI("http://schema.org/Time"), RDF::URI("https://schema.org/Time")
96
+ resource.datatype == RDF::URI("http://schema.org/Time") ||
97
+ resource.datatype == RDF::URI("https://schema.org/Time") ||
86
98
  resource.is_a?(RDF::Literal::Time) ||
87
99
  resource.plain? && RDF::Literal::Time.new(resource.value).valid?
88
- when RDF::Vocab::SCHEMA.Number
100
+ when RDF::URI("http://schema.org/Number"), RDF::URI("https://schema.org/Number")
89
101
  resource.is_a?(RDF::Literal::Numeric) ||
90
- [RDF::Vocab::SCHEMA.Number, RDF::Vocab::SCHEMA.Float, RDF::Vocab::SCHEMA.Integer].include?(resource.datatype) ||
102
+ [
103
+ RDF::URI("http://schema.org/Number"),
104
+ RDF::URI("http://schema.org/Float"),
105
+ RDF::URI("http://schema.org/Integer"),
106
+ RDF::URI("https://schema.org/Number"),
107
+ RDF::URI("https://schema.org/Float"),
108
+ RDF::URI("https://schema.org/Integer"),
109
+ ].include?(resource.datatype) ||
91
110
  resource.plain? && RDF::Literal::Integer.new(resource.value).valid? ||
92
111
  resource.plain? && RDF::Literal::Double.new(resource.value).valid?
93
- when RDF::Vocab::SCHEMA.Float
112
+ when RDF::URI("http://schema.org/Float"), RDF::URI("https://schema.org/Float")
94
113
  resource.is_a?(RDF::Literal::Double) ||
95
- [RDF::Vocab::SCHEMA.Number, RDF::Vocab::SCHEMA.Float].include?(resource.datatype) ||
114
+ [
115
+ RDF::URI("http://schema.org/Number"),
116
+ RDF::URI("http://schema.org/Float"),
117
+ RDF::URI("https://schema.org/Number"),
118
+ RDF::URI("https://schema.org/Float"),
119
+ ].include?(resource.datatype) ||
96
120
  resource.plain? && RDF::Literal::Double.new(resource.value).valid?
97
- when RDF::Vocab::SCHEMA.Integer
121
+ when RDF::URI("http://schema.org/Integer"), RDF::URI("https://schema.org/Integer")
98
122
  resource.is_a?(RDF::Literal::Integer) ||
99
- [RDF::Vocab::SCHEMA.Number, RDF::Vocab::SCHEMA.Integer].include?(resource.datatype) ||
123
+ [
124
+ RDF::URI("http://schema.org/Number"),
125
+ RDF::URI("http://schema.org/Integer"),
126
+ RDF::URI("https://schema.org/Number"),
127
+ RDF::URI("https://schema.org/Integer"),
128
+ ].include?(resource.datatype) ||
100
129
  resource.plain? && RDF::Literal::Integer.new(resource.value).valid?
101
- when RDF::Vocab::SCHEMA.URL
102
- resource.datatype == RDF::Vocab::SCHEMA.URL ||
130
+ when RDF::URI("http://schema.org/URL"), RDF::URI("https://schema.org/URL")
131
+ resource.datatype == RDF::URI("http://schema.org/URL") ||
132
+ resource.datatype == RDF::URI("https://schema.org/URL") ||
103
133
  resource.datatype == RDF::XSD.anyURI ||
104
134
  resource.plain? && RDF::Literal::AnyURI.new(resource.value).valid?
105
135
  else
@@ -117,18 +147,28 @@ module RDF::Reasoner
117
147
  end
118
148
  end
119
149
  end
120
- elsif %w(True False).map {|v| RDF::Vocab::SCHEMA[v]}.include?(resource) && ranges.include?(RDF::Vocab::SCHEMA.Boolean)
150
+ elsif %w(
151
+ http://schema.org/True
152
+ http://schema.org/False
153
+ https://schema.org/True
154
+ https://schema.org/False
155
+ ).include?(resource) &&
156
+ (ranges.include?(RDF::URI("http://schema.org/Boolean")) || ranges.include?(RDF::URI("https://schema.org/Boolean")))
121
157
  true # Special case for schema boolean resources
122
- elsif ranges.include?(RDF::Vocab::SCHEMA.URL) && resource.uri?
158
+ elsif (ranges.include?(RDF::URI("http://schema.org/URL")) || ranges.include?(RDF::URI("http://schema.org/URL"))) &&
159
+ resource.uri?
123
160
  true # schema:URL matches URI resources
124
- elsif ranges == [RDF::Vocab::SCHEMA.Text] && resource.uri?
161
+ elsif ranges == [RDF::URI("http://schema.org/Text")] && resource.uri?
125
162
  # Allowed if resource is untyped
126
- entailed_types(resource, queryable, options).empty?
163
+ entailed_types(resource, queryable, **options).empty?
164
+ elsif ranges == [RDF::URI("https://schema.org/Text")] && resource.uri?
165
+ # Allowed if resource is untyped
166
+ entailed_types(resource, queryable, **options).empty?
127
167
  elsif literal_range?(ranges)
128
168
  false # If resource isn't literal, this is a range violation
129
169
  else
130
170
  # Fully entailed types of the resource
131
- types = entailed_types(resource, queryable, options)
171
+ types = entailed_types(resource, queryable, **options)
132
172
 
133
173
  # Every range must match some entailed type
134
174
  resource_acceptable = Array(types).empty? || ranges.any? {|d| types.include?(d)}
@@ -137,8 +177,8 @@ module RDF::Reasoner
137
177
  resource_acceptable ||
138
178
 
139
179
  # Resource also acceptable if it is a Role, and the Role object contains the same predicate having a compatible object
140
- types.include?(RDF::Vocab::SCHEMA.Role) &&
141
- queryable.query(subject: resource, predicate: self).any? do |stmt|
180
+ (types.include?(RDF::URI("http://schema.org/Role")) || types.include?(RDF::URI("https://schema.org/Role"))) &&
181
+ queryable.query({subject: resource, predicate: self}).any? do |stmt|
142
182
  acc = self.range_compatible_schema?(stmt.object, queryable)
143
183
  acc
144
184
  end ||
@@ -158,9 +198,25 @@ module RDF::Reasoner
158
198
  def literal_range?(ranges)
159
199
  ranges.all? do |range|
160
200
  case range
161
- when RDF::RDFS.Literal, RDF::Vocab::SCHEMA.Text, RDF::Vocab::SCHEMA.Boolean, RDF::Vocab::SCHEMA.Date,
162
- RDF::Vocab::SCHEMA.DateTime, RDF::Vocab::SCHEMA.Time, RDF::Vocab::SCHEMA.URL,
163
- RDF::Vocab::SCHEMA.Number, RDF::Vocab::SCHEMA.Float, RDF::Vocab::SCHEMA.Integer
201
+ when RDF::RDFS.Literal,
202
+ RDF::URI("http://schema.org/Text"),
203
+ RDF::URI("http://schema.org/Boolean"),
204
+ RDF::URI("http://schema.org/Date"),
205
+ RDF::URI("http://schema.org/DateTime"),
206
+ RDF::URI("http://schema.org/Time"),
207
+ RDF::URI("http://schema.org/URL"),
208
+ RDF::URI("http://schema.org/Number"),
209
+ RDF::URI("http://schema.org/Float"),
210
+ RDF::URI("http://schema.org/Integer"),
211
+ RDF::URI("https://schema.org/Text"),
212
+ RDF::URI("https://schema.org/Boolean"),
213
+ RDF::URI("https://schema.org/Date"),
214
+ RDF::URI("https://schema.org/DateTime"),
215
+ RDF::URI("https://schema.org/Time"),
216
+ RDF::URI("https://schema.org/URL"),
217
+ RDF::URI("https://schema.org/Number"),
218
+ RDF::URI("https://schema.org/Float"),
219
+ RDF::URI("https://schema.org/Integer")
164
220
  true
165
221
  else
166
222
  # If this is an XSD range, look for appropriate literal
@@ -174,9 +230,9 @@ module RDF::Reasoner
174
230
 
175
231
  private
176
232
  # Fully entailed types
177
- def entailed_types(resource, queryable, options = {})
233
+ def entailed_types(resource, queryable, **options)
178
234
  options.fetch(:types) do
179
- queryable.query(subject: resource, predicate: RDF.type).
235
+ queryable.query({subject: resource, predicate: RDF.type}).
180
236
  map {|s| (t = (RDF::Vocabulary.find_term(s.object) rescue nil)) && t.entail(:subClassOf)}.
181
237
  flatten.
182
238
  uniq.
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rdf-reasoner
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.2
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gregg Kellogg
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-04-27 00:00:00.000000000 Z
11
+ date: 2021-02-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rdf
@@ -16,84 +16,96 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '3.0'
19
+ version: '3.1'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 3.1.12
20
23
  type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
24
27
  - - "~>"
25
28
  - !ruby/object:Gem::Version
26
- version: '3.0'
29
+ version: '3.1'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 3.1.12
27
33
  - !ruby/object:Gem::Dependency
28
- name: rdf-vocab
34
+ name: rdf-xsd
29
35
  requirement: !ruby/object:Gem::Requirement
30
36
  requirements:
31
37
  - - "~>"
32
38
  - !ruby/object:Gem::Version
33
- version: '3.0'
39
+ version: '3.1'
34
40
  type: :runtime
35
41
  prerelease: false
36
42
  version_requirements: !ruby/object:Gem::Requirement
37
43
  requirements:
38
44
  - - "~>"
39
45
  - !ruby/object:Gem::Version
40
- version: '3.0'
46
+ version: '3.1'
41
47
  - !ruby/object:Gem::Dependency
42
- name: rdf-xsd
48
+ name: rdf-spec
43
49
  requirement: !ruby/object:Gem::Requirement
44
50
  requirements:
45
51
  - - "~>"
46
52
  - !ruby/object:Gem::Version
47
- version: '3.0'
48
- type: :runtime
53
+ version: '3.1'
54
+ type: :development
49
55
  prerelease: false
50
56
  version_requirements: !ruby/object:Gem::Requirement
51
57
  requirements:
52
58
  - - "~>"
53
59
  - !ruby/object:Gem::Version
54
- version: '3.0'
60
+ version: '3.1'
55
61
  - !ruby/object:Gem::Dependency
56
- name: rdf-spec
62
+ name: rdf-vocab
57
63
  requirement: !ruby/object:Gem::Requirement
58
64
  requirements:
59
65
  - - "~>"
60
66
  - !ruby/object:Gem::Version
61
- version: '3.0'
67
+ version: '3.1'
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: 3.1.10
62
71
  type: :development
63
72
  prerelease: false
64
73
  version_requirements: !ruby/object:Gem::Requirement
65
74
  requirements:
66
75
  - - "~>"
67
76
  - !ruby/object:Gem::Version
68
- version: '3.0'
77
+ version: '3.1'
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: 3.1.10
69
81
  - !ruby/object:Gem::Dependency
70
82
  name: rdf-turtle
71
83
  requirement: !ruby/object:Gem::Requirement
72
84
  requirements:
73
85
  - - "~>"
74
86
  - !ruby/object:Gem::Version
75
- version: '3.0'
87
+ version: '3.1'
76
88
  type: :development
77
89
  prerelease: false
78
90
  version_requirements: !ruby/object:Gem::Requirement
79
91
  requirements:
80
92
  - - "~>"
81
93
  - !ruby/object:Gem::Version
82
- version: '3.0'
94
+ version: '3.1'
83
95
  - !ruby/object:Gem::Dependency
84
96
  name: json-ld
85
97
  requirement: !ruby/object:Gem::Requirement
86
98
  requirements:
87
99
  - - "~>"
88
100
  - !ruby/object:Gem::Version
89
- version: '3.0'
101
+ version: '3.1'
90
102
  type: :development
91
103
  prerelease: false
92
104
  version_requirements: !ruby/object:Gem::Requirement
93
105
  requirements:
94
106
  - - "~>"
95
107
  - !ruby/object:Gem::Version
96
- version: '3.0'
108
+ version: '3.1'
97
109
  - !ruby/object:Gem::Dependency
98
110
  name: equivalent-xml
99
111
  requirement: !ruby/object:Gem::Requirement
@@ -114,28 +126,28 @@ dependencies:
114
126
  requirements:
115
127
  - - "~>"
116
128
  - !ruby/object:Gem::Version
117
- version: '3.8'
129
+ version: '3.10'
118
130
  type: :development
119
131
  prerelease: false
120
132
  version_requirements: !ruby/object:Gem::Requirement
121
133
  requirements:
122
134
  - - "~>"
123
135
  - !ruby/object:Gem::Version
124
- version: '3.8'
136
+ version: '3.10'
125
137
  - !ruby/object:Gem::Dependency
126
138
  name: yard
127
139
  requirement: !ruby/object:Gem::Requirement
128
140
  requirements:
129
141
  - - "~>"
130
142
  - !ruby/object:Gem::Version
131
- version: 0.9.19
143
+ version: '0.9'
132
144
  type: :development
133
145
  prerelease: false
134
146
  version_requirements: !ruby/object:Gem::Requirement
135
147
  requirements:
136
148
  - - "~>"
137
149
  - !ruby/object:Gem::Version
138
- version: 0.9.19
150
+ version: '0.9'
139
151
  description: Reasons over RDFS/OWL vocabularies to generate statements which are entailed
140
152
  based on base RDFS/OWL rules along with vocabulary information. It can also be used
141
153
  to ask specific questions, such as if a given object is consistent with the vocabulary
@@ -156,11 +168,11 @@ files:
156
168
  - lib/rdf/reasoner/rdfs.rb
157
169
  - lib/rdf/reasoner/schema.rb
158
170
  - lib/rdf/reasoner/version.rb
159
- homepage: https://githubhub.com/gkellogg/rdf-reasoner
171
+ homepage: https://github.com/ruby-rdf/rdf-reasoner
160
172
  licenses:
161
173
  - Unlicense
162
174
  metadata: {}
163
- post_install_message:
175
+ post_install_message:
164
176
  rdoc_options: []
165
177
  require_paths:
166
178
  - lib
@@ -168,15 +180,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
168
180
  requirements:
169
181
  - - ">="
170
182
  - !ruby/object:Gem::Version
171
- version: 2.2.2
183
+ version: '2.4'
172
184
  required_rubygems_version: !ruby/object:Gem::Requirement
173
185
  requirements:
174
186
  - - ">="
175
187
  - !ruby/object:Gem::Version
176
188
  version: '0'
177
189
  requirements: []
178
- rubygems_version: 3.0.3
179
- signing_key:
190
+ rubygems_version: 3.2.3
191
+ signing_key:
180
192
  specification_version: 4
181
193
  summary: RDFS/OWL Reasoner for RDF.rb
182
194
  test_files: []