From NeOn Wiki
Contents |
New Event Handling: DatamodelListener
The three old event listeners of the OntoBroker/Kaon2 API OntologyListener, OntologyManagerListener and FLogicOntologyListener have been replaced by a single event handling mechanism. The new event handling adds a filtering to restrict the events which are received. Additionally the originator client session is included in the event object (only available for Collaboration server clients.
Overview
The DatamodelListener interface is quite simple:
public interface DatamodelListener { void handleEvent(DatamodelEvent event); }
All events must implement the interface DatamodelEvent
public interface DatamodelEvent { EventType getEventType(); ClientSession getOriginSession(); long getLongTransactionID(); }
Depending on the EventType a sub interface with more information may be available.
The EventType is a predefined enum and currently contains following types:
public static enum EventType { OM_ONTOLOGY_CREATED, OM_ONTOLOGY_OPENED, OM_ONTOLOGY_CLOSED, OM_ONTOLOGY_DELETED, OM_ONTOLOGY_RENAMED, EVENT_OF_IMPORTED_ONTOLOGY, IMPORT_UPDATED, TERM_REPLACED, NAMESPACE_PREFIX_CHANGED, AXIOMS_UPDATED, BULK_AXIOMS_UPDATED, ANNOTATION_UPDATED, ALL_AXIOMS_REMOVED, DRASTICALLY_CHANGED, LONG_TRANSACTION_STARTED, LONG_TRANSACTION_COMMITTED, LONG_TRANSACTION_ROLLBACK }
A DatamodelListener is always registered at the OntologyManager. There are three methods to manage the DatamodelListeners:
public interface OntologyManager { ... void addDatamodelListener(DatamodelListener datamodelListener, DatamodelEventFilter filter); void removeDatamodelListener(DatamodelListener datamodelListener); void updateDatamodelListenerFilter(DatamodelListener datamodelListener, DatamodelEventFilter newFilter); ... }
Using the DatamodelEventFilter, the events sent to the listener can be restricted in three ways
- by the ontology ID
- by the EventType
- if events of imported ontologies should be sent
Examples
Only receive managing events (no content changes) about ontologies
OntologyManager ontologyManager = ...; DatamodelListener listener = new MyDatamodelListener (...); ontologyManager.addDatamodelListener(listener, DatamodelEventFilter.ONTOLOGY_MANAGER_ONLY);
Only receive TERM_REPLACED events for an ontology.
OntologyManager ontologyManager = ...; Ontology ontology = ...; DatamodelListener listener = new MyDatamodelListener (...); Collection<Integer> ontologyIDs = Collections.singleton(ontology.getOntologyID()); Collection<EventType> eventTypes = Collections.singleton(EventType.TERM_REPLACED); DatamodelFilter filter = new DatamodelFilter(ontologyIDs, eventTypes, false); ontologyManager.addDatamodelListener(listener, filter);
Receive all events for all ontologies
OntologyManager ontologyManager = ...; DatamodelListener listener = new MyDatamodelListener (...); ontologyManager.addDatamodelListener(listener, null); // null filter means the same as following line: // ontologyManager.addDatamodelListener(listener, DatamodelEventFilter.ALL);
Interfaces for EventTypes
For every EventType, the events must the following interfaces. All interfaces are extending the DatamodelEvent interface.
EventTypes | Interface |
---|---|
OM_ONTOLOGY_CREATED, OM_ONTOLOGY_OPENED, OM_ONTOLOGY_CLOSED, OM_ONTOLOGY_DELETED | OntologyManagerEvent |
OM_ONTOLOGY_RENAMED | OntologyRenamedEvent |
EVENT_OF_IMPORTED_ONTOLOGY | EventOfImportedOntology |
IMPORT_UPDATE | ImportUpdatedEvent |
TERM_REPLACED | TermReplacedEvent |
NAMESPACE_PREFIX_CHANGED | NamespacePrefixChangedEvent |
AXIOMS_UPDATED | AxiomsUpdatedEvent |
BULK_AXIOMS_UPDATED | BulkAxiomsUpdatedEvent |
ANNOTATION_UPDATED | AnnotationUpdatedEvent |
ALL_AXIOMS_REMOVED, DRASTICALLY_CHANGED | OntologyEvent |
LONG_TRANSACTION_STARTED, LONG_TRANSACTION_COMMITTED, LONG_TRANSACTION_ROLLBACK | LongTransactionEvent |
Example of a DatamodelListener implementation
This example shows how to process AXIOM_UPDATED and OM_ONTOLOGY_CLOSED events.
class ExampleDatamodelListener implements DatamodelListener { public void handleEvent(DatamodelEvent event) { // to keep switch readable we call submethods for the concrete processing switch (event.getEventType()) { case OM_ONTOLOGY_CLOSED: handleClosed((OntologyManagerEvent) event); break; case AXIOMS_UPDATED: handleAxiomUpdated((AxiomsUpdatedEvent) event); break; default: // ignore all other events break; } } private void handleClosed(OntologyManagerEvent event) { // get ontologyURI of closed ontology String ontologyURI = event.getOntologyURI(); ... // do something } private void handleAxiomUpdated(AxiomsUpdatedEvent event) { Ontology ontology = event.getOntology(); List<OntologyChangeEvent> changes = event.getChanges(); ... // do something } }
Changes in Query Interface
The method Query.getNumberOfTuples() has been removed. The new methods getNumberOfConsumedTuples(), skip(int count) and skipAll() have been introduced.
To retrieve the number of result tuples use the following code
Query query = reasoner.openQuery(...); try { query.skipAll(); int count = query.getNumberOfConsumedTuples(); } finally { query.close(); }
Simplified API for Query
There are two minor, but performance relevant changes in the Query and Reasoner interfaces.
Query.dispose()
is now automatically performed during Query.close()
, an explicit call for disposing the Query
object can thereby be avoided.
For the rare cases where the Query
object is going to be reused and must not be disposed, call Query.close(false)
instead.
Additionally there are new openQuery(...)
methods in the Reasoner
interface.
With the above described simplifications, running a query via the API needs two API calls less than before. This is especially important when using the API remotely via the Collaboration server. In addition the code is shorter.
Example:
Query query = reasoner.openQuery(namespaces, "FORALL X <- ..."); try { while (!query.afterLast()) { query.next(); } } finally { query.close(); }
Compare this with the old style:
Query query = reasoner.createQuery(namespaces, "FORALL X <- ..."); try { query.open(); try { while (!query.afterLast()) { query.next(); } } finally { query.close(); } } finally { query.dispose(); }
New query option ignoreImports
The new query option "ignoreImports" allows to run a query without the import rules, which map facts and rules into the importing ontology.
Example Ontology m1:
:- module = m1. A[name=>string].
Second Ontology:
:- module = "http://schema.ontoprise.com/"#DefaultModule.. :- import m1. B::A.
The query
FORALL P,R <- B[P=>R].
returns one result (P=name, R=string).
But the query
FORALL P,R <- B[P=>R]. ignoreImports
returns no result.
Search for license key file changed
The order for searching for the license key file has changed. Additionally multiple license key files are tried as long as a valid key file has been found or all possible directories have been searched.
New search order
- Java System Property "com.ontoprise.license.dir"
- Working directory (Java System Property "user.dir")
- Java System Property "ontobroker.home"
- Enviroment variable "ONTOBROKER_HOME"
- Enviroment variable "ONTOPRISE_LICENSE_HOME"
getFunctionSymbol moved to Term interface
The method getFunctionSymbol()
has been moved from the FunctionalTerm
to its super interface Term
.
Existing code needs no update.
This change simplifies the access of the function symbol as no cast to FunctionalTerm
is needed anymore.
If getFunctionSymbol()
is called for constants, the value is returned. For variables null is returned.
Example:
Here is a short example how to the simplified dealing with function terms works:
Term term = ...; if (term.getArity() > 0) { // it's a function Object symbol = term.getFunctionSymbol(); Term[] args = term.getArguments(); ... } else if (term.isGround()) { // it's a constant: (arity == 0 and ground) // alternative check: if (term instanceof Constant) ... }