Skip to content

Empusa

The development of ...

During the development of the GBOL ontology it became increasingly more difficult to handle the changes made in the ontology. We had developed RDF2Graph in the past to reveal the structure of a semantic database but was only sufficient once a database was created. To enforce parsers to cohere to the ontology we required a more advanced solution in the form of an API generator based on an ontology.

To manage the large variety of properties and classes in an easy to use format we have developed Empusa as part of the GBOL Stack. Empusa is a java application which converts OWL/Shex like ontologies into an API for Java and R + an ontology website.

As an example, for the GBOL ontology, alone empusa generates from a 4000 line ontology a JAVA api of 50.000 lines, R api of 12.000 lines and an OWL and ShExC file of 12.044 and 3202 lines and this website you are currently viewing.

The input file for Empusa is a combination between OWL and a simplified version of ShEx, which can be edited within for example Protege.

The classes are defined in OWL, whereas the properties are defined in each class under the annotation property ‘propertyDefinitions’ encoded within a simplified format of the ShEx standard.

Additionally predefined value sets (for example all article types) can be defined by adding a subclass to the EnumeratedValueClass. Each subclass of the value set is represented as one element within the value set.

All together Empusa shortens the development cycle, eases the development, consistency and maintenance of GBOL and its associated framework as it generates all the elements from one single entity.

Using Empusa

To be able to use the Empusa application, the ontology or input file needs to be written in a combination of OWL/Shex of which structural examples are given below using Protégé.

Obtaining Empusa

The application which consists of various modules can be found at:

https://gitlab.com/Empusa/Empusa

The application can be installed through the following command which is located in the folder obtained.

./install.sh install

An example of an ontology project can be found at:

https://gitlab.com/Empusa/ExampleOntology

And to obtain it just run the following command:

git clone https://gitlab.com/Empusa/ExampleOntology

Once retrieved the ontology builder can be installed using the installation script

./install.sh

Which creates an executable jar if you wish to build it through the command line.

It is advicable to instead of clone the project to fork it. This gives you full rights over the code with your own repository. It allows you then to work with multiple people on the ontology through GIT if needed.

Getting started - Building your own ontology

More importantly there are two turtle files located in this cloned project from before:

  • ExampleAdditional.ttl
  • example-ontology.ttl

First, the ExampleAdditional.ttl is a file containing extra information about your ontology and should be changed accordingly:

@prefix up: <http://purl.uniprot.org/core/> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix xml: <http://www.w3.org/XML/1998/namespace> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix gen: <http://ssb.wur.nl/OwlShexCodeGen#> .
@base <http://mybase.com/0.2/> .


<http://mybase.com/0.2/> rdf:type owl:Ontology ;
    gen:codeProjectGroup "my.project.group";
    gen:codeProjectName "Example";
    gen:codeProjectVersion "0.2";
    gen:codeProjectFullName "Example Api";
    gen:codeProjectDescription "The Example API code generated from the Example owl file";

The values of the codeProject properties can be modified to your likings corresponding to the ontology you are making.

The second file example-ontology.ttl contains the ontology. We used protege to create this ontology file and can therefore be easily opened with protege.

In the following image an overview of the example ontology is given.

Example ontology

The root of the ontology is an owl:Thing in which all the other subclasses are defined in.

An important class for the API is the EnumeratedValueClass. Within this class a limited selection for a specific property can be defined. For example when a class has the property country it should be defined as:

#* The country 
country type::Country;

This makes sure that the predicate country can only choose from the list of contries available in the subclass Country of the EnumeratedvalueClass. This to ensure strict coherence to an accepted naming scheme.

Linking to other classess can be done via

bibo:presents @bibo:Document*;
bibo:organizer @foaf:Agent*;
bibo:place xsd:String*;

In which the @bibo:Document points to the

Document class located under Literature in the same ontology file and the organizer points to an Agent class.

To define other types such as String, integer, date, etc... the following way of writing is used:

bibo:shortTitle xsd:String?;
dc:created xsd:date?;
bibo:numPages xsd:Integer?;

To strict the number of values a specific predicate can have the * ? + symbols are used where * denotes 0 or more, ? 0/1 and + 1 or more.

For a more complex ontology written in this format have a look at the root-ontology.ttl in the GBOL git directory.

Generating the API

Once you have defined (or a part of) your ontology the API can be created. This can be achieved through a Java editor like Eclipse or Intellij but also by using the following command:

java -jar ExampleOntology.jar

