We have tried to support a certain degree of extensibility for iServe by providing a plugin mechanism. This mechanism is currently available for 3rd party developers to provide their own import mechanisms for new formats, as well as for including new matching algorithms. The plugin mechanism is based on Java's ServiceLoader combined with Guice to support the automated detection and use of plugin implementations at runtime, and can therefore be exploited simply by dropping a new jar in the classpath.
Matchers are provided in iServe by means of the very same plugin mechanism used for transformation plugins. In this case however the interface that needs to be implemented is one of the uk.ac.open.kmi.iserve.discovery.api.Matcher extensions, e.g., ConceptMatcher. The Guice module to implement in this case is uk.ac.open.kmi.iserve.discovery.api.MatcherPluginModule.
For the case of Matcher plugins, iServe will choose them at runtime on the basis of their class name, and should thus be registered indexed by that. Below you have a complete example of a Guice module.
public class DiscoMatchersPlugin extends ConfiguredModule implements MatcherPluginModule { @Override protected void configure() { // Ensure we configure it super.configure(); MapBinder<String, ConceptMatcher> conceptBinder = MapBinder.newMapBinder(binder(), String.class, ConceptMatcher.class); conceptBinder.addBinding(SparqlLogicConceptMatcher.class.getName()).to(SparqlLogicConceptMatcher.class).in(Singleton.class); } }
Like for import plugins, it is necessary to include the file for enabling Java's ServiceLoader to detect the implementation at runtime. In this case, the file to provide is META-INF/services/uk.ac.open.kmi.iserve.discovery.api.MatcherPluginModule. The content of the file should just include a line with the complete name of your plugin implementation, eg., :
uk.ac.open.kmi.iserve.discovery.disco.impl.DiscoMatchersPlugin
Maven developers can automated this last step by including the following in the plugin's POM file:
<!-- Generate the META-INF/services information for ServiceLoader --> <plugin> <groupId>eu.somatik.serviceloader-maven-plugin</groupId> <artifactId>serviceloader-maven-plugin</artifactId> <version>1.0.2</version> <configuration> <services> <param>uk.ac.open.kmi.iserve.discovery.api.MatcherPluginModule</param> </services> </configuration> <executions> <execution> <goals> <goal>generate</goal> </goals> </execution> </executions> </plugin>
Given that we use Guice and its multibinding extension for the plugin mechanism, these are also dependencies for your plugin.
Maven users can include the necessary dependencies by including the following:
<dependency> <groupId>uk.ac.open.kmi.iserve.discovery</groupId> <artifactId>iserve-discovery-api</artifactId> <version>${project.version}</version> </dependency> <!--Add Guice for dependency injection --> <dependency> <groupId>com.google.inject</groupId> <artifactId>guice</artifactId> <version>${guice.version}</version> </dependency> <dependency> <groupId>com.google.inject.extensions</groupId> <artifactId>guice-multibindings</artifactId> <version>${guice.version}</version> </dependency>
Should you wish to ensure that the plugin mechanism works and picks up properly your implementation, you can simply try to obtain and use your Matcher by means of the uk.ac.open.kmi.iserve.api.MatchersFactory. Below you have an example on how this can be done.
// Create an engine iServeEngine engine = iServeEngineFactory.createEngine(); // Create a specific matcher ConceptMatcher matcher = engine.getConceptMatcher(SomeConceptMatcherImplementation.class.getName());