Skip to content

API Usage and examples

GBOL API

GitLab CI publishes every build of the Java API to the package registry, so a Gradle project only needs the dependency (Java 21 or newer). RDFSimpleCon comes along with it:

repositories {
    mavenCentral()
    maven { url 'https://gitlab.com/api/v4/groups/Empusa/-/packages/maven' }
    maven { url 'https://gitlab.com/api/v4/groups/gbol/-/packages/maven' }
}
dependencies {
    implementation 'life.gbol.GBOLApi:GBOLApi:0.2'
}

A single jar with all dependencies included can be found here. The R API is in RGBOLApi and the Python API in PyGBOLApi (pip install .).

Private API

If you have developed your own OWL/ShEx file you can generate an API package using the EmpusaCodeGen program.

For example to generate the GBOL Java, R and Python APIs we use the following command

java -jar EmpusaCodeGen.jar -i GbolAdditional.ttl gbol-ontology.ttl -o ../GBOLApi/ -r ../RGBOLApi -py ../PyGBOLApi

(See additional examples in the API Development section)

Compiling the private API

Installing the Java API

To compile the java package into a single jar run the install.sh script in the generated folder. You can also use the java classes directly in your programming environment. The generated API depends on RDFSimpleCon, which Gradle downloads from the Empusa package registry. You need Java 21 or newer and Gradle 9. When the generated project is pushed to GitLab, its CI can publish it to that project's package registry like GBOLApi.

Example shown for Ubuntu:

#Install Java 21
sudo apt-get install openjdk-21-jdk

#Install Gradle 9, for example with SDKMAN (https://sdkman.io)
sdk install gradle

#run the install script
./install.sh

Installing the R API

The R API calls the Java API through rJava, so it needs R, Java 21 or newer, rJava and the jar of the Java API in inst/java.

Example shown for Ubuntu 24.04, for the GBOL R API:

#Install Java 21, R and rJava
sudo apt-get install openjdk-21-jdk r-base
sudo R CMD javareconf
Rscript -e 'install.packages("rJava")'

#Get the package and the GBOLApi jar it needs
git clone https://gitlab.com/gbol/RGBOLApi && cd RGBOLApi
wget -O inst/java/life.gbol.GBOLApi.jar "https://gitlab.com/gbol/GBOLapi/-/jobs/artifacts/main/raw/build/libs/life.gbol.GBOLApi.jar?job=build"

#Install the package
R CMD INSTALL .

For your own API, copy the jar that the Java API build produces into inst/java instead.

Using the API

After compilation of the ontology for the API, we focus now on how to use the API to create and check the consistency of your RDF files. The following instructions are for the Java API and relate to a relatively simple ontology used to store information on books and authors. An example focussed on the GBOL ontology and instructions on how to use the R API are included in

http://gitlab.com/gbol/example

Using the API through the source code files

This example is written for Intellij but it should also work for Eclipse. We first load the code base as a new project into Intellij.

Project overview

  • I have created a new empty project in which the API folder was imported as a module with Gradle support.
  • MyProgram.class should be created inside the following path MyJavaApi/src/main/java/, using the code outlined below:
import com.xmlns.foaf.domain.Agent;
import nl.wur.ssb.RDFSimpleCon.RDFFormat;
import nl.wur.ssb.RDFSimpleCon.api.Domain;
import org.purl.ontology.bibo.domain.Book;

import java.io.File;
import java.time.LocalDate;

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");

        // Setting the title of the book
        book.setTitle("Romeo and Juliet");

        // Setting the abstract of a abook
        book.setAbstract("The abstract of the book");

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

        // But you can also set it to an older date which will overwrite the previous  date
        LocalDate localDate = LocalDate.of(1596, 12, 31);
        book.setDateAccepted(localDate);

        Agent agent = domain.make(com.xmlns.foaf.domain.Agent.class, "http://example/com/myAgent");
        agent.setName("William Shakespeare");
        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 "" creates a temporary memory store that is available for as long as the code runs. Persistent disk stores can be used using a "file://" path.

Domain domain = new Domain("");

