Tuesday, December 12, 2006

gwt open source

wow! I wait for that.

Lazy loading FCKeditor in GWT application

Principle is On-demand script. My sample utils (not tested!) class for create FCKeditor when is neaded. This class is used in google GWT application, and it is not tested but show principle.
package net.ct.sajt.client.ui;
import java.util.ArrayList;
import java.util.List;
import net.ct.sajt.client.Log;

import com.google.gwt.user.client.Random;

import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.HTML;


/**
 * Sampl class for load FCK editor.
 * Usage: 
 * 
 *  ... new HTML("<textarea id="\te\" name="\te\" textarea>..."); 
 * FCKEditorUtil.createScript("http://localhost:8080/web/js/FCKeditor/fckeditor.js", "34534", true);
 * final Timer timer = new Timer() {
 *   public void run() {
 *    if(FCKEditorNews.show()) { // while browser load script
 *     cancel();
 *     return;
 *    }            
 *   }   
 * }; 
 * timer.scheduleRepeating(100);
 */
public class FCKEditorUtil {

/**
  * Return html content from texarea.

  * 
  * @param editorInstance
  *            name of FCKEditor instance.
  * @return html content
  */
public static native String getContent(String editorInstance) /*-{  

  return $wnd.FCKeditorAPI.GetInstance(editorInstance).GetXHTML();
 }-*/;

/**
  * Show editor if is loaded and return true, otherwise false.
  */
private static native boolean show() /*-{

  if($wnd.FCKeditor) {
   var oFCKeditor = new $wnd.FCKeditor( 'te' ) ;
   oFCKeditor.BasePath = "http://localhost:8080/web/js/FCKeditor/" ;
   oFCKeditor.ToolbarSet = 'Basic';
   oFCKeditor.Config["CustomConfigurationsPath"] = "http://localhost:8080/web/js/FCKeditor/news_config.js?" + ( new Date() * 1 ) ;  // not cache while develop        
   oFCKeditor.ReplaceTextarea() ;
   $wnd.oFCKeditor = oFCKeditor;
   return true;
  }else {
   return false;
  }

 }-*/;

// contein script urls for prevent that not two same JS script load twice.
private static List cacheScript = new ArrayList();



/**
  * Create < script src=.... > if not exist alredy. 
  * @param src javascript url
  * @param id any ID for <script id=...
  */
public static void createScript(String src, String id) {

if (cacheScript.contains(src)) {
return;

}
createSrc(src, id);
cacheScript.add(src);

}



private static native void createSrc(String src, String id) /*-{   

   var head = $doc.getElementsByTagName("head")[0];
   var  script = $doc.createElement('script');    
   script.id = id;
   script.type = 'text/javascript';
   script.src = src;
  
   //Indicates that the script is not going to generate any document content. The browser can continue parsing and drawing the page  
   //script.defer = true;
   head.appendChild(script);       
  }-*/;

/**

  * Create <script></script> tag.
  * 
  * @param src javascript url
  * @param id
  * @param noCache if true than add random number to end of script (e.g. src + "?234534" )
  * because browser cache javascipt.
  */
public static void createScript(String src, String id, boolean noCache) {

if (noCache) {
createSrc(src + "?" + Random.nextInt(), id);

}

}
} 
 
 
 
SemGen 

Monday, December 11, 2006

How to access NCBI blast using java?

