JAL-2183 defensive check for openFrameCount < 0 (shouldn't happen but
[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   private static final String GO_GENE_ONTOLOGY = "GO";
31
32   /**
33    * Constructor given the target domain to fetch data from
34    * 
35    * @param d
36    */
37   public EnsemblXref(String d)
38   {
39     super(d);
40   }
41
42   @Override
43   public String getDbName()
44   {
45     return "ENSEMBL (xref)";
46   }
47
48   @Override
49   public AlignmentI getSequenceRecords(String queries) throws Exception
50   {
51     return null;
52   }
53
54   @Override
55   protected URL getUrl(List<String> ids) throws MalformedURLException
56   {
57     return getUrl(ids.get(0));
58   }
59
60   @Override
61   protected boolean useGetRequest()
62   {
63     return true;
64   }
65
66   @Override
67   protected String getRequestMimeType(boolean multipleIds)
68   {
69     return "application/json";
70   }
71
72   @Override
73   protected String getResponseMimeType()
74   {
75     return "application/json";
76   }
77
78   /**
79    * Calls the Ensembl xrefs REST endpoint and retrieves any cross-references
80    * ("primary_id") for the given identifier (Ensembl accession id) and database
81    * names. The "dbname" returned by Ensembl is canonicalised to Jalview's
82    * standard version, and a DBRefEntry constructed. Currently takes all
83    * identifiers apart from GO terms and synonyms.
84    * 
85    * @param identifier
86    *          an Ensembl stable identifier
87    * @return
88    */
89   public List<DBRefEntry> getCrossReferences(String identifier)
90   {
91     List<DBRefEntry> result = new ArrayList<DBRefEntry>();
92     List<String> ids = new ArrayList<String>();
93     ids.add(identifier);
94
95     BufferedReader br = null;
96     try
97     {
98       URL url = getUrl(identifier);
99       if (url != null)
100       {
101         br = getHttpResponse(url, ids);
102       }
103       return (parseResponse(br));
104     } catch (IOException e)
105     {
106       // ignore
107     } finally
108     {
109       if (br != null)
110       {
111         try
112         {
113           br.close();
114         } catch (IOException e)
115         {
116           // ignore
117         }
118       }
119     }
120
121     return result;
122   }
123
124   /**
125    * Parses "primary_id" and "dbname" values from the JSON response and
126    * constructs a DBRefEntry. Returns a list of the DBRefEntry created. Note we
127    * don't parse "synonyms" as they appear to be either redirected or obsolete
128    * in Uniprot.
129    * 
130    * @param br
131    * @return
132    * @throws IOException
133    */
134   protected List<DBRefEntry> parseResponse(BufferedReader br)
135           throws IOException
136   {
137     JSONParser jp = new JSONParser();
138     List<DBRefEntry> result = new ArrayList<DBRefEntry>();
139     try
140     {
141       JSONArray responses = (JSONArray) jp.parse(br);
142       Iterator rvals = responses.iterator();
143       while (rvals.hasNext())
144       {
145         JSONObject val = (JSONObject) rvals.next();
146         String dbName = val.get("dbname").toString();
147         if (dbName.equals(GO_GENE_ONTOLOGY))
148         {
149           continue;
150         }
151         String id = val.get("primary_id").toString();
152         if (dbName != null && id != null)
153         {
154           dbName = DBRefUtils.getCanonicalName(dbName);
155           DBRefEntry dbref = new DBRefEntry(dbName, "0", id);
156           result.add(dbref);
157         }
158       }
159     } catch (ParseException e)
160     {
161       // ignore
162     }
163     return result;
164   }
165
166   /**
167    * Returns the URL for the REST endpoint to fetch all cross-references for an
168    * identifier. Note this may return protein cross-references for nucleotide.
169    * Filter the returned list as required.
170    * 
171    * @param identifier
172    * @return
173    */
174   protected URL getUrl(String identifier)
175   {
176     String url = getDomain() + "/xrefs/id/" + identifier
177             + "?content-type=application/json&all_levels=1";
178     try
179     {
180       return new URL(url);
181     } catch (MalformedURLException e)
182     {
183       return null;
184     }
185   }
186
187 }