Once the domain object is created, classes can be spawned (according to the ontology) and filled with content.

For 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/myAgent");

And what is an author without a name?

agent.setName("William Shakespeare");

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);

Consistency check and validation of ontology restrictions

Within the OWL/ShEx file you can set restrictions using the regex patterns (e.g. ?, *, +, integer / string etc...). In the previous example we meet all requirements and restrictions imposed by the ontology so no errors arose.

The API automatically checks that the data follow the requirements in the ontology (ShEx validation).
In the following example, the API will complain and stop because something was forgotten and the data no longer meet the requirements.

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

import java.io.File;
import java.time.LocalDate;

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");

        // Setting the title of the book
        book.setTitle("Romeo and Juliet");

        // Setting the abstract of a abook
        book.setAbstract("The abstract of the book");

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

        // But you can also set it to an older date which will overwrite the previous  date
        LocalDate localDate = LocalDate.of(1596, 12, 31);
        book.setDateAccepted(localDate);

        Agent agent = domain.make(com.xmlns.foaf.domain.Agent.class, "http://example/com/myAgent");
        // agent.setName("William Shakespeare");
        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);
    }
}

We have commented out the following line // agent.setName("William Shakespeare");. Now there is no author name attached to the agent which is added to the book. When an item (Agent) is added to another item (Book) the validator kicks in and checks the constraints. It then sees that the name is required and will show the following message stating that the cardinality for name is incorrect.

Exception in thread "main" java.lang.RuntimeException: Cardinality should be >=1 for property: http://xmlns.com/foaf/0.1/name
    at nl.wur.ssb.RDFSimpleCon.api.OWLThingImpl.checkCardMin1(OWLThingImpl.java:1187)
    at com.xmlns.foaf.domain.impl.AgentImpl.validate(AgentImpl.java:43)
    at nl.wur.ssb.RDFSimpleCon.api.OWLThingImpl.addRefListList(OWLThingImpl.java:794)
    at org.purl.ontology.bibo.domain.impl.BookImpl.addAuthorList(BookImpl.java:178)
    at MyProgram.main(MyProgram.java:23)

Uncommenting the line ensuring a name is given to the Agent makes the program work again.

Using the API as a dependency

When the API is published to a package registry, like GBOLApi, add the registries and the dependency to your build.gradle as shown at the top of this page.

Using the API through the JAR file

Instead of using the source code files or a package registry, you can also incorporate the JAR file into an already existing JAVA project.

To create a basic JAVA project in which you would like to include the jar execute the following in a new folder (e.g. test)

mkdir test
cd test
mkdir libs # Needed later to place the "API".jar file in
gradle init --type java-application

Open the build.gradle file in intellij as a new project.

Use gradle 'wrapper' task configuration

Once you are all set you should see the newly generated java main and test classes.

To incorporate your API you need to copy the jar file which in my case was my.project.group.jar into the libs folder.

Now you should modify the build.gradle file such that the jar files inside the libs folder are recognised (fileTree line).

dependencies {
    // This includes all jar files from the libs folder
    implementation fileTree(dir: 'libs', include: '*.jar')

    // Use JUnit test framework
    testImplementation 'junit:junit:4.13.2'
}

The editor should see that a change occured and should allow you to reload the gradle build file by importing the changes.

For example:

public class App {

  public static void main(String[] args) throws Exception {
        Domain domain = new Domain("");
        Book book = domain.make(org.purl.ontology.bibo.domain.Book.class,"http://example.com/mybook");
        book.setAbstract("Abstract of the book");
        domain.save("book.ttl");
      }
}

When executed this should create the book.ttl file which contains:

@prefix owl:   <http://www.w3.org/2002/07/owl#> .
@prefix rdf:   <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs:  <http://www.w3.org/2000/01/rdf-schema#> .

<http://example.com/mybook>
        a       <http://purl.org/ontology/bibo/Book> ;
        <http://purl.org/dc/terms/abstract>
                "Abstract of the book" .

The API offers more possibilities, such as direct querying, databases merging and much more!

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