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

  1. Java System Property "com.ontoprise.license.dir"
  2. Working directory (Java System Property "user.dir")
  3. Java System Property "ontobroker.home"
  4. Enviroment variable "ONTOBROKER_HOME"
  5. 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)
   ...
}