rdf-reasoner 0.0.1 → 0.0.2

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
  SHA1:
3
- metadata.gz: 7b64147d73a5e38f5925417e9f090176cc01dfa1
4
- data.tar.gz: cd4660566c88ac7074beec70172b92a6fd220706
3
+ metadata.gz: 201995bd765a1158f571d6bdbcebecbcfa2e83f8
4
+ data.tar.gz: 871c90ef242de061b0fd882c1f37f6d9a68bf55d
5
5
  SHA512:
6
- metadata.gz: a8eb0b42cbfae2278cf3fe2c3b15aa9c6a985b600e9ab8b79f4b7feb3c6adcd7e89da0df91a6d5717a41d01aa650672c3f6e243f16028f206ac5bb49ec54e6dc
7
- data.tar.gz: 35f93debd3072386883f6cdda9761a8aac60158f008ddd058c07420dae06f8d5f2883b5dde1bbab1b72204ef0a58c30afc238e124dba305aed12cf1be88b01ef
6
+ metadata.gz: 0ca78b48855476fa1a699afc8268bd324d837a1c1f107e768aae4959112da154f66f06ed7013a6b3327f96785589cd10edb6c8f6889f1101ca64f2210a0bed42
7
+ data.tar.gz: b104515116a9e39c6596c6fbe1d4b52d211db551f5c4f76452e171c90216890920a85d83fd81907d658913d88395345b0869616a357445e4557b55962e5129fe
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.1
1
+ 0.0.2
data/lib/rdf/reasoner.rb CHANGED
@@ -10,7 +10,7 @@ module RDF
10
10
  module Reasoner
11
11
  autoload :OWL, 'rdf/reasoner/owl'
12
12
  autoload :RDFS, 'rdf/reasoner/rdfs'
13
- autoload :SCHEMA, 'rdf/reasoner/schema'
13
+ autoload :Schema, 'rdf/reasoner/schema'
14
14
  autoload :VERSION, 'rdf/reasoner/version'
15
15
 
16
16
  ##
@@ -38,7 +38,7 @@ module RDF::Reasoner
38
38
  # Return inferred subClassOf relationships by recursively applying to named super classes to get a complete set of classes in the ancestor chain of this class
39
39
  # @private
40
40
  def _entail_subClassOf
41
- raise RDF::Reasoner::Error, "#{self} Can't entail subClassOf" unless class?
41
+ return Array(self) unless class? && respond_to?(:subClassOf)
42
42
  subClassOf_cache[self] ||= begin
43
43
  (Array(self.subClassOf).map {|c| c._entail_subClassOf rescue c}.flatten + Array(self)).compact
44
44
  end
@@ -48,18 +48,21 @@ module RDF::Reasoner
48
48
  # Return inferred subClass relationships by recursively applying to named sub classes to get a complete set of classes in the descendant chain of this class
49
49
  # @private
50
50
  def _entail_subClass
51
- raise RDF::Reasoner::Error, "#{self} Can't entail subClass" unless class?
51
+ return Array(self) unless class?
52
52
  descendant_cache[self] ||= begin
53
53
  (Array(self.subClass).map {|c| c._entail_subClass rescue c}.flatten + Array(self)).compact
54
54
  end
55
55
  end
56
56
 
57
57
  ##
58
- # Get the immediate subclasses of this class
58
+ # Get the immediate subclasses of this class.
59
+ #
60
+ # This iterates over terms defined in the vocabulary of this term, as well as the vocabularies imported by this vocabulary.
61
+
59
62
  # @return [Array<RDF::Vocabulary::Term>]
60
63
  def subClass
61
64
  raise RDF::Reasoner::Error, "#{self} Can't entail subClass" unless class?
62
- subClass_cache[self] ||= ::RDF::Vocabulary.map do |v|
65
+ subClass_cache[self] ||= ([self.vocab] + self.vocab.imported_from).map do |v|
63
66
  Array(v.properties).select {|p| p.class? && Array(p.subClassOf).include?(self)}
64
67
  end.flatten.compact
65
68
  end
@@ -68,7 +71,7 @@ module RDF::Reasoner
68
71
  # 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
69
72
  # @private
70
73
  def _entail_subPropertyOf
71
- raise RDF::Reasoner::Error, "#{self} Can't entail subPropertyOf" unless property?
74
+ return Array(self) unless property? && respond_to?(:subPropertyOf)
72
75
  subPropertyOf_cache[self] ||= begin
