Extension Points Developer's Guide

Semantic Turkey 0.12 introduced a new mechanism for realizing extension points.

Overview

Extension points establish a well-defined interface for third-parties willing to provided additional functionalities. It is possible to distinguish three activities concerning extension points:

The activities above are covered in the forthcoming sections, which assume that the reader is knowledgeable about the development of Semantic Turkey extensions. Because of its extensible use in the code base of Semantic Turkey, some knowledge of Spring DM is also assumed. The rest of the page contains a reference of existing extension points.

Extension Point Development Activities

Extension Point Definition

The definition of an extension point consists of a Java interface, embodying the contract between implementers and users. This interface should be exported from the API bundle, so that others can implement or use it.

Extension Point Implementation

The implementation of an extension point ultimately boils down to a Java class implementing the interface associated with the extension point itself. In fact, it is also necessary to provide a factory, which incapsulates the instantiation policy for the extension point, possibly influenced by a supplied configuration.

The factory for an extension point must implement the interface it.uniroma2.art.semanticturkey.plugin.PluginFactory<T>, which is defined as below:

public interface PluginFactory <T extends PluginConfiguration {

	String getID();
	
	Collection<PluginConfiguration getPluginConfigurations();

	T createDefaultPluginConfiguration();
	
	T createPluginConfiguration(String configType)
			throws UnsupportedPluginConfigurationException,
			UnloadablePluginConfigurationException, ClassNotFoundException;

	Object createInstance(PluginConfiguration conf);
}

The operation getID returns a textual identifier for the factory. That identifier is used at runtime to retrieve the factory from a global registry.

The actual instance returned by the operation createInstance depends on the instantiation policy of the factory, as well as on the supplied configuration parameters. The factory exposes a few operations that allow to retrieve the available configuration alternatives, a default configuration and a configuration given its type.

A configuration class must implement the interface it.uniroma2.art.semanticturkey.plugin.configuration.PluginConfiguration, which defines operations for introspecting the configuration object itself. A factory may support different configuration classes, which should correspond to coarse grain distinctions. At the same time, the available classes must extend a common base class or implement a shared interface, which must be used a type parameter for the interface PluginFactory, since it designes the acceptable configuration types for a factory.

Usually, a configuration class won't implement the interface PluginConfiguration directly; it will instead extend the base class it.uniroma2.art.semanticturkey.plugin.configuration.AbstractPluginConfiguration. That class implements most of the operations expected from a configuration object, while the subclass must only implement the operation getShortName returning its textual identifier. Specific configuration parameters are defined by annotating public fields of the configuration class.

The following code snippet shows a field declaring a parameter with a default value.


@PluginConfigurationParameter(description="a configuration parameter")
public String aParameter = "default value";

It is possible to omit the default value, and require that the user provides a value for the parameter.


@PluginConfigurationParameter(description="a configuration parameter")
@RequiredConfigurationParameter
public String aRequiredParameter;

The abstract class AbstractPluginConfiguration supports configuration parameters of type java.lang.String, boolean, integer, long and double (as well as their associated class wrappers, such as java.lang.Boolean).

To make the implementation of an extension point available for use, it is necessary to publish its factory into the OSGi service registry:

The following snippet shows the above inside a Spring DM context file, assuming the obvious mapping for XML prefixes.


<bean id="extensionPointImplementationFactory" class="class name of the extension point factory" />

<osgi:service interface="it.uniroma2.art.semanticturkey.plugin.PluginFactory" ref="extensionPointImplementationFactory">
	<osgi:service-properties>
    	<entry key="it.uniroma2.art.semanticturkey.extensionpoint" value="name of the interface associated with the extension point" />
    </osgi:service-properties>
</osgi:service>

Extension Point usage

Note: due to rendering issues with the pages of this site, expressions such as $ {...} or $$ {...} are to be intended without the space in the middle.

The entry point for using an extension point inside the server-side of Semantic Turkey is the class it.uniroma2.art.semanticturkey.plugin.PluginManager

The static method it.uniroma2.art.semanticturkey.plugin.PluginManager.getPluginFactories(String) returns the factories associated with available implementations of the supplied extension point (identified via the fully qualified name of the associated Java interface).

When the identifier of a plugin factory is known, it is possible to obtain the factory instance through the operation it.uniroma2.art.semanticturkey.plugin.PluginManager.getPluginFactory(String)

Inside the Firefox client, the service module SERVICE_Plugins.jsm allows to retrieve metadata about an extension point and the available factories.

The method getAvailablePlugins returns the available implementations of a given extension point.


<stresponse request="getAvailablePlugins" type="reply">
	<reply status="ok"/>
	<data>
		<plugin factoryID="it.uniroma2.art.semanticturkey.plugin.impls.rendering.SKOSRenderingEngineFactory"/>
		<plugin factoryID="it.uniroma2.art.semanticturkey.plugin.impls.rendering.RDFSRenderingEngineFactory"/>
		<plugin factoryID="it.uniroma2.art.semanticturkey.plugin.impls.rendering.SKOSXLRenderingEngineFactory"/>
	</data>
</stresponse>

The method getAvailablePlugins returns the available implementations of a given extension point, together with an XML serialization of their alternative configuration classes


<stresponse request="getPluginConfigurations" type="reply">
	<reply status="ok"/>
	<data>
		<configuration editRequired="false" shortName="Native template-based" type="it.uniroma2.art.semanticturkey.plugin.impls.urigen.conf.NativeTemplateBasedURIGeneratorConfiguration">
			<par description="Template for SKOS concepts" name="concept" required="false"$ {rand()}</par>
			<par description="Template for SKOS eXtended Labels" name="xLabel" required="false"$ {lexicalForm.language}_&#38;#36;&#38;#123;rand()}</par>
			<par description="Template for SKOS Definitions" name="xDefinition" required="false"$ {rand()}</par>
			<par description="Fallback template for any unknown genre of resource" name="fallback" required="false">$ {xRole}_$ {rand()}</par>
		</configuration>
	</data>
