Contracts and Converters Development

Introduction

The syntax and semantics of PEARL should be as concise and application/domain independent as possible. At the same time, the generation of RDF terms out of UIMA metadata might require complex and, possibly, domain dependent procedures.

PEARL reconciles these seemingly conflicting requirements by delegating to externally defined converters the conversion task associated with each placeholder in the nodes section. In fact, a PEARL rule should mention converters indirectly by means of the URI denoting the contracts they implement.

Converters are published as OSGi bundles, which can be deployed in the execution enviroment at any time. Indeed, a contract URI should resolve to an RDF document providing information about a contract, including the address of an OBR repository that contains bundles providing concrete implementations. Locally installed bundles advertise the provided converters in the OSGi service registry.

Contract Development

A contract defines a set of assumptions about the behavior of a conforming converter. Concrete converters can implement a contract in any manner, as long as they are consistent with the general behavior prescribed by the contract.

Contract RDF Description

A contract is identified by a URI, which should return (when dereferenced) an RDF description of the contract. The simplest approach to accomplish that goal is to publish an RDF document as a static file, which contains the description of a contract.

The description of a contract should include its name in one or more natural languages (e.g. through the property rdfs:label), its description (e.g. through the property rdfs:comment), and a reference to a known OBR repository of implementations. Only the latter is really prescribed by CODA, which designates for this purpose the property http://art.uniroma2.it/coda/ns/authoritativeOBR.

As an example, let us consider the identity contract, which prescribes that a conforming converter should produce a node that reflects the provided input as is. The first step is to mint a URI for this contract. The easiest approch is mint a hash-URI based on the URI of a Web document. Concretely, we could decide to publish an RDF document at the address http://example.org/coda/contracts.ttl, and then decide to mint the URI http://example.org/coda/contracts.ttl#identity for the contract. The semantics is that the description of the resource is found in the document located at the address that is obtained by ignoring everything that follows the hash (#), including the hash. A possible description of the contract expressed in the Turtle syntax looks like the following:

			
@prefix coda: <http://art.uniroma2.it/coda/ns/> .
@prefix : <http://example.org/coda/contracts.ttl#> .

:identity a coda:Contract ;
          rdfs:label "Identity contract" ;
          rdfs:comment "A conforming converter should construct an RDF term out of the input value as is"@en ;
          coda:authoritativeOBR <http://example.org/coda/repository.xml> .
			
		

The URI http://example.org/coda/repository.xml is the address of the OBR repository file, which references known implementations of the contract. We will se how to create this file at the end of this guide.

Contract Java Implementation

Currently, CODA does not enforce that each contract has a counterpart in the Java runtime (e.g. an interface). However, it is a good practice (an a future-proof decision with respect to the evolution of CODA) to clealry define a Java interface for a contract.

The following is a possible interface for the identity contract:

			
package org.example.coda.contracts;

import it.uniroma2.art.coda.interfaces.CODAContext;
import it.uniroma2.art.owlart.model.ARTURIResource;
import it.uniroma2.art.owlart.model.ARTLiteral;

/**
 * A conforming converter should construct
 * an RDF term out of the input value as is.
 */
public interface IdentityContract {
	ARTURIResource produceURI(CODAContext ctx, String value);
	ARTLiteral produceLiteral(CODAContext ctx, String datatype, String lang, String value);
}
			
		

In general:

In both cases, the parameter ctx provides contextual information, such as a reference to the target semantic repository. The interface is provided by the coda framework artifact.

The interface associated with a contract should be deployed as a separate bundle. The only required configuration is that the bundle must export the package containing the interface. The identity contract in fact does not foresee multiple implementations, therefore the interface could be shipped directly with the converter.

Converter development

A converter is a specific implementation of a contract, and it is realized as a Java class. Converters are shipped as OSGi bundles, which must meet the following conditions:

Converter Java Implementation

Continuing our example on the identity contract, we should define the associated converter as a Java class:

			
package org.example.coda.converters;

