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 +4 -4
- data/VERSION +1 -1
- data/lib/rdf/reasoner.rb +1 -1
- data/lib/rdf/reasoner/rdfs.rb +16 -7
- data/lib/rdf/reasoner/schema.rb +48 -7
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 201995bd765a1158f571d6bdbcebecbcfa2e83f8
|
4
|
+
data.tar.gz: 871c90ef242de061b0fd882c1f37f6d9a68bf55d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0ca78b48855476fa1a699afc8268bd324d837a1c1f107e768aae4959112da154f66f06ed7013a6b3327f96785589cd10edb6c8f6889f1101ca64f2210a0bed42
|
7
|
+
data.tar.gz: b104515116a9e39c6596c6fbe1d4b52d211db551f5c4f76452e171c90216890920a85d83fd81907d658913d88395345b0869616a357445e4557b55962e5129fe
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.2
|
data/lib/rdf/reasoner.rb
CHANGED
data/lib/rdf/reasoner/rdfs.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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] ||=
|
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
|
-
|
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
|
data/lib/rdf/reasoner/schema.rb
CHANGED
@@ -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
|
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
|
-
|
76
|
-
resource
|
77
|
-
|
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,
|
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.
|
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-
|
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: '
|
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: '
|
102
|
+
version: '3.0'
|
103
103
|
- !ruby/object:Gem::Dependency
|
104
104
|
name: yard
|
105
105
|
requirement: !ruby/object:Gem::Requirement
|