Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit c39b714

Browse files
authoredOct 27, 2020
Merge pull request #117 from balhoff/protege-fixes
Improvements to Protege plugin and OWL API interface implementation
2 parents 3a897a3 + 4572539 commit c39b714

File tree

6 files changed

+89
-25
lines changed

6 files changed

+89
-25
lines changed
 

‎build.sbt

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
21
lazy val owlapiVersion = "4.5.17"
32

43
lazy val commonSettings = Seq(
54
organization := "org.geneontology",
6-
version := "1.0.3",
5+
version := "1.0.4",
76
licenses := Seq("BSD-3-Clause" -> url("https://opensource.org/licenses/BSD-3-Clause")),
87
homepage := Some(url("https://github.com/balhoff/whelk")),
98
crossScalaVersions := Seq("2.12.11", "2.13.3"),
@@ -38,27 +37,28 @@ lazy val testSettings = Seq(
3837
libraryDependencies ++= Seq("com.lihaoyi" %% "utest" % "0.7.5" % Test)
3938
)
4039

41-
lazy val parentProject = project.in(file("."))
40+
lazy val parentProject = project
41+
.in(file("."))
4242
.settings(commonSettings)
43-
.settings(
44-
name := "whelk-project",
45-
skip in publish := true)
43+
.settings(name := "whelk-project", skip in publish := true)
4644
.aggregate(
4745
core,
4846
owlapi,
4947
protege
5048
)
5149

52-
lazy val core = project.in(file("modules/core"))
50+
lazy val core = project
51+
.in(file("modules/core"))
5352
.settings(commonSettings)
5453
.settings(testSettings)
5554
.settings(publishSettings)
5655
.settings(
5756
name := "whelk",
58-
description := "Whelk reasoner core",
57+
description := "Whelk reasoner core"
5958
)
6059

61-
lazy val owlapi = project.in(file("modules/owlapi"))
60+
lazy val owlapi = project
61+
.in(file("modules/owlapi"))
6262
.dependsOn(core)
6363
.enablePlugins(JavaAppPackaging)
6464
.settings(commonSettings)
@@ -69,29 +69,31 @@ lazy val owlapi = project.in(file("modules/owlapi"))
6969
description := "Whelk reasoner OWL API bindings",
7070
mainClass in Compile := Some("org.geneontology.whelk.Main"),
7171
libraryDependencies ++= Seq(
72-
"net.sourceforge.owlapi" % "owlapi-distribution" % owlapiVersion,
73-
"org.phenoscape" %% "scowl" % "1.3.4",
74-
"org.semanticweb.elk" % "elk-owlapi" % "0.4.3" % Test,
72+
"net.sourceforge.owlapi" % "owlapi-distribution" % owlapiVersion,
73+
"org.phenoscape" %% "scowl" % "1.3.4",
74+
"org.semanticweb.elk" % "elk-owlapi" % "0.4.3" % Test,
7575
"net.sourceforge.owlapi" % "org.semanticweb.hermit" % "1.4.0.432" % Test,
76-
"net.sourceforge.owlapi" % "jfact" % "4.0.4" % Test
76+
"net.sourceforge.owlapi" % "jfact" % "4.0.4" % Test
7777
)
7878
)
7979

8080
def isJarToEmbed(file: java.io.File): Boolean = file.getName match {
81-
case name if name startsWith "scala" => true
82-
case _ => false
81+
case name if (name startsWith "scala") || (name startsWith "scowl") => true
82+
case _ => false
8383
}
8484

85-
lazy val protege = project.in(file("modules/protege"))
85+
lazy val protege = project
86+
.in(file("modules/protege"))
8687
.dependsOn(owlapi)
8788
.enablePlugins(SbtOsgi)
8889
.settings(commonSettings)
8990
.settings(
9091
skip in publish := true,
91-
name := "whelk-protege",
92+
name := "Whelk reasoner Protege plugin",
9293
description := "Whelk reasoner Protégé plugin",
9394
// Bundle-Version is set to the version by default.
9495
OsgiKeys.bundleSymbolicName := "org.geneontology.whelk;singleton:=true",
96+
OsgiKeys.bundleActivator := Some("org.protege.editor.owl.ProtegeOWL"),
9597
// Include the packages specified by privatePackage in the bundle.
9698
OsgiKeys.privatePackage := Seq("org.geneontology.*"),
9799
OsgiKeys.exportPackage := Seq("!*"),
@@ -105,7 +107,7 @@ lazy val protege = project.in(file("modules/protege"))
105107
),
106108
libraryDependencies ++= Seq(
107109
"net.sourceforge.owlapi" % "owlapi-distribution" % owlapiVersion % Provided,
108-
"edu.stanford.protege" % "protege-editor-core" % "5.2.0" % Provided,
109-
"edu.stanford.protege" % "protege-editor-owl" % "5.2.0" % Provided
110+
"edu.stanford.protege" % "protege-editor-core" % "5.2.0" % Provided,
111+
"edu.stanford.protege" % "protege-editor-owl" % "5.2.0" % Provided
110112
)
111113
)

