--- /dev/null
+package jalview.ext.ensembl;
+
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.DBRefEntry;
+import jalview.util.DBRefUtils;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.json.simple.JSONArray;
+import org.json.simple.JSONObject;
+import org.json.simple.parser.JSONParser;
+import org.json.simple.parser.ParseException;
+
+/**
+ * A class to fetch cross-references from Ensembl by calling the /xrefs REST
+ * service
+ *
+ * @author gmcarstairs
+ * @see http://rest.ensembl.org/documentation/info/xref_id
+ */
+class EnsemblXref extends EnsemblRestClient
+{
+
+ /**
+ * Constructor given the target domain to fetch data from
+ *
+ * @param d
+ */
+ public EnsemblXref(String d)
+ {
+ super(d);
+ }
+
+ @Override
+ public String getDbName()
+ {
+ return "ENSEMBL (xref)";
+ }
+
+ @Override
+ public AlignmentI getSequenceRecords(String queries) throws Exception
+ {
+ return null;
+ }
+
+ @Override
+ protected URL getUrl(List<String> ids) throws MalformedURLException
+ {
+ return getUrl(ids.get(0));
+ }
+
+ @Override
+ protected boolean useGetRequest()
+ {
+ return true;
+ }
+
+ @Override
+ protected String getRequestMimeType(boolean multipleIds)
+ {
+ return "application/json";
+ }
+
+ @Override
+ protected String getResponseMimeType()
+ {
+ return "application/json";
+ }
+
+ /**
+ * Calls the Ensembl xrefs REST endpoint and retrieves any cross-references
+ * ("primary_id") for the given identifier (Ensembl accession id) and database
+ * names. The "dbname" returned by Ensembl is canonicalised to Jalview's
+ * standard version, and a DBRefEntry constructed. If no databases are
+ * specified, all available cross-references are retrieved.
+ *
+ * @param identifier
+ * @param databases
+ * @return
+ */
+ public List<DBRefEntry> getCrossReferences(String identifier,
+ List<String> databases)
+ {
+ List<DBRefEntry> result = new ArrayList<DBRefEntry>();
+ List<String> ids = new ArrayList<String>();
+ ids.add(identifier);
+
+ BufferedReader br = null;
+ try
+ {
+ URL url = getUrl(identifier);
+ if (url != null)
+ {
+ br = getHttpResponse(url, ids);
+ }
+ return (parseResponse(br, databases));
+ } catch (IOException e)
+ {
+ // ignore
+ } finally
+ {
+ if (br != null)
+ {
+ try
+ {
+ br.close();
+ } catch (IOException e)
+ {
+ // ignore
+ }
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Parses "primary_id" and "dbname" values from the JSON response and
+ * constructs a DBRefEntry if the dbname is in the list supplied. Returns a
+ * list of DBRefEntry created.
+ *
+ * @param br
+ * @param databases
+ * @return
+ * @throws IOException
+ */
+ protected List<DBRefEntry> parseResponse(BufferedReader br,
+ List<String> databases)
+ throws IOException
+ {
+ JSONParser jp = new JSONParser();
+ List<DBRefEntry> result = new ArrayList<DBRefEntry>();
+ try
+ {
+ JSONArray responses = (JSONArray) jp.parse(br);
+ Iterator rvals = responses.iterator();
+ while (rvals.hasNext())
+ {
+ JSONObject val = (JSONObject) rvals.next();
+ String dbName = val.get("dbname").toString();
+ if (databases != null && !databases.isEmpty()
+ && !databases.contains(dbName))
+ {
+ continue;
+ }
+ String id = val.get("primary_id").toString();
+ if (dbName != null && id != null)
+ {
+ dbName = DBRefUtils.getCanonicalName(dbName);
+ DBRefEntry dbref = new DBRefEntry(dbName, "0", id);
+ result.add(dbref);
+ }
+ }
+ } catch (ParseException e)
+ {
+ // ignore
+ }
+ return result;
+ }
+
+ /**
+ * Returns the URL for the REST endpoint to fetch all cross-references for an
+ * identifier. Note this may return protein cross-references for nucleotide.
+ * Filter the returned list as required.
+ *
+ * @param identifier
+ * @return
+ */
+ protected URL getUrl(String identifier)
+ {
+ String url = getDomain() + "/xrefs/id/" + identifier
+ + "?content-type=application/json&all_levels=1";
+ try
+ {
+ return new URL(url);
+ } catch (MalformedURLException e)
+ {
+ return null;
+ }
+ }
+
+}