7b5f9da09ff9d4b3ddc783d7b1c04bd732587dfc
[jalview.git] / src / jalview / ext / ensembl / EnsemblXref.java
1 package jalview.ext.ensembl;
2
3 import jalview.datamodel.AlignmentI;
4 import jalview.datamodel.DBRefEntry;
5 import jalview.util.DBRefUtils;
6
7 import java.io.BufferedReader;
8 import java.io.IOException;
9 import java.net.MalformedURLException;
10 import java.net.URL;
11 import java.util.ArrayList;
12 import java.util.Iterator;
13 import java.util.List;
14
15 import org.json.simple.JSONArray;
16 import org.json.simple.JSONObject;
17 import org.json.simple.parser.JSONParser;
18 import org.json.simple.parser.ParseException;
19
20 /**
21  * A class to fetch cross-references from Ensembl by calling the /xrefs REST
22  * service
23  * 
24  * @author gmcarstairs
25  * @see http://rest.ensembl.org/documentation/info/xref_id
26  */
27 class EnsemblXref extends EnsemblRestClient
28 {
29
30   /**
31    * Constructor given the target domain to fetch data from
32    * 
33    * @param d
34    */
35   public EnsemblXref(String d)
36   {
37     super(d);
38   }
39
40   @Override
41   public String getDbName()
42   {
43     return "ENSEMBL (xref)";
44   }
45
46   @Override
47   public AlignmentI getSequenceRecords(String queries) throws Exception
48   {
49     return null;
50   }
51
52   @Override
53   protected URL getUrl(List<String> ids) throws MalformedURLException
54   {
55     return getUrl(ids.get(0));
56   }
57
58   @Override
59   protected boolean useGetRequest()
60   {
61     return true;
62   }
63
64   @Override
65   protected String getRequestMimeType(boolean multipleIds)
66   {
67     return "application/json";
68   }
69
70   @Override
71   protected String getResponseMimeType()
72   {
73     return "application/json";
74   }
75
76   /**
77    * Calls the Ensembl xrefs REST endpoint and retrieves any cross-references
78    * ("primary_id") for the given identifier (Ensembl accession id) and database
79    * names. The "dbname" returned by Ensembl is canonicalised to Jalview's
80    * standard version, and a DBRefEntry constructed. If no databases are
81    * specified, all available cross-references are retrieved.
82    * 
83    * @param identifier
84    *          an Ensembl stable identifier
85    * @param databases
86    *          optional list of Ensembl cross-referenced databases of interest
87    * @return
88    */
89   public List<DBRefEntry> getCrossReferences(String identifier,
90           List<String> databases)
91   {
92     List<DBRefEntry> result = new ArrayList<DBRefEntry>();
93     List<String> ids = new ArrayList<String>();
94     ids.add(identifier);
95
96     BufferedReader br = null;
97     try
98     {
99       URL url = getUrl(identifier);
100       if (url != null)
101       {
102         br = getHttpResponse(url, ids);
103       }
104       return (parseResponse(br, databases));
105     } catch (IOException e)
106     {
107       // ignore
108     } finally
109     {
110       if (br != null)
111       {
112         try
113         {
114           br.close();
115         } catch (IOException e)
116         {
117           // ignore
118         }
119       }
120     }
121
122     return result;
123   }
124
125   /**
126    * Parses "primary_id" and "dbname" values from the JSON response and
127    * constructs a DBRefEntry if the dbname is in the list supplied. Returns a
128    * list of the DBRefEntry created. Note we don't parse "synonyms" as they
129    * appear to be either redirected or obsolete in Uniprot.
130    * 
131    * @param br
132    * @param databases
133    * @return
134    * @throws IOException
135    */
136   protected List<DBRefEntry> parseResponse(BufferedReader br,
137           List<String> databases)
138           throws IOException
139   {
140     JSONParser jp = new JSONParser();
141     List<DBRefEntry> result = new ArrayList<DBRefEntry>();
142     try
143     {
144       JSONArray responses = (JSONArray) jp.parse(br);
145       Iterator rvals = responses.iterator();
146       while (rvals.hasNext())
147       {
148         JSONObject val = (JSONObject) rvals.next();
149         String dbName = val.get("dbname").toString();
150         if (databases != null && !databases.isEmpty()
151                 && !databases.contains(dbName))
152         {
153           continue;
154         }
155         String id = val.get("primary_id").toString();
156         if (dbName != null && id != null)
157         {
158           dbName = DBRefUtils.getCanonicalName(dbName);
159           DBRefEntry dbref = new DBRefEntry(dbName, "0", id);
160           result.add(dbref);
161         }
162       }
163     } catch (ParseException e)
164     {
165       // ignore
166     }
167     return result;
168   }
169
170   /**
171    * Returns the URL for the REST endpoint to fetch all cross-references for an
172    * identifier. Note this may return protein cross-references for nucleotide.
173    * Filter the returned list as required.
174    * 
175    * @param identifier
176    * @return
177    */
178   protected URL getUrl(String identifier)
179   {
180     String url = getDomain() + "/xrefs/id/" + identifier
181             + "?content-type=application/json&all_levels=1";
182     try
183     {
184       return new URL(url);
185     } catch (MalformedURLException e)
186     {
187       return null;
188     }
189   }
190
191 }