From 7446c9f8146c117359846e80c0668a6127a7c03f Mon Sep 17 00:00:00 2001 From: Jim Balhoff Date: Fri, 23 Oct 2020 21:11:01 -0400 Subject: [PATCH 1/4] Fix resources folder path for plugin.xml --- build.sbt | 39 ++++++++++--------- .../main/{resource => resources}/plugin.xml | 0 2 files changed, 21 insertions(+), 18 deletions(-) rename modules/protege/src/main/{resource => resources}/plugin.xml (100%) diff --git a/build.sbt b/build.sbt index a2a244b..46768d3 100644 --- a/build.sbt +++ b/build.sbt @@ -1,4 +1,3 @@ - lazy val owlapiVersion = "4.5.17" lazy val commonSettings = Seq( @@ -38,27 +37,28 @@ lazy val testSettings = Seq( libraryDependencies ++= Seq("com.lihaoyi" %% "utest" % "0.7.5" % Test) ) -lazy val parentProject = project.in(file(".")) +lazy val parentProject = project + .in(file(".")) .settings(commonSettings) - .settings( - name := "whelk-project", - skip in publish := true) + .settings(name := "whelk-project", skip in publish := true) .aggregate( core, owlapi, protege ) -lazy val core = project.in(file("modules/core")) +lazy val core = project + .in(file("modules/core")) .settings(commonSettings) .settings(testSettings) .settings(publishSettings) .settings( name := "whelk", - description := "Whelk reasoner core", + description := "Whelk reasoner core" ) -lazy val owlapi = project.in(file("modules/owlapi")) +lazy val owlapi = project + .in(file("modules/owlapi")) .dependsOn(core) .enablePlugins(JavaAppPackaging) .settings(commonSettings) @@ -69,29 +69,32 @@ lazy val owlapi = project.in(file("modules/owlapi")) description := "Whelk reasoner OWL API bindings", mainClass in Compile := Some("org.geneontology.whelk.Main"), libraryDependencies ++= Seq( - "net.sourceforge.owlapi" % "owlapi-distribution" % owlapiVersion, - "org.phenoscape" %% "scowl" % "1.3.4", - "org.semanticweb.elk" % "elk-owlapi" % "0.4.3" % Test, + "net.sourceforge.owlapi" % "owlapi-distribution" % owlapiVersion, + "org.phenoscape" %% "scowl" % "1.3.4", + "org.semanticweb.elk" % "elk-owlapi" % "0.4.3" % Test, "net.sourceforge.owlapi" % "org.semanticweb.hermit" % "1.4.0.432" % Test, - "net.sourceforge.owlapi" % "jfact" % "4.0.4" % Test + "net.sourceforge.owlapi" % "jfact" % "4.0.4" % Test ) ) def isJarToEmbed(file: java.io.File): Boolean = file.getName match { - case name if name startsWith "scala" => true - case _ => false + case name if (name startsWith "scala") || (name startsWith "scowl") => true + case _ => false } -lazy val protege = project.in(file("modules/protege")) +lazy val protege = project + .in(file("modules/protege")) .dependsOn(owlapi) .enablePlugins(SbtOsgi) .settings(commonSettings) .settings( + //crossScalaVersions := Seq("2.13.3"), skip in publish := true, - name := "whelk-protege", + name := "Whelk reasoner", description := "Whelk reasoner Protégé plugin", // Bundle-Version is set to the version by default. OsgiKeys.bundleSymbolicName := "org.geneontology.whelk;singleton:=true", + OsgiKeys.bundleActivator := Some("org.protege.editor.owl.ProtegeOWL"), // Include the packages specified by privatePackage in the bundle. OsgiKeys.privatePackage := Seq("org.geneontology.*"), OsgiKeys.exportPackage := Seq("!*"), @@ -105,7 +108,7 @@ lazy val protege = project.in(file("modules/protege")) ), libraryDependencies ++= Seq( "net.sourceforge.owlapi" % "owlapi-distribution" % owlapiVersion % Provided, - "edu.stanford.protege" % "protege-editor-core" % "5.2.0" % Provided, - "edu.stanford.protege" % "protege-editor-owl" % "5.2.0" % Provided + "edu.stanford.protege" % "protege-editor-core" % "5.2.0" % Provided, + "edu.stanford.protege" % "protege-editor-owl" % "5.2.0" % Provided ) ) diff --git a/modules/protege/src/main/resource/plugin.xml b/modules/protege/src/main/resources/plugin.xml similarity index 100% rename from modules/protege/src/main/resource/plugin.xml rename to modules/protege/src/main/resources/plugin.xml From 3cd5655cf69cece2846d72244df2cf65ecc78725 Mon Sep 17 00:00:00 2001 From: Jim Balhoff Date: Mon, 26 Oct 2020 16:00:58 -0400 Subject: [PATCH 2/4] Clean up handling of owl:Nothing for OWLAPI interface. --- .../org/geneontology/whelk/Reasoner.scala | 10 ++-- .../whelk/owl-reasoner-nothing-equiv.ofn | 47 +++++++++++++++++++ .../geneontology/whelk/TestOWLReasoner.scala | 12 +++++ 3 files changed, 66 insertions(+), 3 deletions(-) create mode 100644 modules/owlapi/src/test/resources/org/geneontology/whelk/owl-reasoner-nothing-equiv.ofn diff --git a/modules/core/src/main/scala/org/geneontology/whelk/Reasoner.scala b/modules/core/src/main/scala/org/geneontology/whelk/Reasoner.scala index 036a8f6..08e54e4 100644 --- a/modules/core/src/main/scala/org/geneontology/whelk/Reasoner.scala +++ b/modules/core/src/main/scala/org/geneontology/whelk/Reasoner.scala @@ -60,7 +60,7 @@ final case class ReasonerState( // Using the regular algorithm for Bottom takes too long val directSuperClassesOfBottom = closureSubsBySuperclass.collect { case (superclass: AtomicConcept, subclasses) if (subclasses - Bottom - superclass).forall(_.isAnonymous) => superclass }.toSet val equivalentsToBottom = closureSubsBySuperclass(Bottom).collect { case subclass: AtomicConcept => subclass } - closureSubsBySubclass.collect { + (closureSubsBySubclass - Bottom).collect { case (c: AtomicConcept, subsumers) => c -> directSubsumers(c, subsumers + Top) } + (Bottom -> (equivalentsToBottom, directSuperClassesOfBottom)) } @@ -179,16 +179,20 @@ object Reasoner { private[this] def processConcept(concept: Concept, reasoner: ReasonerState): ReasonerState = { if (reasoner.inits(concept)) reasoner else { - val newState = `R⊤`(concept, R0(concept, reasoner.copy(inits = reasoner.inits + concept))) + val superClassesOfBottom = reasoner.closureSubsBySubclass.getOrElse(Bottom, Set.empty) + val updatedClosureSubsBySubclass = reasoner.closureSubsBySubclass.updated(Bottom, superClassesOfBottom + concept) + val newState = `R⊤`(concept, R0(concept, reasoner.copy(inits = reasoner.inits + concept, closureSubsBySubclass = updatedClosureSubsBySubclass))) newState.queueDelegates.keysIterator.foldLeft(newState) { (state, delegateKey) => state.queueDelegates(delegateKey).processConcept(concept, state) } } } + private[this] val emptySubClassSet: Set[Concept] = Set(Bottom) + private[this] def processConceptInclusion(ci: ConceptInclusion, reasoner: ReasonerState): ReasonerState = { val ConceptInclusion(subclass, superclass) = ci - val subs = reasoner.closureSubsBySuperclass.getOrElse(superclass, Set.empty) + val subs = reasoner.closureSubsBySuperclass.getOrElse(superclass, emptySubClassSet) if (subs(subclass)) reasoner else { val closureSubsBySuperclass = reasoner.closureSubsBySuperclass.updated(superclass, subs + subclass) val supers = reasoner.closureSubsBySubclass.getOrElse(subclass, Set.empty) diff --git a/modules/owlapi/src/test/resources/org/geneontology/whelk/owl-reasoner-nothing-equiv.ofn b/modules/owlapi/src/test/resources/org/geneontology/whelk/owl-reasoner-nothing-equiv.ofn new file mode 100644 index 0000000..61f855d --- /dev/null +++ b/modules/owlapi/src/test/resources/org/geneontology/whelk/owl-reasoner-nothing-equiv.ofn @@ -0,0 +1,47 @@ +Prefix(:=) +Prefix(owl:=) +Prefix(rdf:=) +Prefix(xml:=) +Prefix(xsd:=) +Prefix(rdfs:=) + + +Ontology( + +Declaration(Class(:A)) +Declaration(Class(:B)) +Declaration(Class(:BY)) +Declaration(Class(:C)) +Declaration(Class(:X)) +Declaration(Class(:Y)) +Declaration(Class(:Z)) +############################ +# Classes +############################ + +# Class: :A (:A) + +DisjointClasses(:A :X) + +# Class: :B (:B) + +SubClassOf(:B :A) + +# Class: :BY (:BY) + +EquivalentClasses(:BY ObjectIntersectionOf(:B :Y)) + +# Class: :C (:C) + +SubClassOf(:C :B) + +# Class: :Y (:Y) + +SubClassOf(:Y :X) + +# Class: :Z (:Z) + +SubClassOf(:Z :Y) + + +) \ No newline at end of file diff --git a/modules/owlapi/src/test/scala/org/geneontology/whelk/TestOWLReasoner.scala b/modules/owlapi/src/test/scala/org/geneontology/whelk/TestOWLReasoner.scala index adfdce7..3dd66e2 100644 --- a/modules/owlapi/src/test/scala/org/geneontology/whelk/TestOWLReasoner.scala +++ b/modules/owlapi/src/test/scala/org/geneontology/whelk/TestOWLReasoner.scala @@ -66,6 +66,18 @@ object TestOWLReasoner extends TestSuite { reasoner.getInstances(Class("http://example.org/blah"), true) } + "Unsatisfiable classes should be equivalent to owl:Nothing" - { + val manager = OWLManager.createOWLOntologyManager() + val ontology = manager.loadOntologyFromOntologyDocument(this.getClass.getResourceAsStream("owl-reasoner-nothing-equiv.ofn")) + val reasoner = new WhelkOWLReasonerFactory().createReasoner(ontology) + assert(reasoner.getSubClasses(Class("http://example.org/C") and Class("http://example.org/Z"), false).isEmpty) + assert(reasoner.getEquivalentClasses(Class("http://example.org/C") and Class("http://example.org/Z")).getEntities.asScala.toSet == Set(OWLNothing)) + assert(reasoner.getSubClasses(Class("http://example.org/BY"), false).isEmpty) + assert(reasoner.getEquivalentClasses(Class("http://example.org/BY")).getEntities.asScala.toSet == Set(OWLNothing)) + assert(reasoner.getSubClasses(OWLNothing, false).getFlattened.isEmpty) + assert(reasoner.getEquivalentClasses(OWLNothing).getEntities.asScala.toSet == Set(Class("http://example.org/BY"))) + } + } } \ No newline at end of file From 8da5b6e218e97371a2bcc9dc3cf2c7f55b36b942 Mon Sep 17 00:00:00 2001 From: Jim Balhoff Date: Mon, 26 Oct 2020 17:37:27 -0400 Subject: [PATCH 3/4] Tweak build for Protege plugin. --- build.sbt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/build.sbt b/build.sbt index 46768d3..0b249a4 100644 --- a/build.sbt +++ b/build.sbt @@ -2,7 +2,7 @@ lazy val owlapiVersion = "4.5.17" lazy val commonSettings = Seq( organization := "org.geneontology", - version := "1.0.3", + version := "1.0.4", licenses := Seq("BSD-3-Clause" -> url("https://opensource.org/licenses/BSD-3-Clause")), homepage := Some(url("https://github.com/balhoff/whelk")), crossScalaVersions := Seq("2.12.11", "2.13.3"), @@ -88,9 +88,8 @@ lazy val protege = project .enablePlugins(SbtOsgi) .settings(commonSettings) .settings( - //crossScalaVersions := Seq("2.13.3"), skip in publish := true, - name := "Whelk reasoner", + name := "Whelk reasoner Protege plugin", description := "Whelk reasoner Protégé plugin", // Bundle-Version is set to the version by default. OsgiKeys.bundleSymbolicName := "org.geneontology.whelk;singleton:=true", From 457253967b450bf8761eb0e922afdc9ed1c09de3 Mon Sep 17 00:00:00 2001 From: Jim Balhoff Date: Tue, 27 Oct 2020 14:56:43 -0400 Subject: [PATCH 4/4] Update update.properties. --- modules/protege/update.properties | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/modules/protege/update.properties b/modules/protege/update.properties index c87363f..581f876 100644 --- a/modules/protege/update.properties +++ b/modules/protege/update.properties @@ -1,7 +1,6 @@ id=org.geneontology.whelk -version=1.0 -#FIXME -download=https://github.com/balhoff/whelk-protege/releases/download/v0.1.0.1/whelk-protege-0.1.0.1.jar +version=1.0.4 +download=https://github.com/balhoff/whelk-protege/releases/download/v1.0.4/whelk-reasoner-protege-plugin-1.0.4.jar name=Whelk plug-in for Protégé readme=https://raw.githubusercontent.com/balhoff/whelk/master/README.md license=https://opensource.org/licenses/BSD-3-Clause