Web API for Biology (WABI) では 生物分野における様々な Web API を公開しています。 Web API を使用することにより、いくつものデータベースや解析結果に簡単にアクセスすることができます。 本チュートリアルでは、RESTを使用する方法を紹介します。

  1. どんなサービスを公開しているのか
  2. どうやって REST にアクセスするのか
    2. 1 Perlを用いる場合
    2. 2 Javaを用いる場合
    2. 3 C を用いる場合
    2. 4 Rubyを用いる場合
    2. 5 Pythonを用いる場合
    2. 6 C# を用いる場合
  3. 複数行のクエリーを扱うには
  4. 英数字以外が含まれる情報を扱うには
  5. 非同期にメソッドを実行するには
  6. プロキシサーバーを使用してアクセスするには
  7. ワークフローの作成
    7. 1 Perlを用いる場合
    7. 2 Javaを用いる場合
  8. REST と SOAP

1. どんなサービスを提供しているのか

トップページの「利用可能なサービス」にサービスの一覧があります。 各サービスの詳細はリンクをクリックすることにより確認できます。

2. どうやって REST にアクセスするのか

RESTを使用するには、ウェブブラウザは元より、PerlやJavaのようなプログラミング言語からもご利用いただけます。 本システムにアクセスするには、 REST用URL [http://xml.nig.ac.jp/rest/Invoke] に以下を与える必要があります。
service:サービス名(必須)
method:メソッド名(必須)
各メソッド毎のパラメータ
本システムは、POSTでアクセスすることを推奨しておりますが、 GETの限界を超えるような情報量を持つパラメーターを指定しなければ、GET を用いたアクセスも可能です。
http://xml.nig.ac.jp/rest/Invoke?service=ServiceName&method=MethodName&param.....
ご不明な点やご提案などがありましたらこちらまでご連絡ください。

2.1 Perl を用いる場合

Active Perl のインストール方法はこちらをご覧ください。: for Unix for Windows

DDBJ エントリ1件を取得する方法を例に説明します。エントリを取得する為にはアクセッション番号を指定します。
本例では、GetEntrygetDDBJEntry を使用し、 LWP を用いた方法と、Socket を用いた方法を紹介します。

LWPを用いた方法

use LWP::UserAgent;
$ua = new LWP::UserAgent;

# make request
$req = new HTTP::Request POST => "http://xml.nig.ac.jp/rest/Invoke";
$req->content_type("application/x-www-form-urlencoded");
# set parameters
$req->content("service=GetEntry&method=getDDBJEntry&accession=AB000100");

# send request and get response.
$res = $ua->request($req);
# If you want to get a large result. It is better to write to a file directly.
# $res = $ua->request($req,"file_name.txt");
# If your request needs long time to execute, please set timeout as follows.
# $ua->timeout(3600); (1 hour.)

# show response.
print $res->content;
Socket を用いた方法
use Socket;
use FileHandle;

# set hostname
$con_host = "xml.nig.ac.jp";
#set port number.
$con_port = 80;
#set service location
$path = "/rest/Invoke";
#set parameter.
$query = "service=GetEntry&method=getDDBJEntry&accession=AB000100";

$len = length($query);

# make socket
$ip = inet_aton($con_host) || die "host($con_host) not found.\n";
$sockaddr = pack_sockaddr_in($con_port, $ip);
socket(SOCKET, PF_INET, SOCK_STREAM, 0) || die "socket error.\n";

# make connection
connect(SOCKET, $sockaddr) || die "connect $con_host $con_port error.\n";
autoflush SOCKET (1);

# send http request.
print SOCKET "POST $path HTTP/1.0\n";
print SOCKET "User-Agent: perl/socket\n";
print SOCKET "Content-Type: application/x-www-form-urlencoded\n";
print SOCKET "Content-Length: $len\n\n";
print SOCKET $query."\n";

# show response.
while (chomp($buf=<SOCKET>)) {
  print "$buf\n";
}

# socket close
close(SOCKET);

2.2 Java を用いる場合

DDBJ エントリ1件を取得する方法を例に説明します。エントリを取得する為にはアクセッション番号を指定します。
本例では、GetEntrygetDDBJEntry を使用し、 Socket を用いた方法と、URLConnection を用いた方法を紹介します。

Socket を使用した場合
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.net.URL;
import java.net.URLConnection;

public class Rest {

	public static void main(String[] args) throws IOException {
		Socket socket = null;
		//set hostname
		String addr = "xml.nig.ac.jp";

		//set use port
		int port = 80;

		//set service path
		String path = "/rest/Invoke";
		//set parameter
		String query = "service=GetEntry&method=getDDBJEntry&accession=AB000100";

		//open socket
		socket = new Socket(addr, port);

		//send query
		BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
		PrintStream pw = new PrintStream(socket.getOutputStream());
		pw.print("POST " + path + " HTTP/1.0\n");
		pw.print("User-Agent: java/socket\n");
		pw.print("Content-Type: application/x-www-form-urlencoded\n");
		pw.print("Content-Length:" + query.length() + "\n\n");
		pw.print(query);

		//get result
		String l = null;
		while ((l=br.readLine())!=null) {
			System.out.println(l);
		}
		pw.close();
		br.close();
	}
}

URLConnection を使用した場合
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.net.URL;
import java.net.URLConnection;

public class Rest {

	public static void main(String[] args) throws IOException {

		//set URL
		URL url = new URL("http://xml.nig.ac.jp/rest/Invoke");

		//set parameter
		String query = "service=GetEntry&method=getDDBJEntry&accession=AB000100";

		//make connection
		URLConnection urlc = url.openConnection();

		//use post mode
		urlc.setDoOutput(true);
		urlc.setAllowUserInteraction(false);

		//send query
		PrintStream ps = new PrintStream(urlc.getOutputStream());
		ps.print(query);
		ps.close();

		//get result
		BufferedReader br = new BufferedReader(new InputStreamReader(urlc
				.getInputStream()));
		String l = null;
		while ((l=br.readLine())!=null) {
			System.out.println(l);
		}
		br.close();
	}
}

ご不明な点やご提案などがありましたらこちらまでご連絡ください。

2.3 C を用いる場合

DDBJ エントリ1件を取得する方法を例に説明します。エントリを取得する為にはアクセッション番号を指定します。
本例では、GetEntrygetDDBJEntry を使用し、 Socket を用いた方法を紹介します。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/param.h>
#include <sys/uio.h>
#include <unistd.h>

#define BUF_LEN 256

int main(){
	int s;
	struct hostent *servhost;
	struct sockaddr_in server;
	struct servent *service;
	
	char send_buf[BUF_LEN];
	//host name
	char host[BUF_LEN] = "xml.nig.ac.jp";
	//path
	char path[BUF_LEN] = "/rest/Invoke";
	//port number
	unsigned short port = 80;
	char query[BUF_LEN] = "service=GetEntry&method=getDDBJEntry&accession=AB000100";
        
	//get IP adddres from host
	servhost = gethostbyname(host);
	bzero(&server, sizeof(server)); 

	server.sin_family = AF_INET;
	bcopy(servhost->h_addr, &server.sin_addr, servhost->h_length);
	server.sin_port = htons(port);

	//make socket
	s = socket(AF_INET, SOCK_STREAM, 0);

	//make connection
	connect(s, (struct sockaddr *)&server, sizeof(server));

	//send data
	sprintf(send_buf, "POST %s HTTP/1.0\n", path);
	write(s, send_buf, strlen(send_buf));

	sprintf(send_buf, "Host: %s:%d\n", host, port);
	write(s, send_buf, strlen(send_buf));

	sprintf(send_buf, "User-Agent: c/socket\n");
	write(s, send_buf, strlen(send_buf)); 

	sprintf(send_buf, "Content-Type: application/x-www-form-urlencoded\n");
	write(s, send_buf, strlen(send_buf));

	sprintf(send_buf, "Content-Length: %d \n\n", strlen(query));
	write(s, send_buf, strlen(send_buf));

	sprintf(send_buf, "%s", query);
	write(s, send_buf, strlen(send_buf));

	//get your result
	while (1){
	    char buf[BUF_LEN];
	    int read_size;
	    read_size = read(s, buf, BUF_LEN);
	    if ( read_size > 0 ){
	        write(1, buf, read_size);
	    } else {
	        break;
	    }
	}
	close(s);
	return 0;
}

2.4 Ruby を用いる場合

DDBJ エントリ1件を取得する方法を例に説明します。エントリを取得する為にはアクセッション番号を指定します。
本例では、GetEntrygetDDBJEntry を使用し、 Socket を用いた方法を紹介します。
require "socket"

#set hostname
host = "xml.nig.ac.jp"
#set port
port = "80"
#set pass
path = "/rest/Invoke"
#set query
query = "service=GetEntry&method=getDDBJEntry&accession=AB000100"

#make connection
socket = TCPSocket.open(host,port)

#send query
socket.write "POST "+ path + " HTTP/1.0\n"
socket.write "User-Agent: ruby/socket\n"
socket.write "Content-Type: application/x-www-form-urlencoded\n"
socket.write "Content-Length:" + query.size.to_s +  "\n\n"
socket.write query

#get result
while s=socket.gets
	print(s)
end
socket.close

ご不明な点やご提案などがありましたらこちらまでご連絡ください。

2.5 Python を用いる場合

DDBJ エントリ1件を取得する方法を例に説明します。エントリを取得する為にはアクセッション番号を指定します。
本例では、GetEntrygetDDBJEntry を使用し、 Socket を用いた方法を紹介します。
import socket

#set server
host = "xml.nig.ac.jp"
port =  80

#set API server
url = "/rest/Invoke"

#set parameter
query = "service=GetEntry&method=getDDBJEntry&accession=AB000200"

#make connection
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

try:
	sock.connect((host, port))
	sock.send("POST " + url + " HTTP/1.0\n")
	sock.send("Content-Type: application/x-www-form-urlencoded\n")
	sock.send("User-Agent: python/socket\n")
	sock.send("Content-Length:" + `len(query)` + "\n\n")
	sock.send(query)
except socket.error, e:
	print 'Error: %s' % e

while 1:
	rcvmsg = sock.recv(1024)
	print rcvmsg,
	if rcvmsg == '':
		break
sock.close

2.6 C# を用いる場合

DDBJ エントリ1件を取得する方法を例に説明します。エントリを取得する為にはアクセッション番号を指定します。
本例では、GetEntrygetDDBJEntry を使用し、 Socket を用いた方法を紹介します。
using System;
using System.Text;
using System.IO;
using System.Net;
using System.Net.Sockets;

public class GetEntryREST{
	public static void Main(string[] args) {
		/* specify host, url, port number and parameter */
		string host = "xml.nig.ac.jp";
		string url = "/rest/Invoke";
		int port = 80;
		string query = "service=GetEntry&method=getDDBJEntry&accession=AB000200";
		
		/* Retrieve IP from host name*/
		IPHostEntry hostEntry = Dns.GetHostEntry(host);
		IPAddress address = hostEntry.AddressList[0];

		IPEndPoint ipe = new IPEndPoint(address, port);
	
		/* Make connection*/
		Socket socket  = 
			new Socket(ipe.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
		socket.Connect(ipe);

		string request = "POST " + url + " HTTP/1.0\n";
		request += "User-Agent: C#/socket\n";
		request += "Content-Type: application/x-www-form-urlencoded\n";
		request += "Content-Length:" + query.Length + "\n\n";
		request += query;

		Byte[] bytesSent = Encoding.ASCII.GetBytes(request);
		Byte[] bytesReceived = new Byte[256];
		
		/*send query*/
		socket.Send(bytesSent, bytesSent.Length, 0);
		
		/* print result*/
		int bytes = 0;
		do{
			bytes = socket.Receive(bytesReceived, bytesReceived.Length, 0);
			Console.Write(Encoding.ASCII.GetString(bytesReceived, 0, bytes));
		}while (bytes > 0);

		socket.Close();
	}
}
ご不明な点やご提案などがありましたらこちらまでご連絡ください。

3. 複数行のクエリーを扱うには

BLASTやClustalWの配列情報のような複数行のクエリーは、改行コードとして "\n" を使用してください。
query= "atgccagtcataaagttcttcgaagctaagtcgcttgtcgacgccgagaaggggaaagca\ngttgt...
もし、Perl を使う場合、クエリー文字列を 「 '」ではなく「 "」 で囲んでください。
use LWP::UserAgent;
$ua = new LWP::UserAgent;

# make request
$req = new HTTP::Request POST => 'http://xml.ddbj.nig.ac.jp/rest/Invoke';
$req->content_type('application/x-www-form-urlencoded');
# set parameters
$query = "gtggcgagatcagttgttgtctctgcagaagccgtttactcccatgaaggcgaatacgta\n";
$query .= "ggcgatcacgttctagtagatgaggggcttgtaaagtccattagcagaggcgaacctcat\n";

$req->content("service=Blast&method=searchSimple&program=blastn&database=ddbjphg&query=$query");

# send request and get response.
$res = $ua->request($req);
# If you want to get a large result. It is better to write to a file directly.
# $res = $ua->request($req,"file_name.txt");
# If your request needs long time to execute, please set timeout as follows.
# $ua->timeout(3600); (1 hour.)

# show response.
print $res->content;

4. 英数字以外が含まれる情報を扱うには

もし"Homo sapiens" のように、英数字以外が含まれるクエリー(例では、スペース)を実行したい場合、URLエンコードが必要になります。 URLエンコードについては CookBook で紹介されています。
1. Perl でクエリー文字列をエンコードする
2. Java でクエリー文字列をエンコードする
3. C でクエリー文字列をエンコードする
4. C# でクエリー文字列をエンコードする
5. Ruby でクエリー文字列をエンコードする
6. Python でクエリー文字列をエンコードする

5. 非同期にメソッドを実行するには

一般にRESTを実行する場合、コネクション(接続)を確立しつづける必要がありますが、 非同期に実行することも可能です。非同期に実行させることにより、クライアント側の資源を有効利用することができます。 WABI の非同期メソッドは、メソッド名の最後に Async が付きます(例:Blast:searchSimpleAsync)。
非同期メソッドを実行すると、Request ID と呼ばれる ID が返されます。このIDを用いて RequestManager:getAsyncResult を実行することにより、非同期通信の結果を受け取ることが出来ます。非同期通信の結果は、最大2ヶ月間取得することが可能です。 非同期にメソッドを実行する方法を以下に紹介します。
1. 非同期通信を行います
use LWP::UserAgent;
$ua = new LWP::UserAgent;

# make request
$req = new HTTP::Request POST => "http://xml.nig.ac.jp/rest/Invoke";
$req->content_type("application/x-www-form-urlencoded");
# set parameters
$query = "MSSRIARALALVVTLLHLTRLALSTCPAACHCPLEAPKCAPGVGLVRDGCGCCKVCAKQL";
$req->content("service=Blast&method=searchSimpleAsync&program=blastp&database=SWISS&query=$query");

# send request and get response.
$res = $ua->request($req);

# show response.
print $res->content;
出力される ID は Request ID と呼ばれるものであり、本IDを用いて実行結果を参照します。出力形式は
Your requestId is:20090611092939466
のようになり、後ろの数字部分を用いて RequestManager:getAsyncResultに問い合わせを行い、結果を取得します。

2. 結果を取得します。

use LWP::UserAgent;
$ua = new LWP::UserAgent;

# make request
$req = new HTTP::Request POST => "http://xml.nig.ac.jp/rest/Invoke";
$req->content_type("application/x-www-form-urlencoded");
# set parameters
$req->content("service=RequestManager&method=getAsyncResult&requestId=20090611092939466");
# send request and get response.
$res = $ua->request($req);

# show response.
print $res->content;
もし完了していたらサービスの結果を取得できます。 未完了の場合"Your job has not completed yet."のメッセージが返されます。

6. プロキシサーバーを使用してアクセスするには

CookBookでプロキシサーバを用いた通信方法を紹介しています。
1 PerlのSokcetを用いる場合
2 PerlのLWPを用いる場合
3 JavaのURLConnectionを用いる場合
4 JavaのSocketを用いる場合
5 C のSocketを用いる場合
6 RubyのSocketを用いる場合
7 PythonのSocketを用いる場合
ご不明な点やご提案などがありましたらこちらまでご連絡ください。

7. ワークフローの作成

公開しているサービスを組み合わせてることにより、新しいワークフローを作成することができます。ワークフローを作成することで、単一のサービスでは実現できなかった機能を作成することができます。ワークフローの作成にあたり、Web APIの実行結果の一部を抽出・編集するためのパーサー機能を実装する必要がある場合があります。
DDBJにはヒトをはじめチンパンジーやマウスなどさまざまな生物種のDNAデータが登録されています。そこで、本チュートリアルではヒトと同様な遺伝子を持つ生物種を検索するワークフローを紹介します。本ワークフローはワークフローページでも公開されています。
ワークフローで使用するWeb API: ARSA Blast GetEntry
ワークフローの入力: ヒトの遺伝子名 (例.ABO, ALDH2, ACTA1)
ワークフローの結果: オーソログ遺伝子を持つ生物種とその生物種のエントリ(アクセッション番号)、配列の類似度
ワークフローの流れ:
  1. ヒトの遺伝子名でDDBJを検索する
  2. 最初のエントリのDNA配列を取得する
  3. DNA配列をクエリにしてBLASTを実行する
  4. アクセッション番号と類似度を取得する
  5. アクセッション番号から生物種名を取得する
  6. 結果を出力する。
本チュートリアルでは、Perl と Java を用いた実装方法を紹介します。

7.1. Perlを用いる場合

本チュートリアルでは、LWPを用いた方法を紹介します。まず、入力された遺伝子名を持つエントリのアクセッション番号をARSAsearchByXMLPathを用いて取得します。ARSAの検索方法についてはこちらをご覧ください。
use LWP::UserAgent;
$ua = new LWP::UserAgent;

#引数に指定された遺伝子名を取得します。
$gene = $ARGV[0];

# 1. 遺伝子名でDDBJを検索します。
$request = new HTTP::Request POST => 'http://xml.ddbj.nig.ac.jp/rest/Invoke';
$request->content_type('application/x-www-form-urlencoded');

#配列長が300bp以上1000bp以下、フィーチャーキーが CDS、geneクオリファイア値が入力されたものであるエントリを検索します。
$queryPath = "/ENTRY/DDBJ/division=='HUM' AND (/ENTRY/DDBJ/length>=300 AND /ENTRY/DDBJ/length<=1000) ";
$queryPath .= "AND (/ENTRY/DDBJ/feature-table/feature{/f_key = 'CDS' AND ";
$queryPath .= "/f_quals/qualifier{/q_name = 'gene' AND /q_value=='$gene'}})";

#returnPath にprimary-accession を指定し、アクセッション番号を取得します。
$request->content("service=ARSA&method=searchByXMLPath&queryPath=$queryPath
		&returnPath=/ENTRY/DDBJ/primary-accession&offset=1&count=100");

$arsa_result = $ua->request($request)->content;
@arsa_result_lines = split(/\n/, $arsa_result);
$arsa_result_num = substr($arsa_result_lines[0], 18);
#検索してもヒットが無かった場合、メッセージを出して終了します。
if($arsa_result_num == 0) {
	print "There is no entry of $gene.";
	exit(0);
}

次に GetEntrygetFASTA_DDBJEntry を用いて最初のエントリのDNA配列を取得します。
$rep_accession = $arsa_result_lines[2];
$request->content("service=GetEntry&method=getFASTA_DDBJEntry&accession=$rep_accession");
$dna_seq = $ua->request($request)->content;

次に、取得したDNA配列をクエリにして BlastsearchParam を用いて blastn を実行します。オプションは -e 0.0001 -m 8 -b 50 -v 50 を指定することによって、E-value が 0.0001以上の上位50件が出力されます。対象データベースddbjpri(霊長類) ddbjrod(齧歯類) ddbjmam(哺乳類) ddbjvrt(脊椎動物) ddbjinv(無脊椎動物) を指定します。
$request->content("service=Blast&method=searchParam&program=blastn&database=ddbjpri ddbjrod 
			ddbjmam ddbjvrt ddbjinv&query=$dna_seq&param=-m 8 -b 50 -v 50 -e 0.0001");
$blast_result = $ua->request($request)->content;

次に、BLASTの実行結果からアクセッション番号と類似度を取得します。本処理はWeb APIを使用しておらず、実行結果の一部を抽出・編集するパーサー機能に相当します。-m 8 オプションを指定したときの各カラムの情報はこちらをご覧ください。
@blast_result_lines = split(/\n/, $blast_result);
@parsed_blast_result = ();
for($i = 0; $i < $#blast_result_lines; $i++) {
	$line = $blast_result_lines[$i];
	@cols = split(/\t/, $line);
	$accession = substr($cols[1], 0, index($cols[1], '|'));
	$parsed_blast_result[$i][0] = $accession;
	$parsed_blast_result[$i][1] = $cols[2];
}

取得したアクセッション番号からARSAsearchByXMLPathを用いて生物種名を取得します。同じ生物種名がヒットした場合、類似度が一番高いものを採用します。
%organism_accession = ();
for($i = 0; $i < $#parsed_blast_result; $i++) {
	$request->content("service=ARSA&method=searchByXMLPath&queryPath=/ENTRY/DDBJ/primary-accession==
		'$parsed_blast_result[$i][0]'&returnPath=/ENTRY/DDBJ/organism&offset=1&count=100");
	$organism = $ua->request($request)->content;
	@organism_lines = split(/\n/, $organism);
	$organism = $organism_lines[2];
	if(!defined($organism_accession{$organism})) {
		$organism_accession{$organism} = "$parsed_blast_result[$i][0]\t$parsed_blast_result[$i][1]";
	}
}

最後に結果を出力します。
print "DDBJ entries: $arsa_result_num\n";
print "Representative accession: $rep_accession\n";
print "Organism name\tDDBJ accession number\tSequence similarity\n";
foreach $key (sort keys %organism_accession) {
	print "$key\t$organism_accession{$key}\n";
}

ワークフローの実行方法
プログラムをダウンロードして解凍します。引数に 遺伝子名 を与えます。 (最終更新日:2009年9月11日)
perl WorkFlowExampleRest.pl ABO

DDBJ entries: 107
Representative accession: AY611640
Organism name   DDBJ accession number   Sequence simi
Cebus apella apella     FJ377683        94.94
Cebus apella paraguayanus       FJ377685        94.94
Cebus olivaceus FJ377691        95.30
Gorilla gorilla AY138476        98.98
Hylobates agilis        AB196683        97.69
Hylobates lar   AB196692        97.69
Macaca fascicularis     AF100981        95.79
Macaca fuscata  AB041528        95.92
Macaca mulatta  AF094693        95.95
Pan paniscus    AB041757        98.23
Pan troglodytes AY138471        98.55
Papio anubis    AF019417        96.38
Saguinus oedipus        AY091958        92.33

7.2. Javaを用いる場合

本チュートリアルでは、URLConnectionを用いた方法を紹介します。まず、getResult というメソッドを用意します。本メソッドでRESTサービスにアクセスします。
	/**
	 * RESTにアクセスするためのメソッド。
	 * @param query
	 * REST呼び出しを行うための、サービス名、メソッド名必要パラメータをURL形式でまとめたもの
	 * @return
	 * REST呼び出し結果
	 * @throws IOException
	 */
	private String getResult(String query) throws IOException {
		String baseURL = "http://xml.nig.ac.jp/rest/Invoke";
		URL url = new URL(baseURL);
		URLConnection urlc = url.openConnection();
		urlc.setDoOutput(true);
		urlc.setAllowUserInteraction(false);
		PrintStream ps = new PrintStream(urlc.getOutputStream());
		ps.print(query);
		ps.close();
		BufferedReader br = new BufferedReader(new InputStreamReader(urlc
				.getInputStream()));

		StringBuffer sb = new StringBuffer();
		String line = null;
		while ((line = br.readLine()) != null) {
			sb.append(line+"\n");
		}
		br.close();
		return sb.toString();
	}

まず、入力された遺伝子名を持つエントリのアクセッション番号を、ARSAsearchByXMLPathを用いて検索します。ARSAの検索方法についてはこちらをご覧ください。
	/*
		ヒトに対して、配列長300-1000bpかつ、CDSフィーチャのgeneクオリファイアが入力された
		遺伝子名と一致するものを抽出するように指定。戻り値はアクセッション番号
	*/
	String queryPath = "/ENTRY/DDBJ/division=='HUM' AND ";
	       queryPath += "(/ENTRY/DDBJ/length>=300 AND /ENTRY/DDBJ/length<=1000) ";
	queryPath += "AND (/ENTRY/DDBJ/feature-table/feature{/f_key = 'CDS' AND ";
	queryPath += "/f_quals/qualifier{/q_name = 'gene' AND /q_value=='"+geneName+"'}})";
	String query = "service=ARSA&method=searchByXMLPath&queryPath="
			+ queryPath
			+ "&returnPath=/ENTRY/DDBJ/primary-accession&offset=1&count=100";
	//ARSAを実行する
	String arsaResult = getResult(query);
	String[] arsaResultLines = arsaResult.split("\n");
	//ヒット件数の取得を行う
	int arsaResultNum = Integer.parseInt(arsaResultLines[0].replaceAll(
			"hitscount       =", "").trim());
	//ヒットしなかった場合はメッセージを出して終了する
	if (arsaResultNum == 0) {
		System.out.println("There is no entry of $gene.");
		System.exit(0);
	}

次に GetEntrygetFASTA_DDBJEntry を用いて最初のエントリのDNA配列を取得します。
	//	一番上位のアクセッション番号のDNA配列を取得する
	String repAccession = arsaResultLines[2];
	query = "service=GetEntry&method=getFASTA_DDBJEntry&accession="
			+ repAccession;
	String dnaSeq = getResult(query);

次に、取得したDNA配列をクエリにして BlastsearchParam を用いて blastn を実行します。オプションは -e 0.0001 -m 8 -b 50 -v 50 を指定することによって、E-value が 0.0001以上の上位50件が出力されます。対象データベースddbjpri(霊長類) ddbjrod(齧歯類) ddbjmam(哺乳類) ddbjvrt(脊椎動物) ddbjinv(無脊椎動物) を指定します。
	//取得した配列を用いてBLASTを実行する
	query = "service=Blast&method=searchParam&program=blastn&database=ddbjpri"
		+" ddbjrod ddbjmam ddbjvrt ddbjinv&query="
		+ dnaSeq + "&param=-m 8 -b 50 -v 50 -e 0.0001";
	String blastResult = getResult(query);

次に、BLASTの実行結果からアクセッション番号と類似度を取得します。本処理はWeb APIを使用しておらず、実行結果の一部を抽出・編集するパーサー機能に相当します。-m 8 オプションを指定したときの各カラムの情報はこちらをご覧ください。
	String blastResultLines[] = blastResult.split("\n");
	Vector parsedBlastResult = new Vector();
	for (int i = 0; i < blastResultLines.length; i++) {
		String cols[] = blastResultLines[i].split("\t");
		String accession = cols[1].substring(0, cols[1].indexOf("|"));
		String[] result = { accession, cols[2] };
		parsedBlastResult.add(result);
	}

取得したアクセッション番号からARSAsearchByXMLPathを用いて生物種名を取得します。同じ生物種名がヒットした場合、類似度が一番高いものを採用します。
	//アクセッション番号から生物種名を取得する。
	Hashtable organismAccession = new Hashtable();
	for (int i = 0; i < parsedBlastResult.size(); i++) {
		String[] parsed = (String[]) parsedBlastResult.elementAt(i);
		query = "service=ARSA&method=searchByXMLPath&queryPath=/ENTRY/DDBJ/primary-accession=='"
				+ parsed[0]
				+ "'&returnPath=/ENTRY/DDBJ/organism&offset=1&count=100";
		String organism = getResult(query);
		String[] organismLines = organism.split("\n");
		organism = organismLines[2];
		//同じ生物種がヒットしていた場合、最上位のもののみ有効とする
		if (!organismAccession.containsKey(organism)) {
			organismAccession.put(organism, parsed[0] + "\t" + parsed[1]);
		}
	}

最後に結果を出力します。
	//結果出力
	System.out.println("DDBJ entries: " + arsaResultNum);
	System.out.println("Representative accession: " + repAccession);
	System.out
			.println("Organism name\tDDBJ accession number\tSequence similarity");
	String[] keys = new String[organismAccession.size()];
	Enumeration enu = organismAccession.keys();
	int count = 0;
	while (enu.hasMoreElements()) {
		keys[count] = (String) enu.nextElement();
		++count;
	}
	Arrays.sort(keys);
	for (int i = 0; i < keys.length; i++) {
		System.out.println(keys[i] + "\t"
				+ (String) organismAccession.get(keys[i]));
	}

ワークフローの実行方法
プログラムをダウンロードして、コンパイルします。引数に 遺伝子名 を与えます。(最終更新日:2009年9月11日)
javac WorkFlowExampleRest.java
java WorkFlowExampleRest ABO

DDBJ entries: 107
Representative accession: AY611640
Organism name   DDBJ accession number   Sequence simi
Cebus apella apella     FJ377683        94.94
Cebus apella paraguayanus       FJ377685        94.94
Cebus olivaceus FJ377691        95.30
Gorilla gorilla AY138476        98.98
Hylobates agilis        AB196683        97.69
Hylobates lar   AB196692        97.69
Macaca fascicularis     AF100981        95.79
Macaca fuscata  AB041528        95.92
Macaca mulatta  AF094693        95.95
Pan paniscus    AB041757        98.23
Pan troglodytes AY138471        98.55
Papio anubis    AF019417        96.38
Saguinus oedipus        AY091958        92.33 

8. REST と SOAP

Web API for Biology (WABI) では、RESTとSOAPサービスが提供されています。詳細はこちらをご覧ください
ご不明な点やご提案などがありましたらこちらまでご連絡ください。