Henriette's Notes

Home » 2018 » April (Page 2)

Monthly Archives: April 2018

Object Oriented Features that OWL lacks

At some level OWL seem to be very similar to UML, but there are important differences that you have to keep in mind. In this post I detail features you will have to do without coming from a coding or object orientation perspective when you start using OWL. These are:

  1. classes do not have attributes,
  2. classes do have class variables (but not in the way you think),
  3. you have to live without methods,
  4. there are no interfaces, and
  5. neither are there any abstract classes.

Classes do not have Attributes

Programmers are used to classes that have attributes or properties. This is also referred to as instance/member variables of the class. In OWL classes do not have properties. Rather, properties can be used to model relations that exist between classes and data types. You can however state that a class is a subclass of something that has some property. I.e.,

Class: Course
  SubClassOf: 
    hasSubject some Subject 

which states that a Course is a subclass of things that have some
Subject. I explain this here and here.

Classes do have Class Variables (but not in the way you think)

In programming class variables are values that describe the class rather than instances of the class. In OWL this is achieved trough annotations. There exist pre-defined annotation properties and you can define your own annotation properties. Interestingly annotation properties can be specified for any class, individual or axiom, as well as the ontology itself. Annotations are purely used to specify additional information and no reasoning is done over them.

There are no Methods nor Interfaces

This may seem like silly a comment, but is worth making it explicit: “OWL does not have methods”. Why not? Well, OWL is not a programming language nor a modelling language for designing software. It is a conceptual modelling language. Can you model methods in OWL? Yes, I have done it here to find software modelling heuristic violations, but it is not trivial. However, even if you can define the conceptual notion of a method, there is no way to execute methods in OWL. Again, because it is not a programming language.

What about interfaces? Well, since there are no methods in OWL, there are no interfaces either. In programming the idea is that an interface defines the signature of an interaction, usually in terms of method signatures, without specifying how the methods are actually implemented. This allows for the same interface to have different implementations.

Neither are there Abstract Classes

Abstract classes in programming are used to enable programmers to only implement a subset of the interfaces specified, thereby forcing subclasses to do the implementation. However, again since interfaces do not exist, and there are no methods, it does not make sense for OWL to support abstract classes.

What about the case where in programming an abstract class is defined that only consist of member/instance variables? In programming this has the effect that no instances of this class can be created directly. The only way an instance can be created is by creating an instance of a subclass of the abstract class. Importantly these instances created of the subclass are still instances of the abstract class. In OWL there is no way to force that individuals cannot be created of a class, but only for its subclasses. The closest to not being able to create individuals for a class is the class ‘owl:Nothing‘, but that really means the class has zero individuals, which is not what is meant by an abstract class in programming.

Conclusion

In this post I detailed some object oriented features programmers may feel OWL lacks. However, OWL is a conceptual modelling language with reasoning capability. Thinking about it causes one to realize it makes as little sense to say OWL lacks some object oriented feature as saying that Java or C# lacks reasoning capability.

Creating, Writing and Reading Jena TDB2 Datasets

Jena TDB2 can be used as an RDF datastore. Note that TDB (version 1 of Jena TDB) and TDB2 are not compatible with each other. TDB2 is per definition transactional (while TDB is not). In this post I give a simple example that

  1. create a new Jena TDB2 dataset,
  2. create a write transaction and write data to the datastore,
  3. create a read transaction and read the data from the datastore, and
  4. release resources associated with the dataset on writing and reading is done.

Create TDB2 Dataset

To create a Jena TDB2 dataset, we use the TDB2Factory. Note that the class name is TDB2Factory and not TDBFactory. We need to specify a directory where our dataset will be created. Multiple datasets cannot be written to the same directory.

Path path = Paths.get(".").toAbsolutePath().normalize();      
String dbDir = path.toFile().getAbsolutePath() + "/db/"; 
Location location = Location.create(dbDir);      
Dataset dataset = TDB2Factory.connectDataset(location); 

Create WRITE Transaction and Write

dataset.begin(ReadWrite.WRITE);
UpdateRequest updateRequest = UpdateFactory.create(
  "INSERT DATA { " 
  + " \"Grace Hopper\" .}");
UpdateProcessor updateProcessor = 
  UpdateExecutionFactory.create(updateRequest, dataset);
updateProcessor.execute();
dataset.commit(); 

Create READ Transaction and Read

dataset.begin(ReadWrite.READ);
QueryExecution qe = QueryExecutionFactory
  .create("SELECT ?s ?p ?o WHERE {?s ?p ?o .}", dataset);
for (ResultSet results = qe.execSelect(); results.hasNext();) {
  QuerySolution qs = results.next();
  String strValue = qs.get("?o").toString();
  logger.trace("value = " + strValue);
}  

Release Dataset Resources and Run Application

