lib/rdf/reasoner/rdfs.rb in rdf-reasoner-0.0.1 vs lib/rdf/reasoner/rdfs.rb in rdf-reasoner-0.0.2
- old
+ new
@@ -36,41 +36,44 @@
##
# 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
# @private
def _entail_subClassOf
- raise RDF::Reasoner::Error, "#{self} Can't entail subClassOf" unless class?
+ return Array(self) unless class? && respond_to?(:subClassOf)
subClassOf_cache[self] ||= begin
(Array(self.subClassOf).map {|c| c._entail_subClassOf rescue c}.flatten + Array(self)).compact
end
end
##
# 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
# @private
def _entail_subClass
- raise RDF::Reasoner::Error, "#{self} Can't entail subClass" unless class?
+ return Array(self) unless class?
descendant_cache[self] ||= begin
(Array(self.subClass).map {|c| c._entail_subClass rescue c}.flatten + Array(self)).compact
end
end
##
- # Get the immediate subclasses of this class
+ # Get the immediate subclasses of this class.
+ #
+ # This iterates over terms defined in the vocabulary of this term, as well as the vocabularies imported by this vocabulary.
+
# @return [Array<RDF::Vocabulary::Term>]
def subClass
raise RDF::Reasoner::Error, "#{self} Can't entail subClass" unless class?
- subClass_cache[self] ||= ::RDF::Vocabulary.map do |v|
+ subClass_cache[self] ||= ([self.vocab] + self.vocab.imported_from).map do |v|
Array(v.properties).select {|p| p.class? && Array(p.subClassOf).include?(self)}
end.flatten.compact
end
##
# 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
# @private
def _entail_subPropertyOf
- raise RDF::Reasoner::Error, "#{self} Can't entail subPropertyOf" unless property?
+ return Array(self) unless property? && respond_to?(:subPropertyOf)
subPropertyOf_cache[self] ||= begin
(Array(self.subPropertyOf).map {|c| c._entail_subPropertyOf rescue c}.flatten + Array(self)).compact
end
end
@@ -85,11 +88,11 @@
# @option options [Array<RDF::Vocabulary::Term>] :types
# Fully entailed types of resource, if not provided, they are queried
def domain_compatible_rdfs?(resource, queryable, options = {})
raise RDF::Reasoner::Error, "#{self} can't get domains" unless property?
if respond_to?(:domain)
- domains = Array(self.domain) - [RDF::OWL.Thing]
+ domains = Array(self.domain) - [RDF::OWL.Thing, RDF::RDFS.Resource]
# Fully entailed types of the resource
types = options.fetch(:types) do
queryable.query(:subject => resource, :predicate => RDF.type).
map {|s| (t = RDF::Vocabulary.find_term(s.object)) && t.entail(:subClassOf)}.
@@ -115,11 +118,11 @@
# @param [Hash{Symbol => Object}] options ({})
# @option options [Array<RDF::Vocabulary::Term>] :types
# Fully entailed types of resource, if not provided, they are queried
def range_compatible_rdfs?(resource, queryable, options = {})
raise RDF::Reasoner::Error, "#{self} can't get ranges" unless property?
- if respond_to?(:range) && !(ranges = Array(self.range) - [RDF::OWL.Thing]).empty?
+ if respond_to?(:range) && !(ranges = Array(self.range) - [RDF::OWL.Thing, RDF::RDFS.Resource]).empty?
if resource.literal?
ranges.all? do |range|
case range
when RDF::RDFS.Literal, RDF.XMLLiteral, RDF.HTML then true
else
@@ -138,9 +141,15 @@
map {|s| (t = RDF::Vocabulary.find_term(s.object)) && t.entail(:subClassOf)}.
flatten.
uniq.
compact
end
+
+ # If any type is a class, add rdfs:Class
+ if types.any? {|t| t.is_a?(RDF::Vocabulary::Term) && t.class?} && !types.include?(RDF::RDFS.Class)
+ types << RDF::RDFS.Class
+ end
+
# Every range must match some entailed type
Array(types).empty? || ranges.all? {|d| types.include?(d)}
end
else
true
\ No newline at end of file