import it.uniroma2.art.coda.interfaces.CODAContext;
import it.uniroma2.art.owlart.model.ARTURIResource;
import it.uniroma2.art.owlart.model.ARTLiteral;

import org.example.coda.contracts.IdentityContract;

/**
 * An implementation of the IdentityContract.
 */
public class IdentityConverter implements IdentityContract {
	public ARTURIResource produceURI(CODAContext ctx, String value) {
		...
		...
	}
	public ARTLiteral produceLiteral(CODAContext ctx, String datatype, String lang, String value) {
		...
		...
	}
}
			
		

The details of the implementation are out of the scope of this guide, which focuses instead on how to make converters available to CODA.

Converter Publication on the Service Registry

The publication of the converter in the service registry may be perfomed in many different ways. If the converter is relatively simple (e.g. it does not depend on other services), then it is possible to publish it using the bundle context, as in the following example.

			
Properties properties = new Properties();
properties.setProperty("it.uniroma2.art.coda.contract", "http://example.org/coda/contracts.ttl#identity");

context.registerService(IdentityContract.class.getName(), new IdentityConverter(), properties);
			
		

Where:

obr.xml

The file obr.xml contains additional metadata to be added to the bundle description in the OBR repository. In particular, a bundle providing a converter should declare that it will publish the converter as a service:

			
<obr>
	<capability name='service'>
		<p v='org.example.coda.contracts.IdentityContract' n='service' />
		<p v='http://example.org/coda/contracts.ttl#identity' n='it.uniroma2.art.coda.contract' />
	</capability>
</obr>
			
		

Obviously, it is necessary indicate the correct contract interface and URI.

Support Autmatic Provisioning of Converters

The PEARL Execution Engine is able to use any converter published on the OSGi Service Regsitry by a locally active bundle. In other words, CODA can operate completely on locally available bundles, without relying on any metadata on the Web.

However, the Component Discovery may exploit the information provided by the RDF description of a contract URI to support the dynamic provision of converters. In particular, it uses the value of coda:authoritativeOBR to locate its associated OBR repository.

Publish the Artifacts on the Web

The bundles providing the converters, the contracts and their dependencies (excluded those already provided by CODA) should be made available on the Web.

Construct the OBR Repository

In the simplest deployment, an OBR repository is completely represented as an XML document, which contains the metadata about the resources in the repository. Actually, the connection between a repository and a resource lies in the fact that among other metadata there is also the Web address of the resource. In this context, a resource is more general concept that also includes OSGi bundles.

Provided that Maven is available on the PATH as mvn, the following steps are sufficient for adding a bundle to an OBR repository.

  1. unpack the bundle in a folder
  2. add the metadata of the bundle to the OBR repository
    						
    mvn org.apache.felix:maven-bundle-plugin:2.3.7:install-file -Dfile={artifact-file} -DpomFile={unpacked-folder}/META-INF/maven/*/*/pom.xml -DobrXml={unpacked-folder}/obr.xml  -DobrRepository={obr-repository}
    						
    					
    Where:
    • {artifact-file} is the path to the bundle
    • {unpacked-folder} is the path to a folder where the bundle has already been unpacked
    • {obr-repository} is the path to the (local copy of) the OBR repository
    If the bundle does not have a obr.xml, omit the parameter obrXml.
  3. In the repository.xml, there should be a resource element for the newly added bundle. However, it is necessary to change the uri attribute, with the value of the Web address of the bundle.
Once the necessary bundles have been registered, it is possible to publish the OBR repository on the Web.

Further Material

  1. Apache Karaf - http://karaf.apache.org/
  2. OSGi Alliance | Release 4 / Version 4.3 API Javadoc - http://www.osgi.org/Release4/Javadoc43
  3. Bundle Plugin for Maven - http://felix.apache.org/site/apache-felix-maven-bundle-plugin-bnd.html
  4. Apache Felix OSGi Bundle Repository (OBR) - http://karaf.apache.org/
  5. Sources of the CODA standard converter library - https://bitbucket.org/art-uniroma2/coda/src/7ea7e0c77e5888ac6bd9965d98f46f1038ab3817/coda-converters/?at=master