The dataset resources can be release calling close() on the dataset.

dataset.close();

Running the application will cause a /db directory to be created in the directory from where you run your application, which consists of the various files that represent your dataset.

Conclusion

In this post I have given a simple example creating a TDB2 dataset and writing to and reading from it. This code can be found on github.

Creating a Remote Repository for GraphDB with RDF4J Programmatically

In my previous post I have detailed how you can create a local Ontotext GraphDB repository using RDF4J. I indicated that there are some problems when creating a local repository. Therefore, in this post I will detail how to create a remote Ontotext GraphDB repository using RDF4J. As with creating a local repository, there are three steps:

  1. Create a configuration file, which is as for local repositories.
  2. Create pom.xml file, which is as for local repositories.
  3. Create the Java code.

The benefit of creating a remote repository is that it will be under the control of the Ontotext GraphDB Workbench. Hence, you will be able to monitor your repository from the Workbench.

Java Code

package org.graphdb.rdf4j.tutorial;

import java.io.FileInputStream;
import java.io.InputStream;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Iterator;

import org.eclipse.rdf4j.model.Model;
import org.eclipse.rdf4j.model.Resource;
import org.eclipse.rdf4j.model.Statement;
import org.eclipse.rdf4j.model.impl.TreeModel;
import org.eclipse.rdf4j.model.util.Models;
import org.eclipse.rdf4j.model.vocabulary.RDF;
import org.eclipse.rdf4j.repository.Repository;
import org.eclipse.rdf4j.repository.RepositoryConnection;
import org.eclipse.rdf4j.repository.config.RepositoryConfig;
import org.eclipse.rdf4j.repository.config.RepositoryConfigSchema;
import org.eclipse.rdf4j.repository.http.config.HTTPRepositoryConfig;
import org.eclipse.rdf4j.repository.manager.RemoteRepositoryManager;
import org.eclipse.rdf4j.repository.manager.RepositoryManager;
import org.eclipse.rdf4j.repository.manager.RepositoryProvider;
import org.eclipse.rdf4j.rio.RDFFormat;
import org.eclipse.rdf4j.rio.RDFParser;
import org.eclipse.rdf4j.rio.Rio;
import org.eclipse.rdf4j.rio.helpers.StatementCollector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.Marker;
import org.slf4j.MarkerFactory;

public class CreateRemoteRepository {
  private static Logger logger = LoggerFactory.getLogger(CreateRemoteRepository.class);
  // Why This Failure marker
  private static final Marker WTF_MARKER = MarkerFactory.getMarker("WTF");
	
  public static void main(String[] args) {
    try {		
      Path path = Paths.get(".").toAbsolutePath().normalize();
      String strRepositoryConfig = path.toFile().getAbsolutePath() + "/src/main/resources/repo-defaults.ttl";
      String strServerUrl = "http://localhost:7200";
		
      // Instantiate a local repository manager and initialize it
      RepositoryManager repositoryManager  = RepositoryProvider.getRepositoryManager(strServerUrl);
      repositoryManager.initialize();
      repositoryManager.getAllRepositories();

      // Instantiate a repository graph model
      TreeModel graph = new TreeModel();

      // Read repository configuration file
      InputStream config = new FileInputStream(strRepositoryConfig);
      RDFParser rdfParser = Rio.createParser(RDFFormat.TURTLE);
      rdfParser.setRDFHandler(new StatementCollector(graph));
      rdfParser.parse(config, RepositoryConfigSchema.NAMESPACE);
      config.close();

      // Retrieve the repository node as a resource
      Resource repositoryNode =  Models.subject(graph
        .filter(null, RDF.TYPE, RepositoryConfigSchema.REPOSITORY))
        .orElseThrow(() -> new RuntimeException(
            "Oops, no <http://www.openrdf.org/config/repository#> subject found!"));

		
      // Create a repository configuration object and add it to the repositoryManager		
      RepositoryConfig repositoryConfig = RepositoryConfig.create(graph, repositoryNode);
      repositoryManager.addRepositoryConfig(repositoryConfig);

      // Get the repository from repository manager, note the repository id 
      // set in configuration .ttl file
      Repository repository = repositoryManager.getRepository("graphdb-repo");

      // Open a connection to this repository
      RepositoryConnection repositoryConnection = repository.getConnection();

      // ... use the repository

      // Shutdown connection, repository and manager
      repositoryConnection.close();
      repository.shutDown();
      repositoryManager.shutDown();					
   } catch (Throwable t) {
     logger.error(WTF_MARKER, t.getMessage(), t);
   }		
  }
}   

Conclusion

In this post I detailed how you can create remote repository for Ontotext GraphDB using RDF4J, as well as the benefit of creating a remote repository rather than a local repository. You can find the complete code of this example on github.