The following options are required: -i, -input -o, -output 
Usage: <main class> [options]
  Options:
        --help

    -rg, -RDF2Graph
       File to write RDF2Graph file
    -r, -Routput
       The direcotry into which the R project should be generated
    -sC, -ShExC
       Generate ShExC file
    -sR, -ShExR
       Generate ShExR file
    -eb, -excludeBaseFiles
       Do not overwrite the base project and pom files
       Default: false
  * -i, -input
       The ontology to use
  * -o, -output
       The direcotry into which the project should be generated
    -owl
       Generate official OWL file
    -sNP, -skipNarrowingProperties
       RDF2Graph export skip property already defined in parent class
       Default: false

  * required parameter

For example to build the Example ontology:

java -jar ExampleOntology.jar -i example-ontology.ttl -i ExampleAdditional.ttl -o ../MyJavaApi -owl ../MyJavaApi/owl.thing -ShExC ../MyJavaApi/ShExC.thing

This creates a MyJavaApi folder in which all the source code files and gradle build files are located.

Using the API

After creating the ontology and generated the source files for the API we focus now on how to use the API to create your RDF files.

This example is written for Intellij but I am sure it should also work for eclipse.

Project overview

  • I have created a new empty project in which the API folder was imported as a module with Gradle support.

  • MyProgram.class is created inside the following path MyJavaApi/src/main/java/nl/wur/ssb/, using the code outlined below:

package nl.wur.ssb;

import com.xmlns.foaf.domain.Agent;
import java.io.File;
import java.time.LocalDate;
import nl.wur.ssb.RDFSimpleCon.RDFFormat;
import nl.wur.ssb.RDFSimpleCon.api.Domain;
import org.purl.ontology.bibo.domain.Book;

public class MyProgram {

  public static void main(String[] args) throws Exception {
    Domain domain = new Domain("");

    // Creating the book object using the class type and a URL
    Book book = domain.make(org.purl.ontology.bibo.domain.Book.class,"http://example.com/mybook");

    book.setAbstract("The abstract of the book");

    // The book was accepted today!
    book.setDateAccepted(LocalDate.now());

    Agent agent = domain.make(com.xmlns.foaf.domain.Agent.class,"http://example/com/myAgent007");
    agent.setName("James Bond");
    book.addAuthorList(agent);

    // Saving the database to a file in the TURTLE format
    String output = new File("example.ttl").getAbsolutePath();
    domain.save(output , RDFFormat.TURTLE);

    System.out.println("Saved to: "+output);
  }
}

Breaking it down into smaller steps the following is happening:

Standard java class creation:

package nl.wur.ssb;

import com.xmlns.foaf.domain.Agent;
import java.io.File;
import java.time.LocalDate;
import nl.wur.ssb.RDFSimpleCon.RDFFormat;
import nl.wur.ssb.RDFSimpleCon.api.Domain;
import org.purl.ontology.bibo.domain.Book;

public class MyProgram {

  public static void main(String[] args) throws Exception {

RDF / JENA store creation, using "" it creates a temporary memory store as long as the code runs this is available. Persistent disk stores can be used using a "file://" path.

Domain domain = new Domain("");

Once the domain object is created, classess can be spawned and filled with content.

for example example to create a book entry:

domain.make(org.purl.ontology.bibo.domain.Book.class,"http://example.com/mybook");

The source path as present in the "API" folder in this project + the class name (here Book) and the .class is needed. The second argument is the URL of this entry.

The nice thing about the Java api is to know what kind of properties are available for the Book class and all its parent classes. Just type variableName. and possibilities should pop up.

For example to set the Abstract a string object is required and can just be directly written like:

book.setAbstract("The abstract of the book");

Or instead of a string, setting the date for a publication can be done like this:

book.setDateAccepted(LocalDate.now());

Connecting properties can be done via first creating the other object for example the Author of a book which is an Agent:

Agent agent = domain.make(com.xmlns.foaf.domain.Agent.class,"http://example/com/myAgent007");

And what is an author without a name?

agent.setName("James Bond");

Now connecting the book to the author:

book.addAuthorList(agent);

As a book can have multiple authors the book.addAuthorList(agent) can be used multiple times to add other authors e.g. (book.addAuthorList(agent2))

Finally you would like to have the RDF database in a formatted RDF file.

domain.save(output , RDFFormat.TURTLE);

There are more possibilities with the API, such as direct querying, merging databases and more!

Feel free to contact us for any Empusa / API / OWL/Shex related issues.