73
76
  (Array(self.subPropertyOf).map {|c| c._entail_subPropertyOf rescue c}.flatten + Array(self)).compact
74
77
  end
@@ -87,7 +90,7 @@ module RDF::Reasoner
87
90
  def domain_compatible_rdfs?(resource, queryable, options = {})
88
91
  raise RDF::Reasoner::Error, "#{self} can't get domains" unless property?
89
92
  if respond_to?(:domain)
90
- domains = Array(self.domain) - [RDF::OWL.Thing]
93
+ domains = Array(self.domain) - [RDF::OWL.Thing, RDF::RDFS.Resource]
91
94
 
92
95
  # Fully entailed types of the resource
93
96
  types = options.fetch(:types) do
@@ -117,7 +120,7 @@ module RDF::Reasoner
117
120
  # Fully entailed types of resource, if not provided, they are queried
118
121
  def range_compatible_rdfs?(resource, queryable, options = {})
119
122
  raise RDF::Reasoner::Error, "#{self} can't get ranges" unless property?
120
- if respond_to?(:range) && !(ranges = Array(self.range) - [RDF::OWL.Thing]).empty?
123
+ if respond_to?(:range) && !(ranges = Array(self.range) - [RDF::OWL.Thing, RDF::RDFS.Resource]).empty?
121
124
  if resource.literal?
122
125
  ranges.all? do |range|
123
126
  case range
@@ -140,6 +143,12 @@ module RDF::Reasoner
140
143
  uniq.
141
144
  compact
142
145
  end
146
+
147
+ # If any type is a class, add rdfs:Class
148
+ if types.any? {|t| t.is_a?(RDF::Vocabulary::Term) && t.class?} && !types.include?(RDF::RDFS.Class)
149
+ types << RDF::RDFS.Class
150
+ end
151
+
143
152
  # Every range must match some entailed type
144
153
  Array(types).empty? || ranges.all? {|d| types.include?(d)}
145
154
  end
@@ -8,7 +8,26 @@ module RDF::Reasoner
8
8
  # Rules for generating RDFS entailment triples
9
9
  #
10
10
  # Extends `RDF::Vocabulary::Term` with specific entailment capabilities
11
- module SCHEMA
11
+ module Schema
12
+ # See http://www.pelagodesign.com/blog/2009/05/20/iso-8601-date-validation-that-doesnt-suck/
13
+ #
14
+ #
15
+ ISO_8601 = %r(^
16
+ # Year
17
+ ([\+-]?\d{4}(?!\d{2}\b))
18
+ # Month
19
+ ((-?)((0[1-9]|1[0-2])
20
+ (\3([12]\d|0[1-9]|3[01]))?
21
+ | W([0-4]\d|5[0-2])(-?[1-7])?
22
+ | (00[1-9]|0[1-9]\d|[12]\d{2}|3([0-5]\d|6[1-6])))
23
+ ([T\s]((([01]\d|2[0-3])((:?)[0-5]\d)?|24\:?00)
24
+ ([\.,]\d+(?!:))?)?
25
+ (\17[0-5]\d([\.,]\d+)?)?
26
+ ([zZ]|([\+-])([01]\d|2[0-3]):?([0-5]\d)?)?
27
+ )?
28
+ )?
29
+ $)x.freeze
30
+
12
31
  # domain_includes accessor
13
32
  # @return [Array<RDF::Vocabulary::Term>]
14
33
  def domain_includes
@@ -28,6 +47,8 @@ module RDF::Reasoner
28
47
  #
29
48
  # Note that this is different than standard entailment, which simply asserts that the resource has every type in the domain, but this is more useful to check if published data is consistent with the vocabulary definition.
30
49
  #
50
+ # If `resource` is of type `schema:Role`, `resource` is domain acceptable if any other resource references `resource` using this property.
51
+ #
31
52
  # @param [RDF::Resource] resource
32
53
  # @param [RDF::Queryable] queryable
33
54
  # @param [Hash{Symbol => Object}] options
@@ -47,12 +68,19 @@ module RDF::Reasoner
47
68
  end unless domains.empty?
48
69
 
49
70
  # Every domain must match some entailed type