</stresponse>

Extension Point Reference

URI Generator

The extension point uri generator (it.uniroma2.art.semanticturkey.plugin.extpts.URIGenerator) allows to customize the generation of URI for newly created resources in the knowledge base managed inside a Semantic Turkey project. Each project is associated exactly with one instance of this extension point, which is chosen during the creation of the project itself.

In the project file (project.info), there are two properties:

Then, in the project directory, the file urigen.config contains the serialization of the configuration object to use for instantiating the extension point.

The Java interface associated with this extension point is the following one.


public interface URIGenerator {
	
	public static final class Roles {
		public static final String concept = "concept";
		public static final String conceptScheme = "conceptScheme";
		public static final String xLabel = "xLabel";
		public static final String xNote = "xNote";
	}
	
	public static final class Parameters {
		public static final String label = "label";
		public static final String scheme = "scheme";
		public static final String lexicalForm = "lexicalForm";
		public static final String lexicalizedResource = "lexicalizedResource";
		public static final String type = "type";
		public static final String value = "value";
		public static final String annotatedResource = "annotatedResource";
	}

	ARTURIResource generateURI(STServiceContext stServiceContext, String xRole, Map<String, ARTNode> args)
			throws URIGenerationException;
}


The interface above defines only one operation, which produces an ARTURIResource based on the provided input:

  1. stServiceContext: contextual information for the current request
  2. xRole: the "extended role" of the resource being created (which may determine the "shape" of the generated URI)
  3. args: a map providing additional information that may be exploited for the generation of a URI

Depending on the value of the parameter xRole, a conforming converter may generate differently shaped URIs, possibly using specific arguments passed via the map args. For each specific xRole, the client should provide some agreed-upon arguments to the URI generator. For example, the following should be regarded as well known parameters:

The parameters requested by additional xRoles are defined elsewhere by the party defining that xRole. Users of this extension point should always supply values for the mandatory parameters associated with an xRole; therefore, they should not attempt to generate a URI for an xRole unless they known which arguments are requested.

Conversely, it is a duty of the specific implementation of this extension point to verify that all relevant information has been provided by the client. In fact, it is suggested that implementations act defensively, that is to say they should:

In most cases, users do not interact with this extension point directly. Indeed, they should prefer the methods generateXXX that are provided by some service classes, such as SKOS and SKOSXL. The use of those methods is to be preferred because they explicit via a Java method signature which arguments are required, whereas the direct use of the extension point does not enforce in any way the provision of the mandatory arguments.

In some circumstances, Semantic Turkey may execute PEARL transformation rules by means of an embedded instance of the CODA platform. To assure the generation of uniform URIs, the URI generator extension point has been wrapped as a CODA converter implementing the contract http://art.uniroma2.it/coda/contracts/randIdGen. It is therefore necessary to use that contract in the PEARL rules, while externally CODA must be configured to bind that contract to the specific implementation we are discussing. To do so, it is possible to use the code below:


CODACore codaCore = ...;
codaCore.setGlobalContractBinding("http://art.uniroma2.it/coda/contracts/randIdGen",
                                  "http://semanticturkey.uniroma2.it/coda/converters/randIdGen");


See the user guide for information about implementations of this extension point shipped with Semantic Turkey.

Rendering Engine

The extension point rendering engine (it.uniroma2.art.semanticturkey.plugin.extpts.RenderingEngine) allows to customize the generation of a human friendly representation of a resource inside the Resource View. This interface is likely to change in the next release of Semantic Turkey.

Each project managed by Semantic Turkey is associated with a single instance of this extension point, which is specified at the time the project is created. In the project file (project.info), there are two properties:

Then, in the project directory, the file rendering.config contains the serialization of the configuration object to use for instantiating the extension point.

The Java interface associated with this extension point is the following one.


public interface RenderingEngine {

	Map<ARTResource, String> render(Project<> project, ResourcePosition subjectPosition, ARTResource subject,
			OWLModel statements, Collection<ARTResource> resources, Collection<TupleBindings> bindings, String varPrefix) throws ModelAccessException, 
			DataAccessException;

	String getGraphPatternForDescribe(ResourcePosition resourcePosition, ARTResource resourceToBeRendered, String varPrefix);
}

The interface is based on a two-phase protocol.

In the first phase, the method getGraphPatternForDescribe is invoked to obtain a graph pattern suitable for inclusion in the SPARQL query performed by the resource view. Its parameters are:

The linkage between the returned graph pattern and the rest of the SPARQL query is based on the following conventions on the use of variables:

After the evaluation of the overall SPARQL query, it is possible to invoke the method render, which has the following parameters:

The users of this extension point should interact with the instance returned by the class it.uniroma2.art.semanticturkey.rendering.RenderingOrchestrator. The returned rendering engine computes a default rendering for each resource (i.e. its URI or blank node identifier), computes the final rendering for some resources (e.g. bnodes defining anonymous classes or RDF collections), and otherwise delegates to the appropriate rendering engine for the subject resource. If the subject belongs to a local project, then its associated rendering engine is used. Otherwise, in case of a remote dataset, a rendering engine conforming to RDFS labels is used instead.

See the user guide for information about implementations of this extension point shipped with Semantic Turkey.