Skip to content

Commit

Permalink
Finish 0.4.1
Browse files Browse the repository at this point in the history
  • Loading branch information
gkellogg committed Dec 31, 2016
2 parents 2443b45 + f8e9406 commit 60697f6
Show file tree
Hide file tree
Showing 16 changed files with 285 additions and 48 deletions.
12 changes: 7 additions & 5 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ script: "bundle exec rspec spec"
env:
- CI=true
rvm:
- 2.0
- 2.1
- 2.2.4
- 2.3.0
- jruby-9.0.4.0
- 2.2.6
- 2.3.3
- 2.4.0
- jruby
cache: bundler
sudo: false
matrix:
allow_failures:
- rvm: jruby
3 changes: 1 addition & 2 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,13 @@ group :development, :test do
gem 'rdf-isomorphic', github: "ruby-rdf/rdf-isomorphic", branch: "develop"
gem "rdf-spec", github: "ruby-rdf/rdf-spec", branch: "develop"
gem 'rdf-turtle', github: "ruby-rdf/rdf-turtle", branch: "develop"
gem 'sxp', github: "gkellogg/sxp-ruby", branch: "develop"
gem 'sxp', github: "dryruby/sxp.rb", branch: "develop"
gem 'rake'
gem 'simplecov', require: false
gem 'ruby-prof', platform: :mri
end

group :debug do
gem "wirble"
gem "redcarpet", platforms: :ruby
gem "byebug", platforms: :mri
end
Expand Down
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,13 @@ Domain and Range entailment include specific rules for schema.org vocabularies.
end
end

## Command-Line interface
The `rdf` command-line interface is extended with `entail` and `lint` commands. `Entail` can be used in combination, with `serialize` to generate an output graph representation including entailed triples.

## Dependencies