50
- Array(types).empty? || domains.any? {|d| types.include?(d)}
71
+ resource_acceptable = Array(types).empty? || domains.any? {|d| types.include?(d)}
72
+
73
+ # Resource may still be acceptable if types include schema:Role, and any any other resource references `resource` using this property
74
+ resource_acceptable ||
75
+ types.include?(RDF::SCHEMA.Role) &&
76
+ !queryable.query(predicate: self, object: resource).empty?
51
77
  end
52
78
 
53
79
  ##
54
80
  # Schema.org requires that if the property has a range, and the resource has a type that some type matches some range. If the resource is a datatyped Literal, and the range includes a datatype, the resource must be consistent with that.
55
81
  #
82
+ # If `resource` is of type `schema:Role`, it is range acceptable if it has the same property with an acceptable value.
83
+ #
56
84
  # Also, a plain literal (or schema:Text) is always compatible with an object range.
57
85
  #
58
86
  # @param [RDF::Resource] resource
@@ -72,9 +100,13 @@ module RDF::Reasoner
72
100
  [RDF::SCHEMA.Boolean, RDF::XSD.boolean].include?(resource.datatype) ||
73
101
  resource.simple? && RDF::Literal::Boolean.new(resource.value).valid?
74
102
  when RDF::SCHEMA.Date
75
- resource.datatype == RDF::SCHEMA.Date ||
76
- resource.is_a?(RDF::Literal::Date) ||
77
- resource.simple? && RDF::Literal::Date.new(resource.value).valid?
103
+ # Schema.org date based on ISO 8601, mapped to appropriate XSD types for validation
104
+ case resource
105
+ when RDF::Literal::Date, RDF::Literal::Time, RDF::Literal::DateTime, RDF::Literal::Duration
106
+ resource.valid?
107
+ else
108
+ ISO_8601.match(resource.value)
109
+ end
78
110
  when RDF::SCHEMA.DateTime
79
111
  resource.datatype == RDF::SCHEMA.DateTime ||
80
112
  resource.is_a?(RDF::Literal::DateTime) ||
@@ -132,8 +164,17 @@ module RDF::Reasoner
132
164
  uniq.
133
165
  compact
134
166
  end
167
+
135
168
  # Every range must match some entailed type
136
- Array(types).empty? || ranges.any? {|d| types.include?(d)}
169
+ resource_acceptable = Array(types).empty? || ranges.any? {|d| types.include?(d)}
170
+
171
+ # Resource may still be acceptable if it has the same property with an acceptable value
172
+ resource_acceptable ||
173
+ types.include?(RDF::SCHEMA.Role) &&
174
+ queryable.query(subject: resource, predicate: self).any? do |stmt|
175
+ acc = self.range_compatible_schema?(stmt.object, queryable)
176
+ acc
177
+ end
137
178
  end
138
179
  else
139
180
  true
@@ -145,5 +186,5 @@ module RDF::Reasoner
145
186
  end
146
187
 
147
188
  # Extend the Term with this methods
148
- ::RDF::Vocabulary::Term.send(:include, SCHEMA)
189
+ ::RDF::Vocabulary::Term.send(:include, Schema)
149
190
  end
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.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gregg Kellogg
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-06-01 00:00:00.000000000 Z
11
+ date: 2014-06-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rdf
@@ -19,7 +19,7 @@ dependencies:
19
19
  version: '1.1'
20
20
  - - ">="
21
21
  - !ruby/object:Gem::Version
22
- version: 1.1.4
22
+ version: 1.1.4.1
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
@@ -29,7 +29,7 @@ dependencies:
29
29
  version: '1.1'
30
30
  - - ">="
31
31
  - !ruby/object:Gem::Version
32
- version: 1.1.4
32
+ version: 1.1.4.1
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: rdf-xsd
35
35
  requirement: !ruby/object:Gem::Requirement
@@ -92,14 +92,14 @@ dependencies:
92
92
  requirements:
93
93
  - - "~>"
94
94
  - !ruby/object:Gem::Version
95
- version: '2.14'
95
+ version: '3.0'
96
96
  type: :development
97
97
  prerelease: false
98
98
  version_requirements: !ruby/object:Gem::Requirement
99
99
  requirements:
100
100
  - - "~>"
101
101
  - !ruby/object:Gem::Version
102
- version: '2.14'
102
+ version: '3.0'
103
103
  - !ruby/object:Gem::Dependency
104
104
  name: yard
105
105
  requirement: !ruby/object:Gem::Requirement