Getting Started

What is KOMMA?

KOMMA is a Java library for manipulating RDF data through an object-oriented API.

Frameworks like Eclipse RDF4J or Apache Jena provide powerful APIs to execute SPARQL queries and to work with RDF on a statement level. But they require the developer to always think in triples. For example, to get the (FOAF) name of a person with one of these frameworks an API call like conn.getStatements(person, foafName, null) has to be used. KOMMA simply allows to access the property by calling a method like person.getFoafName() on an object representing the person.

Features

KOMMA has the following features:

  • Mapping of Java interfaces to RDF types

  • Support for multiple inheritance

  • Implementation of logic using behaviours and aspect-oriented programming

  • Caching of beans and properties

  • Model API for working with named graphs

Mapping of Java interfaces to RDF types

KOMMA’s main feature is the mapping of Java interfaces to RDF types and properties. The following example shows an interface that represents the RDF type foaf:Person with the two properties foaf:name and foaf:knows.

@Iri("http://xmlns.com/foaf/0.1/Person")
public interface Person {
        @Iri("http://xmlns.com/foaf/0.1/name")
        String name();

        Person name(String name);

    @Iri("http://xmlns.com/foaf/0.1/knows")
        Set<Person> knows();

        Person knows(Set<Person> knows);
}

KOMMA uses only the single annotation @Iri for the definition of mappings that can be applied either to interfaces or methods. When used on an interfaces its string value is interpreted as an RDF type (like http://xmlns.com/foaf/0.1/Person). When used on a method its value is interpreted as an RDF property (like http://xmlns.com/foaf/0.1/knows).

Mappings of interfaces and properties don’t need to correspond to any RDF schema or OWL ontology and they also don’t need to be complete in respect to the RDF data. It is possible to map only those types and properties that are required for an application.

Literal types like xsd:string, xsd:int and others are mapped to the corresponding Java types like String, int/Integer and others.

Entity Manager

The main API for working with RDF objects is the entity manager. It provides methods to create, retrieve and delete RDF objects and their properties.

The entity manager API

The following source code examples demonstrate how to use the entity manager API for working with mapped beans.

IEntityManager em;

// create a named resource with an URI -> RDF type statement is added to database
Person john = em.createNamed(URIs.create("http://example.org/persons/john"), Person.class);

// find an existing resource -> no statements are added to database
Person jane = em.find(URIs.create("http://example.org/persons/jane"), Person.class);

// delete a resource from the database
em.remove(john);
// delete a resources and outgoing statements recursively while following only anonymous resources
em.removeRecursive(john, true);

// use mapped properties to add statements
john.knows().remove(jane);
john.knows().clear();
john.knows().add(jane);

// use equivalent statement-level APIs
em.remove(new Statement(john, URIs.createURI("http://xmlns.com/foaf/0.1/knows"), jane);
em.remove(new Statement(john, URIs.createURI("http://xmlns.com/foaf/0.1/knows"), null);
em.add(new Statement(john, URIs.createURI("http://xmlns.com/foaf/0.1/knows"), jane);

// create resource that is represented by a blank node
Person anonymous = em.create(Person.class);
anonymous.name("Unknown person");

// create a SPARQL query
IQuery<?> query = em.createQuery(
    "prefix foaf: <http://xmlns.com/foaf/0.1/> ." +
    "select ?other { ?p foaf:knows ?ther }");
query.setParameter("p", john);

// evaluate query with unknown result types
IExtendedIterator<?> results = query.evaluate();

// evaluate query while ensuring that results are at least of type Person
IExtendedIterator<Person> resultsAsPersons = query.evaluate(Person.class);
List<Person> personList = resulsAsPerson.toList();

Create an entity manager

The following example shows how an entity manager can be created for an existing RDF4J repository.

IEntityManager createEntityManager(Repository repository) {
    // create a KOMMA module with mapped interfaces
    KommaModule kommaModule = new KommaModule();
    kommaModule.addConcept(Person.class);

    // create a Guice injector and retrieve an entity manager instance
    Injector injector = Guice.createInjector(createGuiceModule(kommaModule, repository));
        IEntityManagerFactory factory = injector.getInstance(IEntityManagerFactory.class);
        return factory.get();
}

Module createGuiceModule(KommaModule kommaModule, Repository repository) {
    return new AbstractModule {
        @Override
        protected void configure() {
            install(new RDF4JModule());
            install(new EntityManagerFactoryModule(kommaModule, null,
                new CachingEntityManagerModule()));
            install(new CacheModule("emCache"));

            UnitOfWork uow = new UnitOfWork();
            uow.begin();

            bind(UnitOfWork.class).toInstance(uow);
            bind(IUnitOfWork.class).toInstance(uow);
            bind(Repository.class).toInstance(dataRepository);
        }

        @Provides
        protected IDataManager provideDataManager(IDataManagerFactory dmFactory) {
            return dmFactory.get();
        }
    }
}

Model API — support for named graphs

KOMMA provides a powerful API for working with named graphs. It has the following features:

  • load and save RDF files in formats supported by RDF4J (Turtle, JSON-LD, RDF/XML and others)

  • automatically resolve OWL imports (owl:imports)

  • change tracking for undo/redo support or audit trails

  • association between mapped interfaces/behaviours and ontologies

The model API provides the following two main interfaces:

  • IModelSet — an interrelated set of multiple named graphs (e.g. ontologies with `owl:import`s)

  • IModel — one named graph within a model set. This interface may represent a single RDF document.

Create a model set

The following example code shows how to create a model set.

// create configuration and a model set factory
KommaModule module = ModelPlugin.createModelSetModule(getClass().getClassLoader());
IModelSetFactory factory = Guice.createInjector(new ModelSetModule(module)).getInstance(IModelSetFactory.class);

// create a model set with an in-memory repository
IModelSet modelSet = factory.createModelSet(MODELS.NAMESPACE_URI.appendFragment("MemoryModelSet"));

// include own modules with concepts and behaviours
modelSet.getModule().includeModule(new ExampleModule());

More examples

Editors

Contributing