JAL-3076 fetch Ensembl sequence as JSON instead of Fasta
[jalview.git] / src / jalview / ext / ensembl / EnsemblLookup.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3  * Copyright (C) $$Year-Rel$$ The Jalview Authors
4  * 
5  * This file is part of Jalview.
6  * 
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3
10  * of the License, or (at your option) any later version.
11  *  
12  * Jalview is distributed in the hope that it will be useful, but 
13  * WITHOUT ANY WARRANTY; without even the implied warranty 
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
15  * PURPOSE.  See the GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
19  * The Jalview Authors are detailed in the 'AUTHORS' file.
20  */
21 package jalview.ext.ensembl;
22
23 import jalview.datamodel.AlignmentI;
24
25 import java.io.BufferedReader;
26 import java.io.IOException;
27 import java.net.MalformedURLException;
28 import java.net.URL;
29 import java.util.Arrays;
30 import java.util.List;
31
32 import org.json.simple.JSONObject;
33 import org.json.simple.parser.JSONParser;
34 import org.json.simple.parser.ParseException;
35
36 /**
37  * A client for the Ensembl lookup REST endpoint, used to find the gene
38  * identifier given a gene, transcript or protein identifier.
39  * 
40  * @author gmcarstairs
41  */
42 public class EnsemblLookup extends EnsemblRestClient
43 {
44   /**
45    * Default constructor (to use rest.ensembl.org)
46    */
47   public EnsemblLookup()
48   {
49     super();
50   }
51
52   /**
53    * Constructor given the target domain to fetch data from
54    * 
55    * @param
56    */
57   public EnsemblLookup(String d)
58   {
59     super(d);
60   }
61
62   @Override
63   public String getDbName()
64   {
65     return "ENSEMBL";
66   }
67
68   @Override
69   public AlignmentI getSequenceRecords(String queries) throws Exception
70   {
71     return null;
72   }
73
74   @Override
75   protected URL getUrl(List<String> ids) throws MalformedURLException
76   {
77     String identifier = ids.get(0);
78     return getUrl(identifier, null);
79   }
80
81   /**
82    * Gets the url for lookup of the given identifier, optionally with objectType
83    * also specified in the request
84    * 
85    * @param identifier
86    * @param objectType
87    * @return
88    */
89   protected URL getUrl(String identifier, String objectType)
90   {
91     String url = getDomain() + "/lookup/id/" + identifier
92             + CONTENT_TYPE_JSON;
93     if (objectType != null)
94     {
95       url += "&" + OBJECT_TYPE + "=" + objectType;
96     }
97
98     try
99     {
100       return new URL(url);
101     } catch (MalformedURLException e)
102     {
103       return null;
104     }
105   }
106
107   @Override
108   protected boolean useGetRequest()
109   {
110     return true;
111   }
112
113   /**
114    * Returns the gene id related to the given identifier, which may be for a
115    * gene, transcript or protein
116    * 
117    * @param identifier
118    * @return
119    */
120   public String getGeneId(String identifier)
121   {
122     return getGeneId(identifier, null);
123   }
124
125   /**
126    * Returns the gene id related to the given identifier (which may be for a
127    * gene, transcript or protein)
128    * 
129    * @param identifier
130    * @param objectType
131    * @return
132    */
133   public String getGeneId(String identifier, String objectType)
134   {
135     List<String> ids = Arrays.asList(new String[] { identifier });
136
137     BufferedReader br = null;
138     try
139     {
140       URL url = getUrl(identifier, objectType);
141       if (url != null)
142       {
143         br = getHttpResponse(url, ids);
144       }
145       return br == null ? null : parseResponse(br);
146     } catch (IOException e)
147     {
148       // ignore
149       return null;
150     } finally
151     {
152       if (br != null)
153       {
154         try
155         {
156           br.close();
157         } catch (IOException e)
158         {
159           // ignore
160         }
161       }
162     }
163   }
164
165   /**
166    * Parses the JSON response and returns the gene identifier, or null if not
167    * found. If the returned object_type is Gene, returns the id, if Transcript
168    * returns the Parent. If it is Translation (peptide identifier), then the
169    * Parent is the transcript identifier, so we redo the search with this value.
170    * 
171    * @param br
172    * @return
173    * @throws IOException
174    */
175   protected String parseResponse(BufferedReader br) throws IOException
176   {
177     String geneId = null;
178     JSONParser jp = new JSONParser();
179     try
180     {
181       JSONObject val = (JSONObject) jp.parse(br);
182       String type = val.get(OBJECT_TYPE).toString();
183       if (OBJECT_TYPE_GENE.equalsIgnoreCase(type))
184       {
185         // got the gene - just returns its id
186         geneId = val.get(ID).toString();
187       }
188       else if (OBJECT_TYPE_TRANSCRIPT.equalsIgnoreCase(type))
189       {
190         // got the transcript - return its (Gene) Parent
191         geneId = val.get(PARENT).toString();
192       }
193       else if (OBJECT_TYPE_TRANSLATION.equalsIgnoreCase(type))
194       {
195         // got the protein - get its Parent, restricted to type Transcript
196         String transcriptId = val.get(PARENT).toString();
197         geneId = getGeneId(transcriptId, OBJECT_TYPE_TRANSCRIPT);
198       }
199     } catch (ParseException e)
200     {
201       // ignore
202     }
203     return geneId;
204   }
205
206 }