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 d165bc5284 GH-2868: [ontapi] override register\unregister
ModelChangedListener functionality: use only UnionGraph (not InfGraph) to hold
graph-listeners
d165bc5284 is described below
commit d165bc5284d5a1b95476dbe1b8cd05841b7c9caa
Author: sszuev <[email protected]>
AuthorDate: Thu Dec 12 23:24:51 2024 +0300
GH-2868: [ontapi] override register\unregister ModelChangedListener
functionality: use only UnionGraph (not InfGraph) to hold graph-listeners
---
.../apache/jena/ontapi/impl/OntGraphModelImpl.java | 20 ++++
.../apache/jena/ontapi/impl/UnionGraphImpl.java | 9 +-
.../ontapi/impl/objects/OntSimpleClassImpl.java | 11 ++-
.../org/apache/jena/ontapi/model/MutableModel.java | 33 +++++++
.../org/apache/jena/ontapi/OntModelMiscTest.java | 102 +++++++++++++++++++++
5 files changed, 166 insertions(+), 9 deletions(-)
diff --git
a/jena-ontapi/src/main/java/org/apache/jena/ontapi/impl/OntGraphModelImpl.java
b/jena-ontapi/src/main/java/org/apache/jena/ontapi/impl/OntGraphModelImpl.java
index ad7bae3c94..c6747bfe92 100644
---
a/jena-ontapi/src/main/java/org/apache/jena/ontapi/impl/OntGraphModelImpl.java
+++
b/jena-ontapi/src/main/java/org/apache/jena/ontapi/impl/OntGraphModelImpl.java
@@ -68,6 +68,7 @@ import org.apache.jena.ontapi.utils.StdModels;
import org.apache.jena.rdf.model.InfModel;
import org.apache.jena.rdf.model.Literal;
import org.apache.jena.rdf.model.Model;
+import org.apache.jena.rdf.model.ModelChangedListener;
import org.apache.jena.rdf.model.Property;
import org.apache.jena.rdf.model.RDFList;
import org.apache.jena.rdf.model.RDFNode;
@@ -355,6 +356,25 @@ public class OntGraphModelImpl extends ModelCom implements
OntModel, OntEnhGraph
return new ModelCom(getBaseGraph());
}
+ @Override
+ public OntGraphModelImpl register(ModelChangedListener listener) {
+ getUnionGraph().getEventManager().register(adapt(listener));
+ return this;
+ }
+
+ @Override
+ public OntGraphModelImpl unregister(ModelChangedListener listener) {
+ getUnionGraph().getEventManager().unregister(adapt(listener));
+ return this;
+ }
+
+ @Override
+ public OntGraphModelImpl notifyEvent(Object event) {
+ var ug = getUnionGraph();
+ ug.getEventManager().notifyEvent(ug, event);
+ return this;
+ }
+
@Override
public OntID getID() {
checkType(OntID.class);
diff --git
a/jena-ontapi/src/main/java/org/apache/jena/ontapi/impl/UnionGraphImpl.java
b/jena-ontapi/src/main/java/org/apache/jena/ontapi/impl/UnionGraphImpl.java
index 6565221138..f73d964347 100644
--- a/jena-ontapi/src/main/java/org/apache/jena/ontapi/impl/UnionGraphImpl.java
+++ b/jena-ontapi/src/main/java/org/apache/jena/ontapi/impl/UnionGraphImpl.java
@@ -18,17 +18,18 @@
package org.apache.jena.ontapi.impl;
-import org.apache.jena.ontapi.UnionGraph;
-import org.apache.jena.ontapi.utils.Graphs;
-import org.apache.jena.ontapi.utils.Iterators;
import org.apache.jena.graph.Graph;
import org.apache.jena.graph.GraphEventManager;
import org.apache.jena.graph.GraphEvents;
import org.apache.jena.graph.GraphListener;
+import org.apache.jena.graph.GraphUtil;
import org.apache.jena.graph.Node;
import org.apache.jena.graph.Triple;
import org.apache.jena.graph.compose.CompositionBase;
import org.apache.jena.graph.impl.SimpleEventManager;
+import org.apache.jena.ontapi.UnionGraph;
+import org.apache.jena.ontapi.utils.Graphs;
+import org.apache.jena.ontapi.utils.Iterators;
import org.apache.jena.shared.PrefixMapping;
import org.apache.jena.util.iterator.ExtendedIterator;
@@ -223,7 +224,7 @@ public class UnionGraphImpl extends CompositionBase
implements UnionGraph {
Triple t = Triple.createMatch(s, p, o);
UnionGraph.EventManager em = getEventManager();
em.onDeleteTriple(this, t);
- super.remove(s, p, o);
+ GraphUtil.remove(this, s, p, o);
em.notifyEvent(this, GraphEvents.remove(s, p, o));
}
diff --git
a/jena-ontapi/src/main/java/org/apache/jena/ontapi/impl/objects/OntSimpleClassImpl.java
b/jena-ontapi/src/main/java/org/apache/jena/ontapi/impl/objects/OntSimpleClassImpl.java
index cef800397b..e39cc0869d 100644
---
a/jena-ontapi/src/main/java/org/apache/jena/ontapi/impl/objects/OntSimpleClassImpl.java
+++
b/jena-ontapi/src/main/java/org/apache/jena/ontapi/impl/objects/OntSimpleClassImpl.java
@@ -22,6 +22,7 @@ import org.apache.jena.enhanced.EnhGraph;
import org.apache.jena.graph.Node;
import org.apache.jena.ontapi.OntJenaException;
import org.apache.jena.ontapi.OntModelControls;
+import org.apache.jena.ontapi.common.OntPersonalities;
import org.apache.jena.ontapi.impl.OntGraphModelImpl;
import org.apache.jena.ontapi.model.OntClass;
import org.apache.jena.ontapi.model.OntDataProperty;
@@ -34,6 +35,7 @@ import org.apache.jena.ontapi.model.OntRelationalProperty;
import org.apache.jena.ontapi.model.OntStatement;
import org.apache.jena.rdf.model.Resource;
import org.apache.jena.vocabulary.OWL2;
+import org.apache.jena.vocabulary.RDFS;
import java.util.Arrays;
import java.util.Collection;
@@ -42,10 +44,9 @@ import java.util.Optional;
import java.util.stream.Stream;
/**
- * {@code owl:Class} Implementation.
- * Instance of this class as a class with unknown nature is only available in
a spec with corresponding permissions
- * ({@link OntModelControls}).
- * Specialized classes have their own implementations ({@link NamedImpl} or
{@link OntClassImpl}).
+ * Simple Ontology Class implementation.
+ * Represents RDFS OntClass or OWL OntClass with unknown nature.
+ * Specialized OWL classes have their own implementations ({@link NamedImpl}
or {@link OntClassImpl}).
*/
@SuppressWarnings("WeakerAccess")
public class OntSimpleClassImpl extends OntObjectImpl implements OntClass {
@@ -56,7 +57,7 @@ public class OntSimpleClassImpl extends OntObjectImpl
implements OntClass {
@Override
public Optional<OntStatement> findRootStatement() {
- return getOptionalRootStatement(this, OWL2.Class);
+ return getOptionalRootStatement(this,
OntPersonalities.isRDFS(getModel().getOntPersonality()) ? RDFS.Class :
OWL2.Class);
}
@Override
diff --git
a/jena-ontapi/src/main/java/org/apache/jena/ontapi/model/MutableModel.java
b/jena-ontapi/src/main/java/org/apache/jena/ontapi/model/MutableModel.java
index 996d9fb8f2..92d04d229f 100644
--- a/jena-ontapi/src/main/java/org/apache/jena/ontapi/model/MutableModel.java
+++ b/jena-ontapi/src/main/java/org/apache/jena/ontapi/model/MutableModel.java
@@ -21,6 +21,7 @@ package org.apache.jena.ontapi.model;
import org.apache.jena.datatypes.RDFDatatype;
import org.apache.jena.rdf.model.Literal;
import org.apache.jena.rdf.model.Model;
+import org.apache.jena.rdf.model.ModelChangedListener;
import org.apache.jena.rdf.model.ModelCon;
import org.apache.jena.rdf.model.Property;
import org.apache.jena.rdf.model.RDFNode;
@@ -109,4 +110,36 @@ interface MutableModel<R extends Model> extends Model {
@Override
R add(Resource s, Property p, String lex, String lang);
+
+ /**
+ * Registers a listener for model-changed events on this model.
+ * The methods on the listener will be called when API add/remove calls on
the model succeed
+ * [in whole or in part].
+ * The same listener may be registered many times;
+ * if so, its methods will be called as many times as it's registered for
each event.
+ *
+ * @param listener {@link ModelChangedListener}, not null
+ * @return this model, for cascading
+ */
+ R register(ModelChangedListener listener);
+
+ /**
+ * Unregisters a listener from model-changed events on this model.
+ * The listener is detached from the model.
+ * The model is returned to permit cascading.
+ * If the listener is not attached to the model, then nothing happens.
+ *
+ * @param listener {@link ModelChangedListener}, not null
+ */
+ R unregister(ModelChangedListener listener);
+
+ /**
+ * Notifies any listeners that the {@code event} has occurred.
+ *
+ * @param event the event, which has occurred, e.g. {@code
GraphEvents#startRead}
+ * @return this model, for cascading
+ * @see ModelChangedListener
+ * @see org.apache.jena.graph.GraphEvents
+ */
+ R notifyEvent(Object event);
}
diff --git
a/jena-ontapi/src/test/java/org/apache/jena/ontapi/OntModelMiscTest.java
b/jena-ontapi/src/test/java/org/apache/jena/ontapi/OntModelMiscTest.java
index 72cb0acf88..263a537acc 100644
--- a/jena-ontapi/src/test/java/org/apache/jena/ontapi/OntModelMiscTest.java
+++ b/jena-ontapi/src/test/java/org/apache/jena/ontapi/OntModelMiscTest.java
@@ -25,15 +25,19 @@ import org.apache.jena.ontapi.model.OntClass;
import org.apache.jena.ontapi.model.OntDisjoint;
import org.apache.jena.ontapi.model.OntModel;
import org.apache.jena.ontapi.utils.OntModels;
+import org.apache.jena.rdf.listeners.StatementListener;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory;
import org.apache.jena.rdf.model.Resource;
+import org.apache.jena.rdf.model.Statement;
import org.apache.jena.shared.PrefixMapping;
import org.apache.jena.vocabulary.OWL;
import org.apache.jena.vocabulary.OWL2;
import org.apache.jena.vocabulary.RDF;
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.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@@ -154,4 +158,102 @@ public class OntModelMiscTest {
Assertions.assertThrows(IllegalArgumentException.class,
ont::createDifferentIndividuals);
}
+
+ @ParameterizedTest
+ @EnumSource(names = {
+ "OWL2_DL_MEM_RDFS_BUILTIN_INF",
+ "OWL2_DL_MEM",
+ "OWL2_DL_MEM_RDFS_INF",
+ "OWL2_DL_MEM_TRANS_INF",
+ "OWL2_DL_MEM_RULES_INF",
+ "OWL2_MEM",
+ "OWL2_MEM_RDFS_INF",
+ "OWL2_MEM_TRANS_INF",
+ "OWL2_MEM_RULES_INF",
+ "OWL2_MEM_MINI_RULES_INF",
+ "OWL2_MEM_MICRO_RULES_INF",
+ "OWL2_EL_MEM",
+ "OWL2_EL_MEM_RDFS_INF",
+ "OWL2_EL_MEM_TRANS_INF",
+ "OWL2_EL_MEM_RULES_INF",
+ "OWL2_QL_MEM",
+ "OWL2_QL_MEM_RDFS_INF",
+ "OWL2_QL_MEM_TRANS_INF",
+ "OWL2_QL_MEM_RULES_INF",
+ "OWL2_RL_MEM",
+ "OWL2_RL_MEM_RDFS_INF",
+ "OWL2_RL_MEM_TRANS_INF",
+ "OWL2_RL_MEM_RULES_INF",
+ "OWL1_DL_MEM",
+ "OWL1_DL_MEM_RDFS_INF",
+ "OWL1_DL_MEM_TRANS_INF",
+ "OWL1_DL_MEM_RULES_INF",
+ "OWL1_MEM",
+ "OWL1_MEM_RDFS_INF",
+ "OWL1_MEM_TRANS_INF",
+ "OWL1_MEM_RULES_INF",
+ "OWL1_MEM_MINI_RULES_INF",
+ "OWL1_MEM_MICRO_RULES_INF",
+ "OWL1_LITE_MEM",
+ "OWL1_LITE_MEM_RDFS_INF",
+ "OWL1_LITE_MEM_TRANS_INF",
+ "OWL1_LITE_MEM_RULES_INF",
+ "RDFS_MEM",
+ "RDFS_MEM_RDFS_INF",
+ "RDFS_MEM_TRANS_INF",
+ })
+ public void testModelChangeListenerGH2868(TestSpec spec) {
+ var listener = new TestModelChangedListener();
+ var m = OntModelFactory.createModel(spec.inst).register(listener);
+
+ var type1 = m.createOntClass("http://x1");
+ type1.removeProperties();
+ Assertions.assertEquals(1, listener.addedStatements.size());
+ Assertions.assertEquals(1, listener.removedStatements.size());
+ Assertions.assertEquals(1, listener.events.size());
+
+ listener.clear();
+
+ var type2 = m.createOntClass("http://x2");
+ m.remove(type2.getMainStatement());
+ Assertions.assertEquals(1, listener.addedStatements.size());
+ Assertions.assertEquals(1, listener.removedStatements.size());
+ Assertions.assertEquals(0, listener.events.size());
+
+ listener.clear();
+
+ m.createOntClass("http://x3");
+ m.createOntClass("http://x4");
+ m.removeAll(null, RDF.type, null);
+ Assertions.assertEquals(2, listener.addedStatements.size());
+ Assertions.assertEquals(2, listener.removedStatements.size());
+ Assertions.assertEquals(1, listener.events.size());
+ }
+
+ private static class TestModelChangedListener extends StatementListener {
+ private final List<Statement> addedStatements = new ArrayList<>();
+ private final List<Statement> removedStatements = new ArrayList<>();
+ private final List<Object> events = new ArrayList<>();
+
+ @Override
+ public void addedStatement(Statement x) {
+ addedStatements.add(x);
+ }
+
+ @Override
+ public void removedStatement(Statement x) {
+ removedStatements.add(x);
+ }
+
+ @Override
+ public void notifyEvent(Model m, Object event) {
+ events.add(event);
+ }
+
+ private void clear() {
+ addedStatements.clear();
+ removedStatements.clear();
+ events.clear();
+ }
+ }
}