Skip to content

Commit bfba5a5

Browse files
committed
ont-api: implement NamedIndividualSearcher (graph-optimization, issue #15)
1 parent ee3d432 commit bfba5a5

File tree

6 files changed

+322
-90
lines changed

6 files changed

+322
-90
lines changed

src/main/java/com/github/owlcs/ontapi/internal/AxiomTranslator.java

+4-18
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* This file is part of the ONT API.
33
* The contents of this file are subject to the LGPL License, Version 3.0.
4-
* Copyright (c) 2020, The University of Manchester, owl.cs group.
4+
* Copyright (c) 2020, owl.cs group.
55
*
66
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
77
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
@@ -16,18 +16,17 @@
1616

1717
import com.github.owlcs.ontapi.DataFactory;
1818
import com.github.owlcs.ontapi.config.AxiomsSettings;
19-
import com.github.owlcs.ontapi.jena.impl.PersonalityModel;
20-
import com.github.owlcs.ontapi.jena.model.OntClass;
2119
import com.github.owlcs.ontapi.jena.model.OntModel;
2220
import com.github.owlcs.ontapi.jena.model.OntStatement;
2321
import com.github.owlcs.ontapi.jena.utils.Iter;
24-
import org.apache.jena.graph.Node;
2522
import org.apache.jena.shared.JenaException;
2623
import org.apache.jena.util.iterator.ExtendedIterator;
2724
import org.semanticweb.owlapi.model.AxiomType;
2825
import org.semanticweb.owlapi.model.OWLAxiom;
2926

30-
import java.util.*;
27+
import java.util.List;
28+
import java.util.Objects;
29+
import java.util.Optional;
3130
import java.util.function.Supplier;
3231
import java.util.stream.Stream;
3332

@@ -71,19 +70,6 @@ public static ONTObjectFactory getObjectFactory(OntModel model) {
7170
((HasObjectFactory) model).getObjectFactory() : ONTObjectFactory.DEFAULT;
7271
}
7372

74-
/**
75-
* Gets all uri-{@link Node}s that are reserved for a model and cannot represent a {@link OntClass.Named}.
76-
*
77-
* @param model {@link OntModel}, not {@code null}
78-
* @return a {@code Set} of {@link Node}s
79-
*/
80-
protected static Set<Node> getSystemResources(OntModel model) {
81-
if (model instanceof PersonalityModel) {
82-
return ((PersonalityModel) model).getSystemResources(OntClass.Named.class);
83-
}
84-
return Collections.emptySet();
85-
}
86-
8773
/**
8874
* Reads all model's axioms in the form of stream.
8975
*

src/main/java/com/github/owlcs/ontapi/internal/BaseSearcher.java

+24-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* This file is part of the ONT API.
33
* The contents of this file are subject to the LGPL License, Version 3.0.
4-
* Copyright (c) 2020, The University of Manchester, owl.cs group.
4+
* Copyright (c) 2020, owl.cs group.
55
*
66
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
77
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
@@ -16,10 +16,13 @@
1616

1717
import com.github.owlcs.ontapi.DataFactory;
1818
import com.github.owlcs.ontapi.config.AxiomsSettings;
19+
import com.github.owlcs.ontapi.jena.impl.PersonalityModel;
20+
import com.github.owlcs.ontapi.jena.model.OntClass;
1921
import com.github.owlcs.ontapi.jena.model.OntModel;
2022
import com.github.owlcs.ontapi.jena.model.OntStatement;
2123
import com.github.owlcs.ontapi.jena.utils.Iter;
2224
import com.github.owlcs.ontapi.jena.utils.OntModels;
25+
import org.apache.jena.graph.Node;
2326
import org.apache.jena.rdf.model.Property;
2427
import org.apache.jena.rdf.model.RDFNode;
2528
import org.apache.jena.rdf.model.Resource;
@@ -28,8 +31,10 @@
2831
import org.semanticweb.owlapi.model.OWLAxiom;
2932
import org.semanticweb.owlapi.model.OWLObject;
3033

34+
import java.util.Collections;
3135
import java.util.List;
3236
import java.util.Set;
37+
import java.util.stream.Stream;
3338

3439
/**
3540
* A base abstraction for {@link AxiomTranslator}s and searchers.
@@ -119,10 +124,11 @@ protected static <T extends AxiomTranslator<? extends A>, A extends OWLAxiom> T
119124
}
120125

121126
protected static Set<AxiomTranslator<OWLAxiom>> selectTranslators(OWLComponentType type) {
122-
return OWLTopObjectType.axioms().filter(x -> type == null || x.hasComponent(type))
123-
.map(OWLTopObjectType::getAxiomType)
124-
.map(AxiomParserProvider::get)
125-
.collect(Iter.toUnmodifiableSet());
127+
return selectTranslators(OWLTopObjectType.axioms().filter(x -> type == null || x.hasComponent(type)));
128+
}
129+
130+
private static Set<AxiomTranslator<OWLAxiom>> selectTranslators(Stream<OWLTopObjectType> types) {
131+
return types.map(OWLTopObjectType::getAxiomType).map(AxiomParserProvider::get).collect(Iter.toUnmodifiableSet());
126132
}
127133

128134
@SuppressWarnings("unchecked")
@@ -135,6 +141,19 @@ static <X extends OWLObject> ObjectsSearcher<X> cast(ObjectsSearcher<?> searcher
135141
return (ObjectsSearcher<X>) searcher;
136142
}
137143

144+
/**
145+
* Gets all uri-{@link Node}s that are reserved for a model and cannot represent a {@link OntClass.Named}.
146+
*
147+
* @param model {@link OntModel}, not {@code null}
148+
* @return a {@code Set} of {@link Node}s
149+
*/
150+
protected static Set<Node> getSystemResources(OntModel model) {
151+
if (model instanceof PersonalityModel) {
152+
return ((PersonalityModel) model).getSystemResources(OntClass.Named.class);
153+
}
154+
return Collections.emptySet();
155+
}
156+
138157
protected final ExtendedIterator<OntStatement> listBySubject(OntModel model, Resource subject) {
139158
return listStatements(model, subject, null, null);
140159
}

src/main/java/com/github/owlcs/ontapi/internal/InternalReadModel.java

+19-8
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import com.github.owlcs.ontapi.internal.axioms.AbstractNaryTranslator;
2121
import com.github.owlcs.ontapi.internal.searchers.axioms.*;
2222
import com.github.owlcs.ontapi.internal.searchers.objects.ClassSearcher;
23+
import com.github.owlcs.ontapi.internal.searchers.objects.NamedIndividualSearcher;
2324
import com.github.owlcs.ontapi.jena.OntJenaException;
2425
import com.github.owlcs.ontapi.jena.RWLockedGraph;
2526
import com.github.owlcs.ontapi.jena.impl.OntGraphModelImpl;
@@ -146,6 +147,7 @@ abstract class InternalReadModel extends OntGraphModelImpl implements ListAxioms
146147

147148
// To search OWLObjects
148149
protected final ObjectsSearcher<OWLClass> classSearcher = new ClassSearcher();
150+
protected final ObjectsSearcher<OWLNamedIndividual> individualSearcher = new NamedIndividualSearcher();
149151

150152
InternalReadModel(Graph base,
151153
OntPersonality personality,
@@ -854,10 +856,8 @@ protected ObjectMap<OWLObject> createComponentObjectMap(OWLComponentType type) {
854856
InternalConfig conf = getConfig();
855857
Supplier<Iterator<ONTObject<OWLObject>>> loader = () -> InternalReadModel.this.listOWLObjects(type, conf);
856858
if (!conf.useComponentCache()) {
857-
ObjectsSearcher<OWLObject> searcher;
858-
if (OWLComponentType.CLASS == type) {
859-
searcher = BaseSearcher.cast(classSearcher);
860-
} else { // TODO: other types
859+
ObjectsSearcher<OWLObject> searcher = getEntitySearcher(type);
860+
if (searcher == null) {
861861
return new DirectObjectMapImpl<>(loader);
862862
}
863863
return new DirectObjectMapImpl<>(loader, toFinder(searcher), toTester(searcher));
@@ -874,17 +874,28 @@ protected ObjectMap<OWLObject> createComponentObjectMap(OWLComponentType type) {
874874
* @param conf {@link InternalConfig}
875875
* @return an {@code Iterator} of {@link ONTObject} with the given type
876876
*/
877-
@SuppressWarnings({"unchecked", "rawtypes"})
878877
protected Iterator<ONTObject<OWLObject>> listOWLObjects(OWLComponentType type, InternalConfig conf) {
879878
ModelObjectFactory factory = getObjectFactory();
880879
OntModel model = getSearchModel();
881-
if (OWLComponentType.CLASS == type && useObjectsSearchOptimization(conf)) {
882-
return ((Iterator) classSearcher.listONTObjects(model, factory, conf));
880+
ObjectsSearcher<OWLObject> searcher = getEntitySearcher(type);
881+
if (searcher != null && useObjectsSearchOptimization(conf)) {
882+
return searcher.listONTObjects(model, factory, conf);
883883
}
884-
// if content cache is loaded its parsing is faster than graph-optimization
884+
// if content cache is loaded then its parsing is faster than graph-optimization (at least for classes)
885885
return selectContentObjects(type).flatMap(x -> type.select(x, model, factory)).iterator();
886886
}
887887

888+
private ObjectsSearcher<OWLObject> getEntitySearcher(OWLComponentType type) {
889+
if (OWLComponentType.CLASS == type) {
890+
return BaseSearcher.cast(classSearcher);
891+
}
892+
if (OWLComponentType.NAMED_INDIVIDUAL == type) {
893+
return BaseSearcher.cast(individualSearcher);
894+
}
895+
// TODO: support other types (see https://github.com/owlcs/ont-api/issues/15)
896+
return null;
897+
}
898+
888899
/**
889900
* Answers {@code true} when need to use {@link ObjectsSearcher} optimization.
890901
*
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* This file is part of the ONT API.
33
* The contents of this file are subject to the LGPL License, Version 3.0.
4-
* Copyright (c) 2020, The University of Manchester, owl.cs group.
4+
* Copyright (c) 2020, owl.cs group.
55
*
66
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
77
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
@@ -17,10 +17,7 @@
1717
import com.github.owlcs.ontapi.OntApiException;
1818
import com.github.owlcs.ontapi.config.AxiomsSettings;
1919
import com.github.owlcs.ontapi.internal.*;
20-
import com.github.owlcs.ontapi.internal.searchers.WithRootStatement;
2120
import com.github.owlcs.ontapi.internal.searchers.axioms.ByClass;
22-
import com.github.owlcs.ontapi.jena.impl.PersonalityModel;
23-
import com.github.owlcs.ontapi.jena.impl.conf.OntPersonality;
2421
import com.github.owlcs.ontapi.jena.model.OntModel;
2522
import com.github.owlcs.ontapi.jena.model.OntStatement;
2623
import com.github.owlcs.ontapi.jena.utils.Iter;
@@ -35,81 +32,60 @@
3532
import org.semanticweb.owlapi.model.OWLClass;
3633

3734
import java.util.HashSet;
38-
import java.util.Optional;
3935
import java.util.Set;
40-
import java.util.function.Function;
4136

4237
/**
38+
* An {@link ObjectsSearcher} that retrieves {@link OWLClass OWL-API Class}es.
4339
* Created by @ssz on 19.04.2020.
4440
*/
45-
public class ClassSearcher extends WithRootStatement implements ObjectsSearcher<OWLClass> {
46-
41+
public class ClassSearcher extends EntitySearcher<OWLClass> {
4742
private static final Set<AxiomTranslator<OWLAxiom>> TRANSLATORS = selectTranslators(OWLComponentType.CLASS);
4843

49-
protected static OntPersonality.Builtins getBuiltins(OntModel m) {
50-
return PersonalityModel.asPersonalityModel(m).getOntPersonality().getBuiltins();
51-
}
52-
53-
private static Function<String, ONTObject<OWLClass>> factoryMapping(OntModel model, ONTObjectFactory factory) {
54-
if (factory instanceof ModelObjectFactory) {
55-
return ((ModelObjectFactory) factory)::getClass;
56-
}
57-
return uri -> factory.getClass(OntApiException.mustNotBeNull(model.getOntClass(uri)));
58-
}
59-
6044
@Override
61-
public ExtendedIterator<ONTObject<OWLClass>> listONTObjects(OntModel model,
62-
ONTObjectFactory factory,
63-
AxiomsSettings config) {
64-
return listClasses(model, config).mapWith(factoryMapping(model, factory));
45+
protected ONTObject<OWLClass> createEntity(String uri, OntModel model, ONTObjectFactory factory) {
46+
return factory.getClass(OntApiException.mustNotBeNull(model.getOntClass(uri)));
6547
}
6648

6749
@Override
68-
public boolean containsONTObject(OWLClass object, OntModel model, ONTObjectFactory factory, AxiomsSettings config) {
69-
return containsClass(object.getIRI().getIRIString(), model, config);
50+
protected ONTObject<OWLClass> createEntity(String uri, ModelObjectFactory factory) {
51+
return factory.getClass(uri);
7052
}
7153

7254
@Override
73-
public Optional<ONTObject<OWLClass>> findONTObject(OWLClass object,
74-
OntModel model,
75-
ONTObjectFactory factory,
76-
AxiomsSettings config) {
77-
String uri = object.getIRI().getIRIString();
78-
if (containsClass(uri, model, config)) {
79-
return Optional.of(InternalObjectFactory.getONTClass(uri, model, factory));
80-
}
81-
return Optional.empty();
55+
protected ExtendedIterator<? extends AxiomTranslator<OWLAxiom>> listTranslators() {
56+
return Iter.create(TRANSLATORS);
8257
}
8358

84-
protected boolean containsClass(String uri, OntModel m, AxiomsSettings conf) {
59+
@Override
60+
protected boolean containsEntity(String uri, OntModel m, AxiomsSettings conf) {
8561
Resource clazz = m.getResource(uri);
8662
if (getBuiltins(m).getClasses().contains(clazz.asNode())) {
8763
if (OWL.Thing.equals(clazz)) {
88-
if (containAxiom(Iter.flatMap(listImplicitStatements(m), s -> listRootStatements(m, s)), conf)) {
64+
if (containsAxiom(Iter.flatMap(listImplicitStatements(m), s -> listRootStatements(m, s)), conf)) {
8965
return true;
9066
}
9167
}
92-
return containAxiom(listStatements(m, clazz), conf);
68+
return containsInAxiom(clazz, m, conf);
9369
}
9470
if (m.independent()) {
9571
return m.getBaseGraph().contains(clazz.asNode(), RDF.type.asNode(), OWL.Class.asNode());
9672
}
9773
if (!m.contains(clazz, RDF.type, OWL.Class)) {
9874
return false;
9975
}
100-
return containAxiom(listStatements(m, clazz), conf);
76+
return containsInAxiom(clazz, m, conf);
10177
}
10278

103-
protected ExtendedIterator<String> listClasses(OntModel m, AxiomsSettings conf) {
79+
@Override
80+
protected ExtendedIterator<String> listEntities(OntModel m, AxiomsSettings conf) {
10481
Set<String> builtins = new HashSet<>();
105-
getBuiltins(m).getClasses()
106-
.forEach(x -> {
107-
if (containAxiom(listStatements(m, m.getResource(x.getURI())), conf)) {
108-
builtins.add(x.getURI());
109-
}
110-
});
82+
getBuiltins(m).getClasses().forEach(x -> {
83+
if (containsInAxiom(x.getURI(), m, conf)) {
84+
builtins.add(x.getURI());
85+
}
86+
});
11187
if (!builtins.contains(OWL.Thing.getURI())) {
112-
if (containAxiom(Iter.flatMap(listImplicitStatements(m), s -> listRootStatements(m, s)), conf)) {
88+
if (containsAxiom(Iter.flatMap(listImplicitStatements(m), s -> listRootStatements(m, s)), conf)) {
11389
builtins.add(OWL.Thing.getURI());
11490
}
11591
}
@@ -119,16 +95,12 @@ protected ExtendedIterator<String> listClasses(OntModel m, AxiomsSettings conf)
11995
ExtendedIterator<String> res = Iter.concat(explicit, Iter.create(builtins));
12096
if (!m.independent()) {
12197
ExtendedIterator<String> shared = listClassesFromImports(m)
122-
.filterKeep(x -> containAxiom(listStatements(m, m.getResource(x)), conf));
98+
.filterKeep(x -> containsInAxiom(x, m, conf));
12399
res = Iter.concat(res, shared);
124100
}
125101
return res;
126102
}
127103

128-
protected ExtendedIterator<OntStatement> listStatements(OntModel m, Resource clazz) {
129-
return Iter.concat(listBySubject(m, clazz), Iter.flatMap(listByObject(m, clazz), s -> listRootStatements(m, s)));
130-
}
131-
132104
protected ExtendedIterator<OntStatement> listImplicitStatements(OntModel m) {
133105
return Iter.flatMap(Iter.of(OWL.cardinality, OWL.maxCardinality, OWL.minCardinality), p -> listByPredicate(m, p))
134106
.filterKeep(this::isCardinalityRestriction);
@@ -144,12 +116,4 @@ protected boolean isCardinalityRestriction(OntStatement s) {
144116
return ByClass.OBJECT_CARDINALITY_TYPES.stream().anyMatch(t -> s.getSubject().canAs(t));
145117
}
146118

147-
protected boolean containAxiom(ExtendedIterator<OntStatement> top, AxiomsSettings conf) {
148-
return Iter.anyMatch(top, s -> Iter.findFirst(listTranslators(s, conf)).isPresent());
149-
}
150-
151-
protected ExtendedIterator<? extends AxiomTranslator<OWLAxiom>> listTranslators(OntStatement statement,
152-
AxiomsSettings conf) {
153-
return Iter.create(TRANSLATORS).filterKeep(t -> t.testStatement(statement, conf));
154-
}
155119
}

0 commit comments

Comments
 (0)