Team:Freiburg Software/Developer/Guide

From 2010.igem.org

(Difference between revisions)
Line 29: Line 29:
Create a public constructor in your robots servlet class with the following content:</p>
Create a public constructor in your robots servlet class with the following content:</p>
-
<div class="box_code">
+
<pre class="box_code"><span style="font-family: Consolas, Monaco, 'Courier New', Courier, monospace; line-height: 18px; font-size: 12px; white-space: pre;">public YourRobot() {
-
<pre><span style="font-family: Consolas, Monaco, 'Courier New', Courier, monospace; line-height: 18px; font-size: 12px; white-space: pre;">public YourRobot() {
+
   String verificationToken = "<em>VERIFICATION_TOKEN</em>";
   String verificationToken = "<em>VERIFICATION_TOKEN</em>";
</span><span style="font-family: Consolas, Monaco, 'Courier New', Courier, monospace; line-height: 18px; font-size: 12px; white-space: pre;">  String securityToken = "<em>SECURITY_TOKEN</em>";
</span><span style="font-family: Consolas, Monaco, 'Courier New', Courier, monospace; line-height: 18px; font-size: 12px; white-space: pre;">  String securityToken = "<em>SECURITY_TOKEN</em>";
</span><span style="font-family: Consolas, Monaco, 'Courier New', Courier, monospace; line-height: 18px; font-size: 12px; white-space: pre;">  super.setupVerificationToken(verificationToken, securityToken);
</span><span style="font-family: Consolas, Monaco, 'Courier New', Courier, monospace; line-height: 18px; font-size: 12px; white-space: pre;">  super.setupVerificationToken(verificationToken, securityToken);
-
</span><span style="font-family: Consolas, Monaco, 'Courier New', Courier, monospace; line-height: 18px; font-size: 12px; white-space: pre;">}</span></pre></div>
+
</span><span style="font-family: Consolas, Monaco, 'Courier New', Courier, monospace; line-height: 18px; font-size: 12px; white-space: pre;">}</span></pre>
<p class="main">
<p class="main">
Upload your robot to AppEngine and go back to the browser tab. Press the "verify"-button and you will be presented with your robots OAuth login information ( "<em>Consumer Key</em>" and "<em>Consumer Secret</em>" ).
Upload your robot to AppEngine and go back to the browser tab. Press the "verify"-button and you will be presented with your robots OAuth login information ( "<em>Consumer Key</em>" and "<em>Consumer Secret</em>" ).
Line 55: Line 54:
Change</p>
Change</p>
-
<pre>public class RobotServlet extends AbstractRobot {</pre>
+
<pre class="box_code">public class RobotServlet extends AbstractRobot {</pre>
<p class="main">to</p>
<p class="main">to</p>
-
<pre>public class RobotServlet extends AbstractSynBioWaveRobot {</pre>
+
<pre class="box_code">public class RobotServlet extends AbstractSynBioWaveRobot {</pre>
<p class="main">SynBioWave needs to be called by the onGadgetStateChanged and onWaveletSelfAdded-event, so add the lines</p>
<p class="main">SynBioWave needs to be called by the onGadgetStateChanged and onWaveletSelfAdded-event, so add the lines</p>
-
<pre>@Override
+
<pre class="box_code">@Override
public void onGadgetStateChanged(GadgetStateChangedEvent event){
public void onGadgetStateChanged(GadgetStateChangedEvent event){
   super.onSynBioWaveGadgetChanged(event);
   super.onSynBioWaveGadgetChanged(event);
Line 72: Line 71:
Furthermore, you need a function to extend SynBioWave's user interface, so add:</p>
Furthermore, you need a function to extend SynBioWave's user interface, so add:</p>
-
<pre>@Override
+
<pre class="box_code">@Override
public void createMenu(MenuItem menu, MenuItemFactory mif, Event event) throws Exception {
public void createMenu(MenuItem menu, MenuItemFactory mif, Event event) throws Exception {
}</pre>
}</pre>
<p class="main">
<p class="main">
The last thing to do is to import the required classes:</p>
The last thing to do is to import the required classes:</p>
-
<pre>import org.synbiowave.AbstractSynBioWaveRobot;
+
<pre class="box_code">import org.synbiowave.AbstractSynBioWaveRobot;
import org.synbiowave.menu.MenuItem;
import org.synbiowave.menu.MenuItem;
import org.synbiowave.menu.MenuItemFactory;</pre>
import org.synbiowave.menu.MenuItemFactory;</pre>
Line 85: Line 84:
<p class="main">
<p class="main">
To add an item to the SynBioWave menu bar, you can create the item using the <code>MenuItemFactory</code> you got as parameter in the <code>createMenu</code> function:</p>
To add an item to the SynBioWave menu bar, you can create the item using the <code>MenuItemFactory</code> you got as parameter in the <code>createMenu</code> function:</p>
-
<pre>MenuItem hello = mif.createButton("Hello World");</pre>
+
<pre class="box_code">MenuItem hello = mif.createButton("Hello World");</pre>
<p class="main">
<p class="main">
Where "Hello World" is the label of the button.
Where "Hello World" is the label of the button.
This button is added to the toolbar by adding it to the given</p>
This button is added to the toolbar by adding it to the given</p>
-
<pre>MenuItem menu</pre>
+
<pre class="box_code">MenuItem menu</pre>
<p class="main">(which repesents the menu-toolbar) as a subitem:</p>
<p class="main">(which repesents the menu-toolbar) as a subitem:</p>
-
<pre>menu.appendSubItem(hello);</pre>
+
<pre class="box_code">menu.appendSubItem(hello);</pre>
<p class="main">The whole function should now look like</p>
<p class="main">The whole function should now look like</p>
-
<pre>public void createMenu(MenuItem menu, MenuItemFactory mif) throws Exception {
+
<pre class="box_code">public void createMenu(MenuItem menu, MenuItemFactory mif) throws Exception {
MenuItem hello = mif.createButton("Hello World");
MenuItem hello = mif.createButton("Hello World");
menu.appendSubItem(hello);
menu.appendSubItem(hello);
Line 104: Line 103:
First, you need to create a new class (in this example named Callback.java) extending MenuCallBack:</p>
First, you need to create a new class (in this example named Callback.java) extending MenuCallBack:</p>
-
<pre>public final class BlastCallback extends MenuCallBack {
+
<pre class="box_code">public final class BlastCallback extends MenuCallBack {
public void onButtonClicked(Event event, MenuItem menuItem,
public void onButtonClicked(Event event, MenuItem menuItem,
AbstractSynBioWaveRobot servlet) {}
AbstractSynBioWaveRobot servlet) {}
Line 110: Line 109:
<p class="main">
<p class="main">
The function onButtonClicked is called when the corresponding button is pressed. As you get an event, you can do everything you could do on "normal" wave events, for example add an new blip to the wave:</p>
The function onButtonClicked is called when the corresponding button is pressed. As you get an event, you can do everything you could do on "normal" wave events, for example add an new blip to the wave:</p>
-
<pre>public final class BlastCallback extends MenuCallBack {
+
<pre class="box_code">public final class BlastCallback extends MenuCallBack {
public void onButtonClicked(Event event, MenuItem menuItem,
public void onButtonClicked(Event event, MenuItem menuItem,
AbstractSynBioWaveRobot servlet) {
AbstractSynBioWaveRobot servlet) {
Line 118: Line 117:
<p class="main">
<p class="main">
Now that you completed the callback, you need to connect it with the button you created before. Go back to the main servlet and add</p>
Now that you completed the callback, you need to connect it with the button you created before. Go back to the main servlet and add</p>
-
<pre>this.connectMenuCallBack(hello, new Callback());</pre>
+
<pre class="box_code">this.connectMenuCallBack(hello, new Callback());</pre>
<p class="main">inside of the createMenu function (again import your Callback class of course):</p>
<p class="main">inside of the createMenu function (again import your Callback class of course):</p>
-
<pre>public void createMenu(MenuItem menu, MenuItemFactory mif) throws Exception {
+
<pre class="box_code">public void createMenu(MenuItem menu, MenuItemFactory mif) throws Exception {
MenuItem hello = mif.createButton("Hello World");
MenuItem hello = mif.createButton("Hello World");
menu.appendSubItem(hello);
menu.appendSubItem(hello);
Line 132: Line 131:
<h3>Create a new sequence</h3>
<h3>Create a new sequence</h3>
<p class="main">Nothing easier like this:</p>
<p class="main">Nothing easier like this:</p>
-
<pre><span style="font-family: Consolas, Monaco, 'Courier New', Courier, monospace; line-height: 18px; font-size: 12px; white-space: pre;">Sequence sequence=new Sequence("<em>Name</em>","<em>Sequence</em>");
+
<pre class="box_code"><span style="font-family: Consolas, Monaco, 'Courier New', Courier, monospace; line-height: 18px; font-size: 12px; white-space: pre;">Sequence sequence=new Sequence("<em>Name</em>","<em>Sequence</em>");
sequence.setAuthor("<em>Author</em>");
sequence.setAuthor("<em>Author</em>");
sequence.addAnnotation("<em>Feature Name</em>",1,15);
sequence.addAnnotation("<em>Feature Name</em>",1,15);
Line 143: Line 142:
<p class="main">
<p class="main">
Again, very easy:</p>
Again, very easy:</p>
-
<pre><span style="font-family: Consolas, Monaco, 'Courier New', Courier, monospace; line-height: 18px; font-size: 12px; white-space: pre;">List&lt;Sequence&gt; sequences=Workspace.getActiveSequences(servlet,event.getWavelet());
+
<pre class="box_code"><span style="font-family: Consolas, Monaco, 'Courier New', Courier, monospace; line-height: 18px; font-size: 12px; white-space: pre;">List&lt;Sequence&gt; sequences=Workspace.getActiveSequences(servlet,event.getWavelet());
if(sequences!=null){
if(sequences!=null){
   for(Sequence sequence:sequences){
   for(Sequence sequence:sequences){

Revision as of 17:41, 24 October 2010

Developer Guide

One main goal of SynBioWave is extendability. If you are missing some functionality using SynBioWave, you can create your own robot implementing it.

1. Basic setup

A SynBioWave-Robot is an extended Wave-Robot. So first, you need to create a normal Wave-Robot following the steps described in the Google Robot Tutorial. Reading is highly recommended, since this forms the basis for our robots. We have put a lot of effort in extending Wave-Robot programming to include robot-robot communication and the use of a common pull-down menu structure.
Following the Google Robot Tutorial, you should get a servlet class in the src/ directory, some jar's under war/WEB-INF/lib and configured war/WEB-INF/appengine-web.xml and war/WEB-INF/web.xml files. We now need to further extend this layout to add the SynBioWave-functionality:

Add the jar files used by SynBioWave

Download biojava.jar from http://biojava.org/wiki/BioJava:Download and the latest latest version of synbiowave.jar from http://sourceforge.net/projects/synbiowave/ (or this wiki)) to your war/WEB-INF/lib folder and add these libraries to your project as you did before.

Add the OAuth login for the Active API

First register your robot on Google's robot registration page. After submitting the form, you will receive a "Verification Token" and a "Security Token". At the end of the received text, you see a "verify" - button. Keep the browser tab open, as you will need this a little later. Create a public constructor in your robots servlet class with the following content:

public YourRobot() {
  String verificationToken = "VERIFICATION_TOKEN";
  String securityToken = "SECURITY_TOKEN";
  super.setupVerificationToken(verificationToken, securityToken);
}

Upload your robot to AppEngine and go back to the browser tab. Press the "verify"-button and you will be presented with your robots OAuth login information ( "Consumer Key" and "Consumer Secret" ). Now change the basic contructor of your robot such that it looks like the following:

public YourRobot() {
  super.setupOAuth("Consumer Key","Consumer Secret","http://gmodules.com/api/rpc");
  super.setupOAuth("Consumer Key","Consumer Secret","http://sandbox.gmodules.com/api/rpc");
  super.setAllowUnsignedRequests(true);
}

Now your robot is ready for the use of the Active API, both in the preview and the sandbox client. This is required for the use of the SynBioWave API, especially for the use of the sequence workspace. For further information please have a look on the official Active API page.

Extend the servlet

Now open the main servlet, and let your main class extend the AbstractSynBioWaveRobot class instead of the normal AbstractRobot class: Change

public class RobotServlet extends AbstractRobot {

to

public class RobotServlet extends AbstractSynBioWaveRobot {

SynBioWave needs to be called by the onGadgetStateChanged and onWaveletSelfAdded-event, so add the lines

@Override
public void onGadgetStateChanged(GadgetStateChangedEvent event){
   super.onSynBioWaveGadgetChanged(event);
}

@Override
public void onWaveletSelfAdded(WaveletSelfAddedEvent event) {
   super.onSynBioWaveRobotSelfAdded(event);
}

It is important that the super.onSynBioWaveRobotSelfAdded() and super.onSynBioWaveGadgetChanged() functions are called. Of course you can add code to these events (best after the existing function) and/or register other wave-events as well. Furthermore, you need a function to extend SynBioWave's user interface, so add:

@Override
public void createMenu(MenuItem menu, MenuItemFactory mif, Event event) throws Exception {
}

The last thing to do is to import the required classes:

import org.synbiowave.AbstractSynBioWaveRobot;
import org.synbiowave.menu.MenuItem;
import org.synbiowave.menu.MenuItemFactory;

This completes the basic layout. You can compare your file with our blueprint robot.

2. Creating menu items

To add an item to the SynBioWave menu bar, you can create the item using the MenuItemFactory you got as parameter in the createMenu function:

MenuItem hello = mif.createButton("Hello World");

Where "Hello World" is the label of the button. This button is added to the toolbar by adding it to the given

MenuItem menu

(which repesents the menu-toolbar) as a subitem:

menu.appendSubItem(hello);

The whole function should now look like

public void createMenu(MenuItem menu, MenuItemFactory mif) throws Exception {
	MenuItem hello = mif.createButton("Hello World");
	menu.appendSubItem(hello);
}

Now, it's a good time to deploy the robot to AppEngine, create a new Wave, add the SynBioWave-Robot, add your robot to the wave and watch the new "Hello World"-button appear.

3. Add functionality to menu items

At the moment, the button doesn't do anything when clicked. SynBioWave uses callbacks to react on menu events. First, you need to create a new class (in this example named Callback.java) extending MenuCallBack:

public final class BlastCallback extends MenuCallBack {
	public void onButtonClicked(Event event, MenuItem menuItem,
				 AbstractSynBioWaveRobot servlet) {}
}

The function onButtonClicked is called when the corresponding button is pressed. As you get an event, you can do everything you could do on "normal" wave events, for example add an new blip to the wave:

public final class BlastCallback extends MenuCallBack {
	public void onButtonClicked(Event event, MenuItem menuItem,
				 AbstractSynBioWaveRobot servlet) {
		event.getBlip().reply().append("Button pressed\n");
	}
}

Now that you completed the callback, you need to connect it with the button you created before. Go back to the main servlet and add

this.connectMenuCallBack(hello, new Callback());

inside of the createMenu function (again import your Callback class of course):

public void createMenu(MenuItem menu, MenuItemFactory mif) throws Exception {
	MenuItem hello = mif.createButton("Hello World");
	menu.appendSubItem(hello);
	this.connectMenuCallBack(hello, new callback());
}

Now your robot should add a reply with "Button pressed" to the root-blip of the wave, which contains the menu and therefore is referred to as active blip in the "event" event.

4. Create and receive sequences

This chapter will give you a brief introduction in SynBioWave's internal sequence usage.

Create a new sequence

Nothing easier like this:

Sequence sequence=new Sequence("Name","Sequence");
sequence.setAuthor("Author");
sequence.addAnnotation("Feature Name",1,15);
sequence.publish(robot,wavelet,true);

With the publish() method of your created sequence class, you add the sequence to the workspace. The boolean parameter of the publish() method sets the initial active state of the sequence in the workspace. You can work on this sequence and change the values as needed. The changes will be presented in the workspace as soon as you use the publish() function again.

Receiving sequences from the workspace

Again, very easy:

List<Sequence> sequences=Workspace.getActiveSequences(servlet,event.getWavelet());
if(sequences!=null){
  for(Sequence sequence:sequences){
    //do everything you want with the sequences
    //remember that you have to use the publish()
    //function of the sequence to update the
    //sequence changes in the workspace
  }
}

For further information, please have a look at our SynBioWave API doc (http://www.synbiowave.org/docu/api/).