Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Registering ModelChangedListener on OntModel when using Reasoner results in no statement changed events #2868

Open
cdorn opened this issue Nov 25, 2024 · 7 comments · May be fixed by #2893
Open
Labels
bug OntAPI Ontology API

Comments

@cdorn
Copy link

cdorn commented Nov 25, 2024

Version

5.1.0

What happened?

Given OntModel m with inference model:
var m = OntModelFactory.createModel( OntSpecification.OWL2_DL_MEM_RDFS_INF );

Given we register some model changed listener:
m.register(listener);

and we create a type
var type = m.createOntClass(SOMEURI);

and we delete that type:
type.deleteProperties();

then listener is not called with any deleted statements.

I also identified the cause:
inside ModelCom.register(ModelChangedListener listener) //line 1359
the getGraph() call returns the inference graph and not the underlying UnionGraph, hence any fine granular changes in the union graph and below have no listener registered

my current work around is pasted below in "Relevant output and stacktrace"
not sure if that workaround would work for other OntModel implementations and inference models.

Relevant output and stacktrace

my current workaround is:
private void register(OntModel model, ModelChangedListener listener) {
  var given = model.getGraph();
	if (given instanceof InfGraph infG) {
            Graph raw = infG.getRawGraph();
            if (raw instanceof UnionGraph ugraph) {
            	ugraph.getEventManager().register(((ModelCom)model).adapt(listener));
            }            
        }
        if (given instanceof UnionGraph ugraph) {
        	ugraph.getEventManager().register(((ModelCom)model).adapt(listener));
        }
	}

Are you interested in making a pull request?

Maybe

@cdorn cdorn added the bug label Nov 25, 2024
@afs afs added the OntAPI Ontology API label Nov 25, 2024
@sszuev
Copy link
Contributor

sszuev commented Nov 25, 2024

Feel free to create a PR or let me know if you wouldn't and I'll create it.

@cdorn
Copy link
Author

cdorn commented Nov 26, 2024

let me test and use that workaround a bit more, as I'm not sure whether in the InfGraph case, the listener should also be added the the outer InfGraph as well (and not just the UnionGraph below).

@cdorn
Copy link
Author

cdorn commented Dec 10, 2024

@sszuev sorry for the delay in getting back on this issue. I realized that the workaround only works for me as a client using the OntModel as the registration call is handled by the ModelCom class in org.apache.jena.rdf.model package, with no knowledge of the UnionGraph and InfGraph , which are in the ONTAPI.
Hence, to automatically pass a listener to all "interior" graphs, this would require quite a bit more of a change on how the ModelCom does the registration, as it would not longer be sufficient to obtain the EventManager from the graphs, but the graphs themselves would need to be aware (or the EventManager) that listeners in the interior graphs also need to be set. To this end, I dont feel I'm sufficiently aware of any sideeffects or other implications such a redesign would entail (especially keeping backwards compatibility).

@sszuev
Copy link
Contributor

sszuev commented Dec 11, 2024

@cdorn
Could you please provide a complete minimal example? I couldn't find the #deleteProperties() method. Maybe this is some kind of extension external method?

There are number of ways to delete triple\statement from a graph\model. The Model#remove() method triggers corresponding event.

    public static void main(String[] args) {
        var listener = new MCL();
        var m = OntModelFactory.createModel(OntSpecification.OWL2_DL_MEM_RDFS_INF);
        m.register(listener);
        var type = m.createOntClass("http://x");
        m.remove(type.getMainStatement());
        Assertions.assertEquals(1, listener.added.size());
        Assertions.assertEquals(1, listener.removed.size());
    }

    static class MCL extends ObjectListener {
        private final List<Object> added = new ArrayList<>();
        private final List<Object> removed = new ArrayList<>();
        @Override
        public void added(Object x) {
            System.out.println("added: " + x);
            added.add(x);
        }
        @Override
        public void removed(Object x) {
            System.out.println("removed: " + x);
            removed.add(x);
        }
    }

@cdorn
Copy link
Author

cdorn commented Dec 11, 2024

dear @sszuev sorry for the typo, its was not #deleteProperties() but #removeProperties() , below a full example:
`package at.jku.isse.passiveprocessengine.rdf.trialcode;

import java.util.ArrayList;
import java.util.List;

import org.apache.jena.graph.Graph;
import org.apache.jena.ontapi.OntModelFactory;
import org.apache.jena.ontapi.OntSpecification;
import org.apache.jena.ontapi.UnionGraph;
import org.apache.jena.rdf.listeners.StatementListener;
import org.apache.jena.rdf.model.Statement;
import org.apache.jena.rdf.model.impl.ModelCom;
import org.apache.jena.reasoner.InfGraph;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

public class GraphListenerTest {

@Test
void testListenToDeleteEventsWithIncompleteRegistration() {
	var listener = new LoggingListener();
    var m = OntModelFactory.createModel(OntSpecification.OWL2_DL_MEM_RDFS_INF);
    m.register(listener);
    var type = m.createOntClass("http://x");
    type.removeProperties();
    Assertions.assertEquals(1, listener.added.size());
 // here I dont receive the removed statement
    Assertions.assertEquals(1, listener.removed.size());
}

@Test
void testListenToDeleteEventsWithCorrectRegistration() {
	var listener = new LoggingListener();
    var m = OntModelFactory.createModel(OntSpecification.OWL2_DL_MEM_RDFS_INF);
    m.register(listener);
    if (m.getGraph() instanceof InfGraph infG) {
    	Graph raw = infG.getRawGraph();
        if (raw instanceof UnionGraph ugraph) {
        	ugraph.getEventManager().register(((ModelCom)m).adapt(listener));
        }   
    }
    var type = m.createOntClass("http://x");
    type.removeProperties();
    // here I receive the same event twice, due to the two listener registrations
    Assertions.assertEquals(2, listener.added.size()); 
    Assertions.assertEquals(1, listener.removed.size());
}

public static class LoggingListener extends StatementListener {

	private final List<Statement> added = new ArrayList<>();
    private final List<Statement> removed = new ArrayList<>();
	
	@Override
	public void addedStatement(Statement s) {
		System.out.println("ADDED "+s.toString());
		added.add(s);
	}

	@Override
	public void removedStatement(Statement s) {
		System.out.println("REMOVED "+s.toString());
		removed.add(s);
	}
}

}
`

the same behavior occurs if I replace type.removeProperties() with type.removeAll(RDF.type)

@cdorn
Copy link
Author

cdorn commented Dec 11, 2024

perhaps to elaborate on what I like to achieve: for me the information that some properties from that resource are removed is insufficient, I need to know the exact statements, hence I'm using the StatementListener.

@sszuev
Copy link
Contributor

sszuev commented Dec 11, 2024

This issue also exists in the Legacy Ont API.

The simplest solution (and probably the most suitable one) is to use only UnionGraph for listener's registration (even there is an InfGraph). I.e.:

    @Override
    public OntGraphModelImpl register(ModelChangedListener listener) {
        getUnionGraph().getEventManager().register(adapt(listener));
        return this;
    }

sszuev added a commit that referenced this issue Dec 12, 2024
…unctionality: use only UnionGraph (not InfGraph) to hold graph-listeners
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug OntAPI Ontology API
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants