001/*
002 *                    BioJava development code
003 *
004 * This code may be freely distributed and modified under the
005 * terms of the GNU Lesser General Public Licence.  This should
006 * be distributed with the code.  If you do not have a copy,
007 * see:
008 *
009 *      http://www.gnu.org/copyleft/lesser.html
010 *
011 * Copyright for this code is held jointly by the individual
012 * authors.  These should be listed in @author doc comments.
013 *
014 * For more information on the BioJava project and its aims,
015 * or to join the biojava-l mailing list, visit the home page
016 * at:
017 *
018 *      http://www.biojava.org/
019 *
020 */
021
022package org.biojava.bio.seq.db.biofetch;
023
024import java.io.BufferedReader;
025import java.io.IOException;
026import java.io.InputStreamReader;
027import java.net.HttpURLConnection;
028import java.net.URL;
029import java.util.StringTokenizer;
030
031import org.biojava.bio.BioException;
032import org.biojava.bio.seq.Sequence;
033import org.biojava.bio.seq.SequenceIterator;
034import org.biojava.bio.seq.db.IllegalIDException;
035import org.biojava.bio.seq.db.SequenceDBLite;
036import org.biojava.bio.seq.io.SeqIOTools;
037import org.biojava.utils.ChangeVetoException;
038import org.biojava.utils.Unchangeable;
039
040/**
041 * Simple SequenceDB implementation backed by a BioFetch (HTTP)
042 * server.
043 *
044 * @author Thomas Down
045 * @author Matthew Pocock
046 * @author Greg Cox
047 * @author Keith James
048 * @since 1.3
049 */
050public class BioFetchSequenceDB
051  extends
052    Unchangeable
053  implements
054    SequenceDBLite {
055    private final String location;
056    private final String dbName;
057
058    /**
059     * Construct a BioFetchSequenceDB which connects to the specified
060     * BioFetch server.
061     *
062     * @param location The base URL of the server.
063     * @param dbName The database name to use.
064     */
065    public BioFetchSequenceDB(String location,
066                                          String dbName) {
067        this.location = location;
068        this.dbName = dbName;
069    }
070
071    public String getName() {
072        return dbName;
073    }
074
075    public void addSequence(Sequence seq)  throws ChangeVetoException {
076        throw new ChangeVetoException("Failed to add sequence."
077                                      + " Sequences may not be added"
078                                      + " to a biofetch database");
079    }
080
081    public void removeSequence(String id) throws ChangeVetoException {
082        throw new ChangeVetoException("Failed to add sequence."
083                                      + " Sequences may not be removed"
084                                      + " from a biofetch database");
085    }
086
087    public Sequence getSequence(String id)
088        throws BioException, IllegalIDException
089    {
090        String format = "";
091
092        if (dbName.equals("embl"))
093            format = "embl";
094        if (dbName.equals("genbank"))
095            format = "genbank";
096        else if (dbName.equals("swiss"))
097            format = "swissprot";
098        else if (dbName.equals("refseq"))
099            throw new BioException("Sequence database "
100                                   + dbName
101                                   + " is not supported");
102
103        StringBuffer uri = new StringBuffer(location);
104        uri.append('?');
105        uri.append("style=raw;");
106        uri.append("format=");
107        uri.append(format);
108        uri.append(";db=");
109        uri.append(dbName);
110        uri.append(";id=");
111        uri.append(id);
112
113        try {
114            HttpURLConnection huc =
115                (HttpURLConnection) new URL(uri.substring(0)).openConnection();
116            huc.connect();
117            BufferedReader data =
118                new BufferedReader(new InputStreamReader(huc.getInputStream()));
119            data.mark(1000);
120
121            String firstLine = data.readLine();
122            if (firstLine.startsWith("Content-")) {
123                data.readLine();
124                firstLine = data.readLine();
125            }
126
127            StringTokenizer toke = new StringTokenizer(firstLine);
128            String first = toke.nextToken();
129            if ("ERROR".equals(first)) {
130                int errorCode = Integer.parseInt(toke.nextToken());
131                if (errorCode == 4) {
132                    throw new IllegalIDException("No such ID "
133                                                 + id
134                                                 + " in database "
135                                                 + getName());
136                } else {
137                    throw new BioException("Error fetching from BioFetch:"
138                                           + firstLine);
139                }
140            }
141
142            data.reset();
143
144            SequenceIterator si = SeqIOTools.readEmbl(data);
145
146            if (dbName.equals("embl"))
147                si = SeqIOTools.readEmbl(data);
148            else if (dbName.equals("genbank"))
149                si = SeqIOTools.readGenbank(data);
150            else if (dbName.equals("swiss"))
151                si = SeqIOTools.readSwissprot(data);
152
153            return si.nextSequence();
154
155        } catch (IOException ex) {
156            throw new BioException("Error reading data from BioFetch",ex);
157        }
158    }
159}