This is an automated email from the ASF dual-hosted git repository.
andy pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/jena.git
The following commit(s) were added to refs/heads/main by this push:
new 3a196f50cd GH-2487: add OntModels#namedHierarchyRoots
3a196f50cd is described below
commit 3a196f50cdc6f315440c4a113f5f29d1c41f9230
Author: sszuev <[email protected]>
AuthorDate: Sun Jul 7 13:15:47 2024 +0300
GH-2487: add OntModels#namedHierarchyRoots
---
.../org/apache/jena/ontapi/utils/OntModels.java | 45 +-
.../java/org/apache/jena/ontapi/OntModelsTest.java | 478 +++++++++++++++++++++
2 files changed, 522 insertions(+), 1 deletion(-)
diff --git
a/jena-ontapi/src/main/java/org/apache/jena/ontapi/utils/OntModels.java
b/jena-ontapi/src/main/java/org/apache/jena/ontapi/utils/OntModels.java
index 4af32c8b52..ae0e180272 100644
--- a/jena-ontapi/src/main/java/org/apache/jena/ontapi/utils/OntModels.java
+++ b/jena-ontapi/src/main/java/org/apache/jena/ontapi/utils/OntModels.java
@@ -18,6 +18,7 @@
package org.apache.jena.ontapi.utils;
+import org.apache.jena.graph.Triple;
import org.apache.jena.ontapi.OntJenaException;
import org.apache.jena.ontapi.common.OntConfig;
import org.apache.jena.ontapi.common.OntEnhGraph;
@@ -39,7 +40,6 @@ import org.apache.jena.ontapi.model.OntObjectProperty;
import org.apache.jena.ontapi.model.OntSWRL;
import org.apache.jena.ontapi.model.OntStatement;
import org.apache.jena.ontapi.model.RDFNodeList;
-import org.apache.jena.graph.Triple;
import org.apache.jena.rdf.model.Property;
import org.apache.jena.rdf.model.RDFNode;
import org.apache.jena.rdf.model.Resource;
@@ -48,7 +48,9 @@ import org.apache.jena.reasoner.Reasoner;
import org.apache.jena.util.iterator.ExtendedIterator;
import java.util.ArrayDeque;
+import java.util.Collection;
import java.util.Deque;
+import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.stream.Stream;
@@ -372,4 +374,45 @@ public class OntModels {
public static OntConfig config(OntModel m) {
return (m instanceof OntEnhGraph) ? ((OntEnhGraph)
m).getOntPersonality().getConfig() : null;
}
+
+ /**
+ * Answer a stream of the named hierarchy roots of a given OntModel.
+ * This will be similar to the results of {@code OntModel.hierarchyRoot()},
+ * with the added constraint that every member of the returned stream will
be a named class,
+ * not an anonymous class expression.
+ * The named root classes are calculated from the root classes
+ * by recursively replacing every anonymous class with its direct
subclasses.
+ * Thus, it can be seen
+ * that the values in the stream consist of the shallowest fringe of named
classes in the hierarchy.
+ *
+ * @param m {@link OntModel}
+ * @return a {@code Stream} of {@link OntClass.Named}
+ * @see OntModel#hierarchyRoots()
+ */
+ public static Stream<OntClass.Named> namedHierarchyRoots(OntModel m) {
+ Set<OntClass> named = new HashSet<>();
+ Set<OntClass> anonymous = new HashSet<>();
+ collectNamedHierarchyRoots(m.getOWLThing(), m.hierarchyRoots(), named,
anonymous);
+ while (!anonymous.isEmpty()) {
+ OntClass anon = anonymous.iterator().next();
+ anonymous.remove(anon);
+ collectNamedHierarchyRoots(m.getOWLThing(), anon.subClasses(true),
named, anonymous);
+ }
+ return named.stream().map(OntClass::asNamed);
+ }
+
+ private static void collectNamedHierarchyRoots(OntClass thing,
+ Stream<OntClass> classes,
+ Collection<OntClass> named,
+ Collection<OntClass>
anonymous) {
+ classes.forEach(clazz -> {
+ if (named.contains(clazz) || anonymous.contains(clazz)) {
+ return;
+ }
+ if (clazz.superClasses(false)
+ .allMatch(it -> it.isAnon() || it.equals(clazz) ||
it.equals(thing))) {
+ (clazz.isAnon() ? anonymous : named).add(clazz);
+ }
+ });
+ }
}
diff --git
a/jena-ontapi/src/test/java/org/apache/jena/ontapi/OntModelsTest.java
b/jena-ontapi/src/test/java/org/apache/jena/ontapi/OntModelsTest.java
new file mode 100644
index 0000000000..2ec8fddc83
--- /dev/null
+++ b/jena-ontapi/src/test/java/org/apache/jena/ontapi/OntModelsTest.java
@@ -0,0 +1,478 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.ontapi;
+
+import org.apache.jena.ontapi.model.OntClass;
+import org.apache.jena.ontapi.model.OntModel;
+import org.apache.jena.ontapi.testutils.RDFIOTestUtils;
+import org.apache.jena.ontapi.utils.OntModels;
+import org.apache.jena.rdf.model.Resource;
+import org.apache.jena.riot.Lang;
+import org.apache.jena.vocabulary.OWL;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.EnumSource;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+public class OntModelsTest {
+
+ @ParameterizedTest
+ @EnumSource(names = {
+ "OWL2_DL_MEM_RDFS_BUILTIN_INF",
+ "OWL2_DL_MEM",
+ "OWL2_DL_MEM_RDFS_INF",
+ "OWL2_MEM",
+ "OWL2_MEM_RDFS_INF",
+ "OWL2_MEM_MICRO_RULES_INF",
+ "OWL2_EL_MEM",
+ "OWL2_EL_MEM_RDFS_INF",
+ "OWL2_QL_MEM",
+ "OWL2_QL_MEM_RDFS_INF",
+ "OWL2_RL_MEM",
+ "OWL2_RL_MEM_RDFS_INF",
+ "OWL1_DL_MEM",
+ "OWL1_DL_MEM_RDFS_INF",
+ "OWL1_MEM",
+ "OWL1_MEM_RDFS_INF",
+ "OWL1_MEM_MICRO_RULES_INF",
+ "OWL1_LITE_MEM",
+ "OWL1_LITE_MEM_RDFS_INF",
+ "RDFS_MEM",
+ "RDFS_MEM_TRANS_INF",
+ })
+ public void testNamedHierarchyRoots1a(TestSpec spec) {
+ // A
+ // / / \
+ // / B C
+ // | / \ / \
+ // D E F
+ // / \
+ // G H = K
+ // / \
+ // L M
+ OntModel m =
TestModelFactory.createClassesABCDEFGHKLM(OntModelFactory.createModel(spec.inst));
+ OntClass A = m.getOntClass(TestModelFactory.NS + "A");
+ Assertions.assertEquals(List.of(A),
OntModels.namedHierarchyRoots(m).toList());
+ }
+
+ @ParameterizedTest
+ @EnumSource(names = {
+ "OWL2_DL_MEM_TRANS_INF",
+ "OWL2_DL_MEM_RULES_INF",
+ "OWL2_MEM_TRANS_INF",
+ "OWL2_MEM_RULES_INF",
+ "OWL2_MEM_MINI_RULES_INF",
+ "OWL2_EL_MEM_TRANS_INF",
+ "OWL2_EL_MEM_RULES_INF",
+ "OWL2_QL_MEM_TRANS_INF",
+ "OWL2_QL_MEM_RULES_INF",
+ "OWL2_RL_MEM_TRANS_INF",
+ "OWL2_RL_MEM_RULES_INF",
+ "OWL1_DL_MEM_TRANS_INF",
+ "OWL1_DL_MEM_RULES_INF",
+ "OWL1_MEM_TRANS_INF",
+ "OWL1_MEM_RULES_INF",
+ "OWL1_MEM_MINI_RULES_INF",
+ "OWL1_LITE_MEM_TRANS_INF",
+ "OWL1_LITE_MEM_RULES_INF",
+ "RDFS_MEM_RDFS_INF",
+ })
+ public void testNamedHierarchyRoots1b(TestSpec spec) {
+ // A
+ // / / \
+ // / B C
+ // | / \ / \
+ // D E F
+ // / \
+ // G H = K
+ // / \
+ // L M
+ OntModel m =
TestModelFactory.createClassesABCDEFGHKLM(OntModelFactory.createModel(spec.inst));
+ Assertions.assertEquals(List.of(),
OntModels.namedHierarchyRoots(m).toList());
+ }
+
+ @ParameterizedTest
+ @EnumSource(names = {
+ "OWL2_DL_MEM_RDFS_BUILTIN_INF",
+ "OWL2_DL_MEM",
+ "OWL2_DL_MEM_RDFS_INF",
+ "OWL2_MEM",
+ "OWL2_MEM_RDFS_INF",
+ "OWL2_EL_MEM",
+ "OWL2_EL_MEM_RDFS_INF",
+ "OWL2_QL_MEM",
+ "OWL2_QL_MEM_RDFS_INF",
+ "OWL2_RL_MEM",
+ "OWL2_RL_MEM_RDFS_INF",
+ "OWL1_DL_MEM",
+ "OWL1_DL_MEM_RDFS_INF",
+ "OWL1_MEM",
+ "OWL1_MEM_RDFS_INF",
+ "OWL1_LITE_MEM",
+ "OWL1_LITE_MEM_RDFS_INF",
+ })
+ public void testNamedHierarchyRoots2a(TestSpec spec) {
+ OntModel m =
RDFIOTestUtils.readResourceToModel(OntModelFactory.createModel(spec.inst),
"/pizza.ttl", Lang.TURTLE);
+ Set<String> actual =
OntModels.namedHierarchyRoots(m).map(Resource::getLocalName).collect(Collectors.toSet());
+ Set<String> expected = Set.of(
+ "NonVegetarianPizza",
+ "VegetarianTopping",
+ "DomainConcept",
+ "SpicyPizza",
+ "VegetarianPizza",
+ "SpicyPizzaEquivalent",
+ "MeatyPizza",
+ "CheeseyPizza",
+ "VegetarianPizzaEquivalent2",
+ "Country",
+ "ThinAndCrispyPizza",
+ "SpicyTopping",
+ "ValuePartition",
+ "VegetarianPizzaEquivalent1",
+ "InterestingPizza",
+ "RealItalianPizza");
+ Assertions.assertEquals(expected, actual);
+ }
+
+ @ParameterizedTest
+ @EnumSource(names = {
+ "RDFS_MEM_RDFS_INF",
+ })
+ public void testNamedHierarchyRoots2b(TestSpec spec) {
+ OntModel m =
RDFIOTestUtils.readResourceToModel(OntModelFactory.createModel(spec.inst),
"/pizza.ttl", Lang.TURTLE);
+ Set<String> actual =
OntModels.namedHierarchyRoots(m).map(Resource::getLocalName).collect(Collectors.toSet());
+
+ Set<String> expected = Set.of(
+ // reserved in OWL, but not in RDFS
+ "ObjectProperty",
+ "InverseFunctionalProperty",
+ "Ontology",
+ "TransitiveProperty",
+ "FunctionalProperty",
+ "Restriction",
+ "AllDifferent",
+ "Class",
+ "NamedIndividual",
+ "Thing",
+
+ "DomainConcept",
+ "Country",
+ "ValuePartition",
+ "RealItalianPizza");
+ Assertions.assertEquals(expected, actual);
+ }
+
+ @ParameterizedTest
+ @EnumSource(names = {
+ "OWL2_DL_MEM_TRANS_INF",
+ "OWL2_MEM_TRANS_INF",
+ "OWL2_EL_MEM_TRANS_INF",
+ "OWL2_QL_MEM_TRANS_INF",
+ "OWL2_RL_MEM_TRANS_INF",
+ "OWL1_DL_MEM_TRANS_INF",
+ "OWL1_MEM_TRANS_INF",
+ "OWL1_LITE_MEM_TRANS_INF",
+ "RDFS_MEM",
+ "RDFS_MEM_TRANS_INF",
+ })
+ public void testNamedHierarchyRoots2c(TestSpec spec) {
+ OntModel m =
RDFIOTestUtils.readResourceToModel(OntModelFactory.createModel(spec.inst),
"/pizza.ttl", Lang.TURTLE);
+ Set<String> actual =
OntModels.namedHierarchyRoots(m).map(Resource::getLocalName).collect(Collectors.toSet());
+
+ Set<String> expected = Set.of();
+ Assertions.assertEquals(expected, actual);
+ }
+
+ @Test
+ public void testNamedHierarchyRoots3() {
+ OntModel m =
OntModelFactory.createModel(OntSpecification.OWL2_FULL_MEM_MICRO_RULES_INF);
+ OntClass A = m.createOntClass(TestModelFactory.NS + "A");
+ OntClass B = m.createOntClass(TestModelFactory.NS + "B");
+ OntClass C = m.createOntClass(TestModelFactory.NS + "C");
+ OntClass D = m.createOntClass(TestModelFactory.NS + "D");
+ OntClass E = m.createOntClass(TestModelFactory.NS + "E");
+ OntClass F = m.createOntClass(TestModelFactory.NS + "F");
+ OntClass G = m.createOntClass(TestModelFactory.NS + "G");
+
+ A.addSubClass(B);
+ B.addSubClass(C);
+ C.addSubClass(D);
+ E.addSubClass(E);
+ E.addSubClass(F);
+
+ List<OntClass.Named> nhr = OntModels.namedHierarchyRoots(m).toList();
+ Assertions.assertEquals(3, nhr.size());
+ Assertions.assertTrue(nhr.contains(A));
+ Assertions.assertTrue(nhr.contains(E));
+ Assertions.assertTrue(nhr.contains(G));
+ }
+
+ @Test
+ public void testNamedHierarchyRoots4() {
+ OntModel m =
OntModelFactory.createModel(OntSpecification.OWL2_FULL_MEM_MICRO_RULES_INF);
+ OntClass A = m.createOntClass(TestModelFactory.NS + "A");
+ OntClass B = m.createOntClass(TestModelFactory.NS + "B");
+ OntClass C = m.createOntClass(TestModelFactory.NS + "C");
+ OntClass D = m.createOntClass(TestModelFactory.NS + "D");
+ OntClass E = m.createOntClass(TestModelFactory.NS + "E");
+ OntClass F = m.createOntClass(TestModelFactory.NS + "F");
+ OntClass G = m.createOntClass(TestModelFactory.NS + "G");
+
+ A.addSubClass(B);
+ B.addSubClass(C);
+ C.addSubClass(D);
+ E.addSubClass(E);
+ E.addSubClass(F);
+
+ OntClass anon0 = m.createObjectUnionOf(A, F);
+ anon0.addSubClass(A);
+ anon0.addSubClass(E);
+
+ List<OntClass.Named> nhr = OntModels.namedHierarchyRoots(m).toList();
+ Assertions.assertEquals(3, nhr.size());
+ Assertions.assertTrue(nhr.contains(A));
+ Assertions.assertTrue(nhr.contains(E));
+ Assertions.assertTrue(nhr.contains(G));
+ }
+
+ @Test
+ public void testNamedHierarchyRoots5() {
+ OntModel m =
OntModelFactory.createModel(OntSpecification.OWL2_FULL_MEM_MICRO_RULES_INF);
+ OntClass A = m.createOntClass(TestModelFactory.NS + "A");
+ OntClass B = m.createOntClass(TestModelFactory.NS + "B");
+ OntClass C = m.createOntClass(TestModelFactory.NS + "C");
+ OntClass D = m.createOntClass(TestModelFactory.NS + "D");
+ OntClass E = m.createOntClass(TestModelFactory.NS + "E");
+ OntClass F = m.createOntClass(TestModelFactory.NS + "F");
+ OntClass G = m.createOntClass(TestModelFactory.NS + "G");
+
+ OntClass anon0 = m.createObjectUnionOf(A, B, G);
+ OntClass anon1 = m.createObjectUnionOf(C, D, anon0);
+ anon0.addSubClass(A);
+ anon0.addSubClass(E);
+ anon0.addSubClass(anon1);
+ anon1.addSubClass(G);
+
+ A.addSubClass(B);
+ B.addSubClass(C);
+ C.addSubClass(D);
+ E.addSubClass(E);
+ E.addSubClass(F);
+
+ List<OntClass.Named> nhr = OntModels.namedHierarchyRoots(m).toList();
+ Assertions.assertEquals(3, nhr.size());
+ Assertions.assertTrue(nhr.contains(A));
+ Assertions.assertTrue(nhr.contains(E));
+ Assertions.assertTrue(nhr.contains(G));
+ }
+
+ @Test
+ public void testNamedHierarchyRoots6() {
+ OntModel m =
OntModelFactory.createModel(OntSpecification.OWL2_FULL_MEM_MICRO_RULES_INF);
+ OntClass A = m.createOntClass(TestModelFactory.NS + "A");
+ OntClass B = m.createOntClass(TestModelFactory.NS + "B");
+ OntClass C = m.createOntClass(TestModelFactory.NS + "C");
+ OntClass D = m.createOntClass(TestModelFactory.NS + "D");
+ OntClass E = m.createOntClass(TestModelFactory.NS + "E");
+ OntClass F = m.createOntClass(TestModelFactory.NS + "F");
+ OntClass G = m.createOntClass(TestModelFactory.NS + "G");
+
+ OntClass anon0 = m.createObjectComplementOf(F);
+ OntClass anon1 = m.createObjectUnionOf(F);
+ anon0.addSubClass(A);
+ anon1.addSubClass(A);
+
+ // only A is root
+ A.addSubClass(B);
+ A.addSubClass(C);
+ A.addSubClass(D);
+ A.addSubClass(E);
+ A.addSubClass(F);
+ A.addSubClass(G);
+
+ List<OntClass.Named> nhr = OntModels.namedHierarchyRoots(m).toList();
+ Assertions.assertEquals(List.of(A), nhr);
+ }
+
+ @Test
+ public void testNamedHierarchyRoots7() {
+ OntModel m =
OntModelFactory.createModel(OntSpecification.OWL2_FULL_MEM_MICRO_RULES_INF);
+ OntClass A = m.createOntClass(TestModelFactory.NS + "A");
+ OntClass B = m.createOntClass(TestModelFactory.NS + "B");
+ OntClass C = m.createOntClass(TestModelFactory.NS + "C");
+ OntClass D = m.createOntClass(TestModelFactory.NS + "D");
+ OntClass E = m.createOntClass(TestModelFactory.NS + "E");
+ OntClass F = m.createOntClass(TestModelFactory.NS + "F");
+ OntClass G = m.createOntClass(TestModelFactory.NS + "G");
+
+ OntClass anon0 = m.createObjectUnionOf(A, B);
+ OntClass anon1 = m.createObjectUnionOf(C, D, anon0);
+ anon0.addSubClass(A);
+ anon1.addSubClass(B);
+
+ // only A is root, because B is a subclass of A
+ // even though B is a subclass of an anon root
+ A.addSubClass(B);
+ A.addSubClass(C);
+ A.addSubClass(D);
+ A.addSubClass(E);
+ A.addSubClass(F);
+ A.addSubClass(G);
+
+ List<OntClass.Named> nhr = OntModels.namedHierarchyRoots(m).toList();
+ Assertions.assertEquals(List.of(A), nhr);
+ }
+
+ @ParameterizedTest
+ @EnumSource(names = {
+ "OWL2_DL_MEM_RDFS_BUILTIN_INF",
+ "OWL2_DL_MEM",
+ "OWL2_DL_MEM_RDFS_INF",
+ "OWL2_MEM",
+ "OWL2_MEM_RDFS_INF",
+ "OWL1_DL_MEM",
+ "OWL1_DL_MEM_RDFS_INF",
+ "OWL1_MEM",
+ "OWL1_MEM_RDFS_INF",
+ })
+ public void testNamedHierarchyRoots9a(TestSpec spec) {
+ OntModel m = OntModelFactory.createModel(spec.inst);
+
+ OntClass c0 = m.createOntClass(":C0");
+ OntClass c1 = m.createOntClass(":C1");
+ OntClass c2 = m.createOntClass(":C2");
+ OntClass c3 = m.createOntClass(":C3");
+ OntClass c4 = m.createOntClass(":C4");
+ OntClass c5 = m.createOntClass(":C5");
+ OntClass c6 = m.createOntClass(":C6");
+ OntClass c7 = m.createOntClass(":C7");
+ OntClass c8 = m.createOntClass(":C8");
+ OntClass c9 = m.createDataSomeValuesFrom(m.createDataProperty(":p1"),
m.createDataOneOf(m.createLiteral("42")));
+ OntClass c10 = m.createObjectOneOf(m.createIndividual(null, c0),
m.createIndividual(null, c1));
+ OntClass c11 = m.createObjectComplementOf(c6);
+ OntClass c12 = OWL.Thing.inModel(m).as(OntClass.class);
+ OntClass c13 = OWL.Nothing.inModel(m).as(OntClass.class);
+
+ c1.addSuperClass(c2);
+ c2.addSuperClass(c3);
+ c3.addSuperClass(c4);
+ c5.addSuperClass(c6);
+ c6.addSuperClass(c13);
+ c8.addSuperClass(c11);
+ c9.addSuperClass(c10);
+ c10.addSuperClass(c5);
+ c10.addSuperClass(c7);
+ c11.addSuperClass(c12);
+
+ Set<OntClass> actual =
OntModels.namedHierarchyRoots(m).collect(Collectors.toSet());
+ Set<Resource> expected = Set.of(c0, c4, c7, c8);
+
+ Assertions.assertEquals(expected, actual);
+ }
+
+ @ParameterizedTest
+ @EnumSource(names = {
+ "OWL2_DL_MEM_RULES_INF",
+ "OWL2_MEM_RULES_INF",
+ "OWL2_MEM_MINI_RULES_INF",
+ "OWL1_DL_MEM_RULES_INF",
+ "OWL1_MEM_RULES_INF",
+ "OWL1_MEM_MINI_RULES_INF",
+ })
+ public void testNamedHierarchyRoots9b(TestSpec spec) {
+ OntModel m = OntModelFactory.createModel(spec.inst);
+
+ OntClass c0 = m.createOntClass(":C0");
+ OntClass c1 = m.createOntClass(":C1");
+ OntClass c2 = m.createOntClass(":C2");
+ OntClass c3 = m.createOntClass(":C3");
+ OntClass c4 = m.createOntClass(":C4");
+ OntClass c5 = m.createOntClass(":C5");
+ OntClass c6 = m.createOntClass(":C6");
+ OntClass c7 = m.createOntClass(":C7");
+ OntClass c8 = m.createOntClass(":C8");
+ OntClass c9 = m.createDataSomeValuesFrom(m.createDataProperty(":p1"),
m.createDataOneOf(m.createLiteral("42")));
+ OntClass c10 = m.createObjectOneOf(m.createIndividual(null, c0),
m.createIndividual(null, c1));
+ OntClass c11 = m.createObjectComplementOf(c6);
+ OntClass c12 = OWL.Thing.inModel(m).as(OntClass.class);
+ OntClass c13 = OWL.Nothing.inModel(m).as(OntClass.class);
+
+ c1.addSuperClass(c2);
+ c2.addSuperClass(c3);
+ c3.addSuperClass(c4);
+ c5.addSuperClass(c6);
+ c6.addSuperClass(c13);
+ c8.addSuperClass(c11);
+ c9.addSuperClass(c10);
+ c10.addSuperClass(c5);
+ c10.addSuperClass(c7);
+ c11.addSuperClass(c12);
+
+ List<OntClass.Named> actual =
OntModels.namedHierarchyRoots(m).toList();
+ Assertions.assertTrue(actual.isEmpty());
+ }
+
+ @ParameterizedTest
+ @EnumSource(names = {
+ "OWL2_DL_MEM_TRANS_INF",
+ "OWL2_MEM_TRANS_INF",
+ "OWL1_DL_MEM_TRANS_INF",
+ "OWL1_MEM_TRANS_INF",
+ })
+ public void testNamedHierarchyRoots9c(TestSpec spec) {
+ OntModel m = OntModelFactory.createModel(spec.inst);
+
+ OntClass c0 = m.createOntClass(":C0");
+ OntClass c1 = m.createOntClass(":C1");
+ OntClass c2 = m.createOntClass(":C2");
+ OntClass c3 = m.createOntClass(":C3");
+ OntClass c4 = m.createOntClass(":C4");
+ OntClass c5 = m.createOntClass(":C5");
+ OntClass c6 = m.createOntClass(":C6");
+ OntClass c7 = m.createOntClass(":C7");
+ OntClass c8 = m.createOntClass(":C8");
+ OntClass c9 = m.createDataSomeValuesFrom(m.createDataProperty(":p1"),
m.createDataOneOf(m.createLiteral("42")));
+ OntClass c10 = m.createObjectOneOf(m.createIndividual(null, c0),
m.createIndividual(null, c1));
+ OntClass c11 = m.createObjectComplementOf(c6);
+ OntClass c12 = OWL.Thing.inModel(m).as(OntClass.class);
+ OntClass c13 = OWL.Nothing.inModel(m).as(OntClass.class);
+
+ c1.addSuperClass(c2);
+ c2.addSuperClass(c3);
+ c3.addSuperClass(c4);
+ c5.addSuperClass(c6);
+ c6.addSuperClass(c13);
+ c8.addSuperClass(c11);
+ c9.addSuperClass(c10);
+ c10.addSuperClass(c5);
+ c10.addSuperClass(c7);
+ c11.addSuperClass(c12);
+
+ List<OntClass.Named> actual =
OntModels.namedHierarchyRoots(m).toList();
+ Set<Resource> expected = Set.of(c12, c8);
+
+ Assertions.assertEquals(2, actual.size());
+ Assertions.assertEquals(expected, new HashSet<>(actual));
+ }
+}