Connecting the SADL IDE with Persistent Storage of OWL Models and Rules

Last revised 9/24/2021.

Introduction

The SADL IDE uses Apache Jena as the interface to in-memory OWL models created when a SADL model is processed by the Xtext model processor and as the interface to OWL model persistence. The in-memory OWL model, which exists as an instance of the Jena org.apache.jena.ontology.OntModel class, is persisted when the SADL model from which it was created is saved. There are multiple options for how this persistence is accomplished. The purpose of this document is to explain the mechanisms for both retrieving OWL models from the persistence repository and for persisting OWL models to the persistence repository. OWL models must be retrieved in various operations such as when inference is run, queries are performed, models are graphed, etc.

SADL and SadlServer use the Jena org.apache.jena.rdf.model.ModelGetter Java Interface class to retrieve OWL models from persistent storage, in the form of in-memory Jena org.apache.jena.ref.model.Model and org.apache.jena.ontology.OntModel instances. SADL extends this Interface class with the com.ge.research.sadl.model.persistence.ISadlModelGetter Interface class, which is in turn extended by the com.ge.research.sadl.model.persistence.ISadlModelGetterPutter Interface class, as shown in the figure below. The ISadlModelGetterPutter Interface defines methods for persisting OWL models, where as the ISadlModelGetter Interface only defines methods for retrieving OWL models from the persistent store.

The ISadlModelGetter is implemented by the abstract com.ge.research.sadl.model.persistence.SadlModelGetter class. This class has an extension for each basic type of persistence, e.g., file-based persistence and Jena TDB persistence, that provide the actual implementations of the methods to retrieve OWL models from the persistent store. Each of these implementations are also extended by classes that implement the com.ge.research.sadl.model.persistence.ISadlModelGetterPutter Interface and provide implementations for saving OWL models to the persistent store.

These classes work in conjunction with the com.ge.research.sadl.model.persistence.SadlPersistenceFormat class, which identifies the various persistence formats supported and provides convenience methods for validating formats, converting from the SADL identifier to those used by Jena in the case of file-based persistence, etc.

Adding a New Persistence Format to SADL

To add a new persistence format to SADL, do the following.

  1. Add the format to the SadlPersistenceFormat class.
  2. Create an getter for the new format by extending the SadlModelGetter class, as do the SadJenaFileGetter and the SadlJenaTDBGetter classes.
  3. Create a putter for the new format that extends the new format's getter class and implements the ISadlModelGetterPutter Interface class, as do the SadlJenaFileGetterPutter and the SadlJenaTDBGetterPutter classes.

Overview of Classes Involved in SADL and External OWL Model Persistence

Apache Jena includes the Java interface class org.apache.jena.rdf.model.ModelGetter to retrieve models from the persistence repository. The class documentation states, "A ModelGetter object can retrieve a Model given a URL for it. If it doesn't have such a Model, it returns null." The extensions and implementations of this class used by SADL are described above.

Jena also uses the class org.apache.jena.ontology.OntModelSpec, which "Encapsulates a description of the components of an ontology model, including the storage scheme, reasoner and language profile." This class encapsulates a field of type OntDocumentManager, in the same package, which "Provides services for managing ontology documents, including loading imported documents, and locally caching documents from resolvable URL's to improve load performance." The OntModelSpec class also includes the methods getBaseModelMaker, getImportModelMaker, and setImportModelGetter.

SADL uses an implementation of the class com.ge.research.sadl.reasoner.IConfigurationManager or one of its extensions, com.ge.research.sadl.reasoner.IConfigurationManagerForEditing or com.ge.research.sadl.builder.IConfigurationManagerForIDE, to manage the SADL configuration, including the relevant OntModelSpec and OntDocumentManager instances. When the SADL IDE processes a SADL model in the com.ge.research.sadl.jena.JenaBasedSadlModelProcessor onValidate method, it retrieves the instance of IConfigurationManagerForIDE for the Xtext resource (the current SADL file), from which it retrieves an instance of OntModelSpec and OntDocumentManager. It then calls the OntModelSpec's method setImportModelGetter with an instance of the class SadlJenaModelGetterPutter. Then, before starting to process the SADL file parse tree to construct the corresponding OWL OntModel, it calls org.apache.jena.rdf.modelModelFactory's createOntologyModel method, passing in the OntModelSpec instance, to create an empty OntModel. This in-memory OntModel is populated as the SADL file parse tree is processed. When an import statement is encountered (and for the implicitly imported models), a call is made to get the imported model's OntModel from the com.ge.research.sadl.processing.OntModelProvider class. If the imported model's OntModel is not found, then the imported model is loaded. If the imported model is another SADL model, then it is processed by the JenaBasedSadlModelProcessor and an OntModel is created and stored in the OntModelProvider. If the imported model is an ExternalEmfResource (an OWL model not derived from a SADL model), then the OntModel is generated from the OWL model, which is processed to identify the ontological concepts found therein, and stored. This method of loading is necessary so that Xtext will have all of the information for hyperlinking referenced concepts to their definitions and concept definitions to their references. In the case of an ExternalEmfResource, the SADL IDE loads an OWL model from an OWL model from persistent storage. In the case of a modified SADL model which is saved, the in-memory OntModel is saved to the persistence repository as an OWL model using the ISadlModelGetterPutter set in the OntModelSpec instance.

This process works differently when, for example, a request is made to graph the models in a SADL project or when running inference not in the SADL IDE. In this case the in-memory OntModel instances necessary to create the graph(s) or do inference are loaded directly from  the persistence repository using the ISadlModelGetter. Import statements encountered in the OntModel's triples result in additional OWL models being loaded using the instance of SadlJenaModelGetterPutter stored in the OntModelSpec. In other words, when Jena loads an OWL model from the persistence repository, again using the instance of SadlJenaModelGetterPutter in the OntModelSpec, Jena will also load all of the model's imports in the same way.