JAL-2679 use object_type=Transcript for lookup of Parent for Protein
[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   @Override
114   protected String getRequestMimeType(boolean multipleIds)
115   {
116     return "application/json";
117   }
118
119   @Override
120   protected String getResponseMimeType()
121   {
122     return "application/json";
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    * @return
131    */
132   public String getGeneId(String identifier)
133   {
134     return getGeneId(identifier, null);
135   }
136
137   /**
138    * Calls the Ensembl lookup REST endpoint and retrieves the 'Parent' for the
139    * given identifier, or null if not found
140    * 
141    * @param identifier
142    * @param objectType
143    *          (optional)
144    * @return
145    */
146   public String getGeneId(String identifier, String objectType)
147   {
148     List<String> ids = Arrays.asList(new String[] { identifier });
149
150     BufferedReader br = null;
151     try
152     {
153       URL url = getUrl(identifier, objectType);
154       if (url != null)
155       {
156         br = getHttpResponse(url, ids);
157       }
158       return br == null ? null : parseResponse(br);
159     } catch (IOException e)
160     {
161       // ignore
162       return null;
163     } finally
164     {
165       if (br != null)
166       {
167         try
168         {
169           br.close();
170         } catch (IOException e)
171         {
172           // ignore
173         }
174       }
175     }
176   }
177
178   /**
179    * Parses the JSON response and returns the gene identifier, or null if not
180    * found. If the returned object_type is Gene, returns the id, if Transcript
181    * returns the Parent. If it is Translation (peptide identifier), then the
182    * Parent is the transcript identifier, so we redo the search with this value.
183    * 
184    * @param br
185    * @return
186    * @throws IOException
187    */
188   protected String parseResponse(BufferedReader br) throws IOException
189   {
190     String geneId = null;
191     JSONParser jp = new JSONParser();
192     try
193     {
194       JSONObject val = (JSONObject) jp.parse(br);
195       String type = val.get(OBJECT_TYPE).toString();
196       if (OBJECT_TYPE_GENE.equalsIgnoreCase(type))
197       {
198         // got the gene - just returns its id
199         geneId = val.get(ID).toString();
200       }
201       else if (OBJECT_TYPE_TRANSCRIPT.equalsIgnoreCase(type))
202       {
203         // got the transcript - return its (Gene) Parent
204         geneId = val.get(PARENT).toString();
205       }
206       else if (OBJECT_TYPE_TRANSLATION.equalsIgnoreCase(type))
207       {
208         // got the protein - get its Parent, restricted to type Transcript
209         String transcriptId = val.get(PARENT).toString();
210         geneId = getGeneId(transcriptId, OBJECT_TYPE_TRANSCRIPT);
211       }
212     } catch (ParseException e)
213     {
214       // ignore
215     }
216     return geneId;
217   }
218
219 }