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 class name under which the service has to be located is
it.uniroma2.art.semanticturkey.plugin.PluginFactory
- the service must have the property
it.uniroma2.art.semanticturkey.extensionpoint
the value of which is the fully qualified name of the interface associated with the extension point
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}_&#36;&#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:
plugins.mandatory.urigen.factoryID
: the ID of the factory to useplugins.mandatory.urigen.configType
: the type of configuration used
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:
stServiceContext
: contextual information for the current requestxRole
: the "extended role" of the resource being created (which may determine the "shape" of the generated URI)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:
concept
(forskos:Concept
s)label
(optional): the accompanying preferred label of the skos:Conceptscheme
(optional): the concept scheme to which the concept is being attached at the moment of its creation
conceptScheme
(forskos:ConceptScheme
s)label
(optional): the accompaying preferred label of the skos:ConceptScheme
xLabel
(forskosxl:Label
s)lexicalForm
: the lexical form of the skosxl:LabellexicalizedResource
: the resource to which the skosxl:Label will be attached totype
: the property used for attaching the label
xNote
(for reifiedskos:note
s)value
: the content of the noteannotatedResource
: the resource being annotatedtype
: the property used for annotation
The parameters requested by additional xRole
s 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:
- complain only about the absence of absolutely required parameters
- handle unknown
xRole
s gracefully, by means of some fallback strategy
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:
plugins.mandatory.rendering.factoryID
: the ID of the factory to useplugins.mandatory.rendering.configType
: the type of configuration used
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:
resourcePosition
: the position of the resource being shown in the resource view (either a local project, a remote repository or unknown)resourceToBeRendered
: the resource being shown in the resource viewvarPrefix
: a prefix for the names of internal variables used to compose the graph pattern
?resource
: the resource being shown in the resource view?object
: one of the property values for the subject resource
After the evaluation of the overall SPARQL query, it is possible to invoke the method render
, which has the following parameters:
project
: the current projectsubjectPosition
: the position of the resource being shown in the resource view (either a local project, a remote repository or unknown)subject
: the resource being shown in the resource viewstatements
: a model containing all the triples about the subject resource (inferred triples are stored explicitly in the graph namedhttp://semanticturkey/inference-graph
)resources
: the resources to be rendered (usually the subject resource and a subset of its property objects)bindings
: is a collection of bindings produced by the overall query including the graph pattern of the rendering enginevarPrefix
: is the prefix that was used to avoid clashes with variables outside the graph pattern of the rendering engine
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.