-
Notifications
You must be signed in to change notification settings - Fork 0
2.3 Create Classifier (Java)
This tutorial explains how to create a fully Knowing compatible classifier with the java API and Eclipse IDE. First of all configure Knowing as explained in Knowing-Launch.
Create an new Eclipse Plug-in Project with following options
- No contributions to the UI
- Activator yes
NOTE: When the Java API is finished, this step will be unnecessary Right-click on the project->configure->Add Scala nature
Open META-INF/MANIFEST.MF and open tab dependecies
- Add de.lmu.ifi.dbs.knowing.core as required Plugin-in.
- Remove _org.scala-ide.library.2.9.0
- Add imported packages -> NONE
Optional
Eclipse automatically adds org.eclipse.core.runtime as dependency. If you want to use another OSGi runtime, remove org.eclipse.core.runtime from required bundles and add org.osgi.framework to imported packages as shown here:
Currently we use the WEKA API as Java API. So you have to implement weka.classifiers.Classifier to create a classifier. WEKA offers an AbstractClassifier class with some default implementations. For furtherinformation on that, please consult WEKA Homepage. Knowing uses WEKA 3.7.3.
Every node in a dpu is created via a factory, so you have to provide a factory for you classifier, which configures and creates the classifier. This factory is registered as an OSGi-Service.
NOTE: Currently there is no Java API for this purpose!
Create a new Scala class MyClassifierFactory and extend de.lmu.ifi.dbs.knowing.core.weka.WekaClassifierFactory . Scala IDE doesn't correctly create the class. Here is an example how it should (could) look like:
package com.example.knowing
import java.util.Properties
import scala.collection.immutable.Map
import akka.actor.Actor
import de.lmu.ifi.dbs.knowing.core.factory._
import de.lmu.ifi.dbs.knowing.core.factory.TFactory._
import de.lmu.ifi.dbs.knowing.core.weka.{WekaClassifier, WekaClassifierFactory }
import de.lmu.ifi.dbs.knowing.core.weka.WekaClassifierFactory._
class MyFactory extends WekaClassifierFactory[MyClassifierWrapper, MyClassifier]
(classOf[MyClassifierWrapper], classOf[MyClassifier]) {
//Creates default Properties which are used if properties aren't set
override def createDefaultProperties: Properties = {
val returns = new Properties
returns.setProperty(DEBUG, "false")
returns
}
//Possible property values. Editor should show these
override def createPropertyValues: Map[String, Array[_<:Any]] = {
Map(DEBUG -> boolean_property)
}
//Property description
override def createPropertyDescription: Map[String, String] = {
Map(DEBUG -> "Debug true/false")
}
}
The tricky part is the constructor. In the first brackets [...] there are two generics. The first one is the original WEKA Classifier and the second one is the WEKA Classifier Wrapper, which we will created next. The following constructor parameters (...) are the two classes for WEKA Classifier and WEKA Classifier Wrapper.
MyClassifier has only one option to set, the DEBUG option, which is a standard value imported from WekaClassifierFactory.
In the same class you add this piece of code
class MyClassifierWrapper extends WekaClassifier(new MyClassifier()) {
override def configure(properties:Properties) = {
//Configure your classifier here with
val myClassifier = classifier.asInstanceOf[MyClassifier]
val debug = properties.getProperty(DEBUG)
myClassifier.setDebug(debug.toBoolean)
}
}
This class takes an Instance of your WEKA Classifier as constructor parameter and manages the rest. In this example we override the configure method to set the classifier options based on the given properties.
Last but not least we have to register MyFactory as an OSGi service. Open your Activator.java and add the following line of code into the start method
myFactory = context.registerService(TFactory.class.getName(), new MyFactory(), null);
Your Activator should look like this.
package com.example.knowing;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import de.lmu.ifi.dbs.knowing.core.factory.TFactory;
public class Activator implements BundleActivator {
private static BundleContext context;
static BundleContext getContext() {
return context;
}
private ServiceRegistration myFactory;
/*
* (non-Javadoc)
* @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
*/
public void start(BundleContext bundleContext) throws Exception {
Activator.context = bundleContext;
myFactory = context.registerService(TFactory.class.getName(), new MyFactory(), null);
}
/*
* (non-Javadoc)
* @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
*/
public void stop(BundleContext bundleContext) throws Exception {
myFactory.unregister();
Activator.context = null;
}
}
Make sure that your plugin gets started at the beginning so the service is registered. You can use declarative services as well if you want. The id of MyClassifier is com.example.knowing.MyClassifier if you use it in a DPU.