Part I.
NCBI Blast can be searched in two ways: using the web form available at their home page or by making our own custom interface.
In this tutorial we will concentrate on the second approach, so we will implement http access, by using NCBI’s URL API.
“The URL API is a standardized application program interface (API) for accessing the NCBI $QBl_{A}st$ system. It uses direct HTTP-encoded requests to NCBI web server.”
In order to implement this access we must have the following prerequisite libraries available for use:
Jakarta Commons HttpClient
Castor
The quick outline of the steps required is as follows:
First we query the NCBI blast query, after which we receive a reply containing the number of seconds left for processing this request, or an error message if the query was malformed.
After that wait period is expired, we again query the server for the status of our request, and if the reply is positive we proceed to the final request results. Otherwise we wait for the request to complete, and then proceed.
Basically, our program emulates a browser accessing blast via ordinary web form.
More accurately, our program creates HTTP GET query string , and sends a query to the
http://www.ncbi.nlm.nih.gov/blast/Blast.cgi.
For every URL , query must specify CMD value which indicates that we are sending a query (CMD=Put) , or we are requesting the query results (CMD=Get).
There are also other CMD values (INFO and WEB), but we wont look at them now, as they are not essential for our access interface.
In addition to the CMD=Put command, we also need to select a database using a DATABASE variable (e.g. DATABASE=nr), then specify a sequence using QUERY
(e.g. QUERY=SSWWAHVEMGPPDPILGVTEAY) and select a PROGRAM using
PROGRAM variable (e.g. PROGRAM=blastp).
Other values are not mandatory, and if not specified, the defaults will be used.
Jakarta Commons HttpClient library contains a class for constructing queries:
UrlQuery putQuery = new UrlQuery();
putQuery.setNameValue("CMD", "Put");
putQuery.setNameValue("DATABASE", "nr");
putQuery.setNameValue("QUERY", "SSWWAHVEMGPPDPILGVTEAY");
putQuery.setNameValue("PROGRAM", "blastp");
After query has been specified, we continue with:
HttpClient http = new HttpClient();
GetMethod getMethod = new GetMethod("http://www.ncbi.nlm.nih.gov/blast/Blast.cgi")
getMethod.setQueryString(putQuery);
And finally, we send the request:
int statusCode = http.executeMethod(getMethod);
Then we check for the results using:
if (statusCode != HttpStatus.SC_OK)
If all goes ok, then we extract the result to String:
InputStreamReader inputStream = new InputStreamReader(
getMethod.getResponseBodyAsStream(),
getMethod.getResponseCharSet());
BufferedReader buffer = new BufferedReader(inputStream);
StringBuilder resultBuffer = new StringBuilder(2048);
String line;
while ((line = buffer.readLine()) != null) {
result.append(line);
}
Strigin result = resultBuffer.toString();
It is also important to close all opened connections:
getMethod.releaseConnection();
inputStream.close();
The result contains HTML, and it is not the final data-set we are trying to retrieve.
NCBI returned two values commented in the HTML code, the rest we ignore:
<!-- QBlastInfoBegin
RID = 954517067-8610-1647
RTOE = 207
QBlastInfoEnd
-->
RID (Request Identifier) Value is something similar to a sessionID, which lasts for 24h
That is the number we will return to NCBI when we request the result, and
RTOE (Request Time of Execution ) is time of seconds to wait until NCBI has finished processing our request. Now we need to extract RID and RTOE values.
We will do that using regular expressions:
public static final String RTOE_RID_PATTERN =
"<!--\\s*QBlastInfoBegin\\s*RID = (.*)\\s*RTOE = (.*)\\s*QBlastInfoEnd\\s*-->";
Pattern pattern = Pattern.compile(RTOE_RID_PATTERN);
Matcher matcher = pattern.matcher(result);
String resultRID;
String resultRTOE;
if (matcher.find()) {
if (matcher.groupCount() != 2) {
return false;
}
}
resultRID = matcher.group(1);
resultRTOE = matcher.group(2);
Now that we know how much longer we need to wait, we call:
long sleepMillis = TimeUnit.SECONDS.toMillis((long) resultRTOE);
Thread.sleep(sleepMillis);
After waiting we are making another query to check if our request has been processed:
UrlQuery getQuery = new UrlQuery();
getQuery.setNameValue("RID", rid);
getQuery.setNameValue("CMD", "GET");
After which we get another HTML code containing something like this:
Now we need to retrieve the Status value which can be either WAITING, READY, UNKNOWN or ERROR.
WAITING - we need to wait a few more seconds
READY - request has been processed
UNKNOWN - request has been lost
ERROR - our request was malformed, we made an error during issuing our request
If we got Status=WAITING, then we will wait for couple of more seconds, and resend the query, and if the Status=READY we can create a query for retrieving the final result data in a form of an XML document.
To be continued in part II of this tutorial.