‎modules/core/src/main/scala/org/geneontology/whelk/Reasoner.scala

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ final case class ReasonerState(
6060
// Using the regular algorithm for Bottom takes too long
6161
val directSuperClassesOfBottom = closureSubsBySuperclass.collect { case (superclass: AtomicConcept, subclasses) if (subclasses - Bottom - superclass).forall(_.isAnonymous) => superclass }.toSet
6262
val equivalentsToBottom = closureSubsBySuperclass(Bottom).collect { case subclass: AtomicConcept => subclass }
63-
closureSubsBySubclass.collect {
63+
(closureSubsBySubclass - Bottom).collect {
6464
case (c: AtomicConcept, subsumers) => c -> directSubsumers(c, subsumers + Top)
6565
} + (Bottom -> (equivalentsToBottom, directSuperClassesOfBottom))
6666
}
@@ -179,16 +179,20 @@ object Reasoner {
179179
private[this] def processConcept(concept: Concept, reasoner: ReasonerState): ReasonerState = {
180180
if (reasoner.inits(concept)) reasoner
181181
else {
182-
val newState = `R⊤`(concept, R0(concept, reasoner.copy(inits = reasoner.inits + concept)))
182+
val superClassesOfBottom = reasoner.closureSubsBySubclass.getOrElse(Bottom, Set.empty)
183+
val updatedClosureSubsBySubclass = reasoner.closureSubsBySubclass.updated(Bottom, superClassesOfBottom + concept)
184+
val newState = `R⊤`(concept, R0(concept, reasoner.copy(inits = reasoner.inits + concept, closureSubsBySubclass = updatedClosureSubsBySubclass)))
183185
newState.queueDelegates.keysIterator.foldLeft(newState) { (state, delegateKey) =>
184186
state.queueDelegates(delegateKey).processConcept(concept, state)
185187
}
186188
}
187189
}
188190

191+
private[this] val emptySubClassSet: Set[Concept] = Set(Bottom)
192+
189193
private[this] def processConceptInclusion(ci: ConceptInclusion, reasoner: ReasonerState): ReasonerState = {
190194
val ConceptInclusion(subclass, superclass) = ci
191-
val subs = reasoner.closureSubsBySuperclass.getOrElse(superclass, Set.empty)
195+
val subs = reasoner.closureSubsBySuperclass.getOrElse(superclass, emptySubClassSet)
192196
if (subs(subclass)) reasoner else {
193197
val closureSubsBySuperclass = reasoner.closureSubsBySuperclass.updated(superclass, subs + subclass)
194198
val supers = reasoner.closureSubsBySubclass.getOrElse(subclass, Set.empty)
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
Prefix(:=<http://example.org/>)
2+
Prefix(owl:=<http://www.w3.org/2002/07/owl#>)
3+
Prefix(rdf:=<http://www.w3.org/1999/02/22-rdf-syntax-ns#>)
4+
Prefix(xml:=<http://www.w3.org/XML/1998/namespace>)
5+
Prefix(xsd:=<http://www.w3.org/2001/XMLSchema#>)
6+
Prefix(rdfs:=<http://www.w3.org/2000/01/rdf-schema#>)
7+
8+
9+
Ontology(<http://example.org/>
10+
11+
Declaration(Class(:A))
12+
Declaration(Class(:B))
13+
Declaration(Class(:BY))
14+
Declaration(Class(:C))
15+
Declaration(Class(:X))
16+
Declaration(Class(:Y))
17+
Declaration(Class(:Z))
18+
############################
19+
# Classes
20+
############################
21+
22+
# Class: :A (:A)
23+
24+
DisjointClasses(:A :X)
25+
26+
# Class: :B (:B)
27+
28+
SubClassOf(:B :A)
29+
30+
# Class: :BY (:BY)
31+
32+
EquivalentClasses(:BY ObjectIntersectionOf(:B :Y))
33+
34+
# Class: :C (:C)
35+
36+
SubClassOf(:C :B)
37+
38+
# Class: :Y (:Y)
39+
40+
SubClassOf(:Y :X)
41+
42+
# Class: :Z (:Z)
43+
44+
SubClassOf(:Z :Y)
45+
46+
47+
)

‎modules/owlapi/src/test/scala/org/geneontology/whelk/TestOWLReasoner.scala

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,18 @@ object TestOWLReasoner extends TestSuite {
6666
reasoner.getInstances(Class("http://example.org/blah"), true)
6767
}
6868

69+
"Unsatisfiable classes should be equivalent to owl:Nothing" - {
70+
val manager = OWLManager.createOWLOntologyManager()
71+
val ontology = manager.loadOntologyFromOntologyDocument(this.getClass.getResourceAsStream("owl-reasoner-nothing-equiv.ofn"))
72+
val reasoner = new WhelkOWLReasonerFactory().createReasoner(ontology)
73+
assert(reasoner.getSubClasses(Class("http://example.org/C") and Class("http://example.org/Z"), false).isEmpty)
74+
assert(reasoner.getEquivalentClasses(Class("http://example.org/C") and Class("http://example.org/Z")).getEntities.asScala.toSet == Set(OWLNothing))
75+
assert(reasoner.getSubClasses(Class("http://example.org/BY"), false).isEmpty)
76+
assert(reasoner.getEquivalentClasses(Class("http://example.org/BY")).getEntities.asScala.toSet == Set(OWLNothing))
77+
assert(reasoner.getSubClasses(OWLNothing, false).getFlattened.isEmpty)
78+
assert(reasoner.getEquivalentClasses(OWLNothing).getEntities.asScala.toSet == Set(Class("http://example.org/BY")))
79+
}
80+
6981
}
7082

7183
}

‎modules/protege/update.properties

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
id=org.geneontology.whelk
2-
version=1.0
3-
#FIXME
4-
download=https://github.com/balhoff/whelk-protege/releases/download/v0.1.0.1/whelk-protege-0.1.0.1.jar
2+
version=1.0.4
3+
download=https://github.com/balhoff/whelk-protege/releases/download/v1.0.4/whelk-reasoner-protege-plugin-1.0.4.jar
54
name=Whelk plug-in for Protégé
65
readme=https://raw.githubusercontent.com/balhoff/whelk/master/README.md
76
license=https://opensource.org/licenses/BSD-3-Clause

0 commit comments

Comments
 (0)
Please sign in to comment.