* [Ruby](http://ruby-lang.org/) (>= 2.0)
* [RDF.rb](http://rubygems.org/gems/rdf) (>= 2.0)
* [Ruby](http://ruby-lang.org/) (>= 2.2.2)
* [RDF.rb](http://rubygems.org/gems/rdf) (>= 2.1.1)

## Mailing List

Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.4.0
0.4.1
5 changes: 5 additions & 0 deletions dependencyci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
platform:
Rubygems:
rdf-isomorphic:
tests:
unmaintained: skip
4 changes: 2 additions & 2 deletions lib/rdf/reasoner/owl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def _entail_equivalentClass
if self.predicate == RDF.type
if term = (RDF::Vocabulary.find_term(self.object) rescue nil)
term._entail_equivalentClass do |t|
statements << RDF::Statement(self.to_hash.merge(object: t))
statements << RDF::Statement(self.to_h.merge(object: t, inferred: true))
end
end
end
Expand Down Expand Up @@ -89,7 +89,7 @@ def _entail_equivalentProperty
statements = []
if term = (RDF::Vocabulary.find_term(self.predicate) rescue nil)
term._entail_equivalentProperty do |t|
statements << RDF::Statement(self.to_hash.merge(predicate: t))
statements << RDF::Statement(self.to_h.merge(predicate: t, inferred: true))
end
end
statements.each {|s| yield s} if block_given?
Expand Down
8 changes: 4 additions & 4 deletions lib/rdf/reasoner/rdfs.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def _entail_subClassOf
if self.predicate == RDF.type
if term = (RDF::Vocabulary.find_term(self.object) rescue nil)
term._entail_subClassOf do |t|
statements << RDF::Statement(self.to_hash.merge(object: t))
statements << RDF::Statement(self.to_h.merge(object: t, inferred: true))
end
end
#$stderr.puts("subClassf(#{self.predicate.pname}): #{statements.map(&:object).map {|r| r.respond_to?(:pname) ? r.pname : r.to_ntriples}}}")
Expand Down Expand Up @@ -127,7 +127,7 @@ def _entail_subPropertyOf
statements = []
if term = (RDF::Vocabulary.find_term(self.predicate) rescue nil)
term._entail_subPropertyOf do |t|
statements << RDF::Statement(self.to_hash.merge(predicate: t))
statements << RDF::Statement(self.to_h.merge(predicate: t, inferred: true))
end
#$stderr.puts("subPropertyOf(#{self.predicate.pname}): #{statements.map(&:object).map {|r| r.respond_to?(:pname) ? r.pname : r.to_ntriples}}}")
end
Expand All @@ -146,7 +146,7 @@ def _entail_domain
statements = []
if term = (RDF::Vocabulary.find_term(self.predicate) rescue nil)
term.domain.each do |t|
statements << RDF::Statement(self.to_hash.merge(predicate: RDF.type, object: t))
statements << RDF::Statement(self.to_h.merge(predicate: RDF.type, object: t, inferred: true))
end
end
#$stderr.puts("domain(#{self.predicate.pname}): #{statements.map(&:object).map {|r| r.respond_to?(:pname) ? r.pname : r.to_ntriples}}}")
Expand All @@ -165,7 +165,7 @@ def _entail_range
statements = []
if object.resource? && term = (RDF::Vocabulary.find_term(self.predicate) rescue nil)
term.range.each do |t|
statements << RDF::Statement(self.to_hash.merge(subject: self.object, predicate: RDF.type, object: t))
statements << RDF::Statement(self.to_h.merge(subject: self.object, predicate: RDF.type, object: t, inferred: true))
end
end
#$stderr.puts("range(#{self.predicate.pname}): #{statements.map(&:object).map {|r| r.respond_to?(:pname) ? r.pname : r.to_ntriples}}")
Expand Down
42 changes: 17 additions & 25 deletions lib/rdf/reasoner/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,7 @@ def domain_compatible_schema?(resource, queryable, options = {})
domains = Array(self.domainIncludes) - [RDF::OWL.Thing]

# 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) rescue nil)) && t.entail(:subClassOf)}.
flatten.
uniq.
compact
end unless domains.empty?
types = entailed_types(resource, queryable, options) unless domains.empty?

# Every domain must match some entailed type
resource_acceptable = Array(types).empty? || domains.any? {|d| types.include?(d)}
Expand Down Expand Up @@ -109,7 +103,7 @@ def range_compatible_schema?(resource, queryable, options = {})
resource.datatype == RDF::XSD.anyURI ||
resource.plain? && RDF::Literal::AnyURI.new(resource.value).valid?
else
# If this is an XSD range, look for appropriate literal
# If may be an XSD range, look for appropriate literal
if range.start_with?(RDF::XSD.to_s)
if resource.datatype == RDF::URI(range)
true
Expand All @@ -127,28 +121,14 @@ def range_compatible_schema?(resource, queryable, options = {})
true # Special case for schema boolean resources
elsif ranges.include?(RDF::Vocab::SCHEMA.URL) && resource.uri?
true # schema:URL matches URI resources
elsif ranges.include?(RDF::Vocab::SCHEMA.Text) && resource.uri?
elsif ranges == [RDF::Vocab::SCHEMA.Text] && resource.uri?
# Allowed if resource is untyped
# 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) rescue nil)) && t.entail(:subClassOf)}.
flatten.
uniq.
compact
end
types.empty?
entailed_types(resource, queryable, options).empty?
elsif literal_range?(ranges)
false # If resource isn't literal, this is a range violation
else
# 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) rescue nil)) && t.entail(:subClassOf)}.
flatten.
uniq.
compact
end
types = entailed_types(resource, queryable, options)

# Every range must match some entailed type
resource_acceptable = Array(types).empty? || ranges.any? {|d| types.include?(d)}
Expand Down Expand Up @@ -191,6 +171,18 @@ def literal_range?(ranges)

def self.included(mod)
end

private
# Fully entailed types
def entailed_types(resource, queryable, options = {})
options.fetch(:types) do
queryable.query(:subject => resource, :predicate => RDF.type).
map {|s| (t = (RDF::Vocabulary.find_term(s.object) rescue nil)) && t.entail(:subClassOf)}.
flatten.
uniq.
compact
end
end
end

# Extend the Term with this methods
Expand Down
8 changes: 4 additions & 4 deletions rdf-reasoner.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,17 @@ Gem::Specification.new do |gem|
the vocabulary ruleset. This can be used to implement
SPARQL Entailment Regimes.).gsub(/\s+/m, ' ')

gem.required_ruby_version = '>= 2.0'
gem.required_ruby_version = '>= 2.2.2'
gem.requirements = []
gem.add_runtime_dependency 'rdf', '~> 2.0'
gem.add_runtime_dependency 'rdf', '~> 2.1', '>= 2.1.1'
gem.add_runtime_dependency 'rdf-vocab', '~> 2.0'
gem.add_runtime_dependency 'rdf-xsd', '~> 2.0'

gem.add_runtime_dependency 'rdf-spec', '~> 2.0'
gem.add_development_dependency 'rdf-spec', '~> 2.0'
gem.add_development_dependency 'json-ld', '~> 2.0'
gem.add_development_dependency 'rdf-turtle', '~> 2.0'
gem.add_development_dependency 'equivalent-xml', '~> 0.4'
gem.add_development_dependency 'rspec', '~> 3.4'
gem.add_development_dependency 'yard' , '~> 0.8'
gem.post_install_message = nil
end
end
1 change: 1 addition & 0 deletions spec/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/w3c-rdf
6 changes: 4 additions & 2 deletions spec/format_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,15 @@
describe ".cli_commands" do
require 'rdf/cli'
let(:ttl) {File.expand_path("../../etc/doap.ttl", __FILE__)}
let(:capture) {StringIO.new}

it "entails" do
expect {RDF::CLI.exec(["entail", ttl])}.to write.to(:output)
expect {RDF::CLI.exec(["entail", "serialize", ttl], format: :ttl, output: capture)}.to write.to(:output)
expect(capture.string).not_to be_empty
end

it "lints" do
expect {RDF::CLI.exec(["lint", ttl])}.to write.to(:output)
expect {RDF::CLI.exec(["lint", ttl], format: :ttl)}.to write(/Linted in .* seconds/).to(:output)
end
end
end
2 changes: 2 additions & 0 deletions spec/owl_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
subject {RDF::Statement(RDF::URI("a"), RDF.type, cls)}
let(:results) {entails.map {|r| RDF::Statement(RDF::URI("a"), RDF.type, r)}}
specify {expect(subject.entail(:equivalentClass)).to include(*results)}
specify {expect(subject.entail(:equivalentClass)).to all(be_inferred)}
specify {expect {|b| subject.entail(:equivalentClass, &b)}.to yield_control.at_least(entails.length)}
end

Expand Down Expand Up @@ -65,6 +66,7 @@
subject {RDF::Statement(RDF::URI("a"), prop, RDF::URI("b"))}
let(:results) {entails.map {|r| RDF::Statement(RDF::URI("a"), r, RDF::URI("b"))}}
specify {expect(subject.entail(:equivalentProperty)).to include(*results)}
specify {expect(subject.entail(:equivalentProperty)).to all(be_inferred)}
specify {expect {|b| subject.entail(:equivalentProperty, &b)}.to yield_control.at_least(entails.length)}
end

Expand Down
5 changes: 5 additions & 0 deletions spec/rdfs_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
subject {RDF::Statement(RDF::URI("a"), RDF.type, cls)}
let(:results) {entails.map {|r| RDF::Statement(RDF::URI("a"), RDF.type, r)}}
specify {expect(subject.entail(:subClassOf)).to include(*results)}
specify {expect(subject.entail(:subClassOf)).to all(be_inferred)}
specify {expect {|b| subject.entail(:subClassOf, &b)}.to yield_control.at_least(entails.length)}
end

Expand Down Expand Up @@ -65,6 +66,7 @@
subject {RDF::Statement(RDF::URI("a"), RDF.type, cls)}
let(:results) {entails.map {|r| RDF::Statement(RDF::URI("a"), RDF.type, r)}}
specify {expect(subject.entail(:subClass)).to be_empty}
specify {expect(subject.entail(:subClass)).to all(be_inferred)}
specify {expect {|b| subject.entail(:subClass, &b)}.not_to yield_control}
end

Expand Down Expand Up @@ -103,6 +105,7 @@
subject {RDF::Statement(RDF::URI("a"), prop, RDF::URI("b"))}
let(:results) {entails.map {|r| RDF::Statement(RDF::URI("a"), r, RDF::URI("b"))}}
specify {expect(subject.entail(:subPropertyOf)).to include(*results)}
specify {expect(subject.entail(:subPropertyOf)).to all(be_inferred)}
specify {expect {|b| subject.entail(:subPropertyOf, &b)}.to yield_control.at_least(entails.length)}
end

Expand Down Expand Up @@ -143,6 +146,7 @@
subject {RDF::Statement(RDF::URI("a"), prop, RDF::URI("b"))}
let(:results) {entails.map {|r| RDF::Statement(RDF::URI("a"), RDF.type, r)}}
specify {expect(subject.entail(:domain)).to include(*results)}
specify {expect(subject.entail(:domain)).to all(be_inferred)}
specify {expect {|b| subject.entail(:domain, &b)}.to yield_control.at_least(entails.length)}
end

Expand Down Expand Up @@ -183,6 +187,7 @@
subject {RDF::Statement(RDF::URI("a"), prop, RDF::URI("b"))}
let(:results) {entails.map {|r| RDF::Statement(RDF::URI("b"), RDF.type, r)}}
specify {expect(subject.entail(:range)).to include(*results)}
specify {expect(subject.entail(:range)).to all(be_inferred)}
specify {expect {|b| subject.entail(:range, &b)}.to yield_control.at_least(entails.length)}
end

Expand Down
19 changes: 18 additions & 1 deletion spec/schema_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,18 @@
@prefix schema: <http://schema.org/> .
<foo> schema:height <dist> . <dist> a schema:Distance; schema:name "20 3/4 inches" .
),
"schema:CreativeWork with itemListElement (IRI)" => %(
@prefix schema: <http://schema.org/> .
<foo> schema:itemListElement <obj> . <obj> a schema:CreativeWork .
),
"schema:CreativeWork with itemListElement (BNode)" => %(
@prefix schema: <http://schema.org/> .
<foo> schema:itemListElement [ a schema:CreativeWork ] .
),
"text literal with itemListElement" => %(
@prefix schema: <http://schema.org/> .
<foo> schema:itemListElement "Foo" .
),
}.each do |name, input|
it name do
graph = RDF::Graph.new << RDF::Turtle::Reader.new(input)
Expand Down Expand Up @@ -187,6 +199,7 @@
end
end
end

context "object range violations" do
{
"object of wrong type" => %(
Expand Down Expand Up @@ -239,7 +252,7 @@
"schema:Text with datatyped literal" => %(
@prefix schema: <http://schema.org/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
<foo> a schema:Thing; schema:activeIngredient "foo"^^xsd:token .
<foo> a schema:Thing; schema:recipeIngredient "foo"^^xsd:token .
),
"schema:URL with non-conforming plain literal" => %(
@prefix schema: <http://schema.org/> .
Expand All @@ -249,6 +262,10 @@
@prefix schema: <http://schema.org/> .
<foo> a schema:CreativeWork; schema:isFamilyFriendly "bar" .
),
"date with itemListElement" => %(
@prefix schema: <http://schema.org/> .
<foo> schema:itemListElement "2016-08-22"^^schema:Date .
),
}.each do |name, input|
it name do
graph = RDF::Graph.new << RDF::Turtle::Reader.new(input)
Expand Down
Loading

0 comments on commit 60697f6

Please sign in to comment.