JAL-2089 patch broken merge to master for Release 2.10.0b1
[jalview.git] / src / jalview / ws / dbsources / Uniprot.java
index 2abb605..b6f53cd 100644 (file)
@@ -1,57 +1,69 @@
 /*
- * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.0b1)
- * Copyright (C) 2014 The Jalview Authors
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
  * 
  * This file is part of Jalview.
  * 
  * Jalview is free software: you can redistribute it and/or
  * modify it under the terms of the GNU General Public License 
- * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
  *  
  * Jalview is distributed in the hope that it will be useful, but 
  * WITHOUT ANY WARRANTY; without even the implied warranty 
  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
  * PURPOSE.  See the GNU General Public License for more details.
  * 
- * You should have received a copy of the GNU General Public License along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
  * The Jalview Authors are detailed in the 'AUTHORS' file.
  */
 package jalview.ws.dbsources;
 
-import java.io.File;
-import java.io.FileReader;
-import java.util.Enumeration;
-import java.util.Vector;
-
-import org.exolab.castor.xml.Unmarshaller;
-
-import com.stevesoft.pat.Regex;
-
 import jalview.datamodel.Alignment;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.DBRefEntry;
 import jalview.datamodel.DBRefSource;
 import jalview.datamodel.PDBEntry;
+import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
 import jalview.datamodel.UniprotEntry;
 import jalview.datamodel.UniprotFile;
 import jalview.ws.ebi.EBIFetchClient;
-import jalview.ws.seqfetcher.DbSourceProxy;
 import jalview.ws.seqfetcher.DbSourceProxyImpl;
 
+import java.io.File;
+import java.io.FileReader;
+import java.io.Reader;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Vector;
+
+import org.exolab.castor.mapping.Mapping;
+import org.exolab.castor.xml.Unmarshaller;
+
+import com.stevesoft.pat.Regex;
+
 /**
  * @author JimP
  * 
  */
-public class Uniprot extends DbSourceProxyImpl implements DbSourceProxy
+public class Uniprot extends DbSourceProxyImpl
 {
+  private static final String BAR_DELIMITER = "|";
+
+  /*
+   * Castor mapping loaded from uniprot_mapping.xml
+   */
+  private static Mapping map;
+
+  /**
+   * Constructor
+   */
   public Uniprot()
   {
     super();
-    addDbSourceProperty(DBRefSource.SEQDB, DBRefSource.SEQDB);
-    addDbSourceProperty(DBRefSource.PROTSEQDB);
-    // addDbSourceProperty(DBRefSource.MULTIACC, new Integer(50));
   }
 
   /*
@@ -59,9 +71,10 @@ public class Uniprot extends DbSourceProxyImpl implements DbSourceProxy
    * 
    * @see jalview.ws.DbSourceProxy#getAccessionSeparator()
    */
+  @Override
   public String getAccessionSeparator()
   {
-    return null; // ";";
+    return null;
   }
 
   /*
@@ -69,6 +82,7 @@ public class Uniprot extends DbSourceProxyImpl implements DbSourceProxy
    * 
    * @see jalview.ws.DbSourceProxy#getAccessionValidator()
    */
+  @Override
   public Regex getAccessionValidator()
   {
     return new Regex("([A-Z]+[0-9]+[A-Z0-9]+|[A-Z0-9]+_[A-Z0-9]+)");
@@ -79,6 +93,7 @@ public class Uniprot extends DbSourceProxyImpl implements DbSourceProxy
    * 
    * @see jalview.ws.DbSourceProxy#getDbSource()
    */
+  @Override
   public String getDbSource()
   {
     return DBRefSource.UNIPROT;
@@ -89,16 +104,21 @@ public class Uniprot extends DbSourceProxyImpl implements DbSourceProxy
    * 
    * @see jalview.ws.DbSourceProxy#getDbVersion()
    */
+  @Override
   public String getDbVersion()
   {
     return "0"; // we really don't know what version we're on.
   }
 
-  private EBIFetchClient ebi = null;
-
-  private static org.exolab.castor.mapping.Mapping map;
-
-  public Vector getUniprotEntries(File file)
+  /**
+   * Reads a file containing the reply to the EBI Fetch Uniprot data query,
+   * unmarshals it to a UniprotFile object, and returns the list of UniprotEntry
+   * data models (mapped from &lt;entry&gt; elements)
+   * 
+   * @param fileReader
+   * @return
+   */
+  public Vector<UniprotEntry> getUniprotEntries(Reader fileReader)
   {
     UniprotFile uni = new UniprotFile();
     try
@@ -106,9 +126,8 @@ public class Uniprot extends DbSourceProxyImpl implements DbSourceProxy
       if (map == null)
       {
         // 1. Load the mapping information from the file
-        map = new org.exolab.castor.mapping.Mapping(uni.getClass()
-                .getClassLoader());
-        java.net.URL url = getClass().getResource("/uniprot_mapping.xml");
+        map = new Mapping(uni.getClass().getClassLoader());
+        URL url = getClass().getResource("/uniprot_mapping.xml");
         map.loadMapping(url);
       }
 
@@ -116,9 +135,9 @@ public class Uniprot extends DbSourceProxyImpl implements DbSourceProxy
       Unmarshaller unmar = new Unmarshaller(uni);
       unmar.setIgnoreExtraElements(true);
       unmar.setMapping(map);
-      if (file != null)
+      if (fileReader != null)
       {
-        uni = (UniprotFile) unmar.unmarshal(new FileReader(file));
+        uni = (UniprotFile) unmar.unmarshal(fileReader);
       }
     } catch (Exception e)
     {
@@ -133,6 +152,7 @@ public class Uniprot extends DbSourceProxyImpl implements DbSourceProxy
    * 
    * @see jalview.ws.DbSourceProxy#getSequenceRecords(java.lang.String[])
    */
+  @Override
   public AlignmentI getSequenceRecords(String queries) throws Exception
   {
     startQuery();
@@ -140,62 +160,23 @@ public class Uniprot extends DbSourceProxyImpl implements DbSourceProxy
     {
       queries = queries.toUpperCase().replaceAll(
               "(UNIPROT\\|?|UNIPROT_|UNIREF\\d+_|UNIREF\\d+\\|?)", "");
-      Alignment al = null;
-      ebi = new EBIFetchClient();
-      StringBuffer result = new StringBuffer();
+      AlignmentI al = null;
+      EBIFetchClient ebi = new EBIFetchClient();
       // uniprotxml parameter required since december 2007
       // uniprotkb dbname changed introduced december 2008
       File file = ebi.fetchDataAsFile("uniprotkb:" + queries, "uniprotxml",
-              null);
-      Vector entries = getUniprotEntries(file);
+              ".xml");
+      Vector<UniprotEntry> entries = getUniprotEntries(new FileReader(file));
 
       if (entries != null)
       {
-        // First, make the new sequences
-        Enumeration en = entries.elements();
-        while (en.hasMoreElements())
+        ArrayList<SequenceI> seqs = new ArrayList<SequenceI>();
+        for (UniprotEntry entry : entries)
         {
-          UniprotEntry entry = (UniprotEntry) en.nextElement();
-
-          StringBuffer name = new StringBuffer(">UniProt/Swiss-Prot");
-          Enumeration en2 = entry.getAccession().elements();
-          while (en2.hasMoreElements())
-          {
-            name.append("|");
-            name.append(en2.nextElement());
-          }
-          en2 = entry.getName().elements();
-          while (en2.hasMoreElements())
-          {
-            name.append("|");
-            name.append(en2.nextElement());
-          }
-
-          if (entry.getProtein() != null
-                  && entry.getProtein().getName() != null)
-          {
-            for (int nm = 0, nmSize = entry.getProtein().getName().size(); nm < nmSize; nm++)
-            {
-              name.append(" " + entry.getProtein().getName().elementAt(nm));
-            }
-          }
-
-          result.append(name + "\n"
-                  + entry.getUniprotSequence().getContent() + "\n");
-
+          seqs.add(uniprotEntryToSequenceI(entry));
         }
+        al = new Alignment(seqs.toArray(new SequenceI[0]));
 
-        // Then read in the features and apply them to the dataset
-        al = parseResult(result.toString());
-        if (al != null)
-        {
-          // Decorate the alignment with database entries.
-          addUniprotXrefs(al, entries);
-        }
-        else
-        {
-          results = result;
-        }
       }
       stopQuery();
       return al;
@@ -207,68 +188,139 @@ public class Uniprot extends DbSourceProxyImpl implements DbSourceProxy
   }
 
   /**
-   * add an ordered set of UniprotEntry objects to an ordered set of seuqences.
    * 
-   * @param al
-   *          - a sequence of n sequences
-   * @param entries
-   *          a seuqence of n uniprot entries to be analysed.
+   * @param entry
+   *          UniprotEntry
+   * @return SequenceI instance created from the UniprotEntry instance
    */
-  public void addUniprotXrefs(Alignment al, Vector entries)
+  public SequenceI uniprotEntryToSequenceI(UniprotEntry entry)
   {
-    for (int i = 0; i < entries.size(); i++)
+    String id = getUniprotEntryId(entry);
+    SequenceI sequence = new Sequence(id, entry.getUniprotSequence()
+            .getContent());
+    sequence.setDescription(getUniprotEntryDescription(entry));
+
+    final String dbVersion = getDbVersion();
+    ArrayList<DBRefEntry> dbRefs = new ArrayList<DBRefEntry>();
+    for (String accessionId : entry.getAccession())
+    {
+      DBRefEntry dbRef = new DBRefEntry(DBRefSource.UNIPROT, dbVersion,
+              accessionId);
+
+      // mark dbRef as a primary reference for this sequence
+      dbRefs.add(dbRef);
+    }
+
+    Vector<PDBEntry> onlyPdbEntries = new Vector<PDBEntry>();
+    for (PDBEntry pdb : entry.getDbReference())
     {
-      UniprotEntry entry = (UniprotEntry) entries.elementAt(i);
-      Enumeration e = entry.getDbReference().elements();
-      Vector onlyPdbEntries = new Vector();
-      Vector dbxrefs = new Vector();
-      while (e.hasMoreElements())
+      DBRefEntry dbr = new DBRefEntry();
+      dbr.setSource(pdb.getType());
+      dbr.setAccessionId(pdb.getId());
+      dbr.setVersion(DBRefSource.UNIPROT + ":" + dbVersion);
+      dbRefs.add(dbr);
+      if ("PDB".equals(pdb.getType()))
       {
-        PDBEntry pdb = (PDBEntry) e.nextElement();
-        DBRefEntry dbr = new DBRefEntry();
-        dbr.setSource(pdb.getType());
-        dbr.setAccessionId(pdb.getId());
-        dbr.setVersion(DBRefSource.UNIPROT + ":" + getDbVersion());
-        dbxrefs.addElement(dbr);
-        if (!pdb.getType().equals("PDB"))
+        onlyPdbEntries.addElement(pdb);
+      }
+      if ("EMBL".equals(pdb.getType()))
+      {
+        // look for a CDS reference and add it, too.
+        String cdsId = (String) pdb.getProperty("protein sequence ID");
+        if (cdsId != null && cdsId.trim().length() > 0)
         {
-          continue;
+          // remove version
+          String[] vrs = cdsId.split("\\.");
+          dbr = new DBRefEntry(DBRefSource.EMBLCDS, vrs.length > 1 ? vrs[1]
+                  : DBRefSource.UNIPROT + ":" + dbVersion, vrs[0]);
+          dbRefs.add(dbr);
         }
-
-        onlyPdbEntries.addElement(pdb);
       }
-      SequenceI sq = al.getSequenceAt(i);
-      while (sq.getDatasetSequence() != null)
+      if ("Ensembl".equals(pdb.getType()))
       {
-        sq = sq.getDatasetSequence();
+        /*UniprotXML
+         * <dbReference type="Ensembl" id="ENST00000321556">
+        * <molecule id="Q9BXM7-1"/>
+        * <property type="protein sequence ID" value="ENSP00000364204"/>
+        * <property type="gene ID" value="ENSG00000158828"/>
+        * </dbReference> 
+         */
+        String cdsId = (String) pdb.getProperty("protein sequence ID");
+        if (cdsId != null && cdsId.trim().length() > 0)
+        {
+          dbr = new DBRefEntry(DBRefSource.ENSEMBL, DBRefSource.UNIPROT
+                  + ":" + dbVersion, cdsId.trim());
+          dbRefs.add(dbr);
+
+        }
       }
 
-      Enumeration en2 = entry.getAccession().elements();
-      while (en2.hasMoreElements())
+    }
+
+    sequence.setPDBId(onlyPdbEntries);
+    if (entry.getFeature() != null)
+    {
+      for (SequenceFeature sf : entry.getFeature())
       {
-        // we always add as uniprot if we retrieved from uniprot or uniprot name
-        sq.addDBRef(new DBRefEntry(DBRefSource.UNIPROT, getDbVersion(), en2
-                .nextElement().toString()));
+        sf.setFeatureGroup("Uniprot");
+        sequence.addSequenceFeature(sf);
       }
-      en2 = dbxrefs.elements();
-      while (en2.hasMoreElements())
-      {
-        // we always add as uniprot if we retrieved from uniprot or uniprot name
-        sq.addDBRef((DBRefEntry) en2.nextElement());
+    }
+    for (DBRefEntry dbr : dbRefs)
+    {
+      sequence.addDBRef(dbr);
+    }
+    return sequence;
+  }
 
-      }
-      sq.setPDBId(onlyPdbEntries);
-      if (entry.getFeature() != null)
+  /**
+   * 
+   * @param entry
+   *          UniportEntry
+   * @return protein name(s) delimited by a white space character
+   */
+  public static String getUniprotEntryDescription(UniprotEntry entry)
+  {
+    StringBuilder desc = new StringBuilder(32);
+    if (entry.getProtein() != null && entry.getProtein().getName() != null)
+    {
+      boolean first = true;
+      for (String nm : entry.getProtein().getName())
       {
-        e = entry.getFeature().elements();
-        while (e.hasMoreElements())
+        if (!first)
         {
-          SequenceFeature sf = (SequenceFeature) e.nextElement();
-          sf.setFeatureGroup("Uniprot");
-          sq.addSequenceFeature(sf);
+          desc.append(" ");
         }
+        first = false;
+        desc.append(nm);
       }
     }
+    return desc.toString();
+  }
+
+  /**
+   *
+   * @param entry
+   *          UniportEntry
+   * @return The accession id(s) and name(s) delimited by '|'.
+   */
+  public static String getUniprotEntryId(UniprotEntry entry)
+  {
+    StringBuilder name = new StringBuilder(32);
+    // name.append("UniProt/Swiss-Prot");
+    // use 'canonicalised' name for optimal id matching
+    name.append(DBRefSource.UNIPROT);
+    for (String accessionId : entry.getAccession())
+    {
+      name.append(BAR_DELIMITER);
+      name.append(accessionId);
+    }
+    for (String n : entry.getName())
+    {
+      name.append(BAR_DELIMITER);
+      name.append(n);
+    }
+    return name.toString();
   }
 
   /*
@@ -276,6 +328,7 @@ public class Uniprot extends DbSourceProxyImpl implements DbSourceProxy
    * 
    * @see jalview.ws.DbSourceProxy#isValidReference(java.lang.String)
    */
+  @Override
   public boolean isValidReference(String accession)
   {
     // TODO: make the following a standard validator
@@ -286,11 +339,13 @@ public class Uniprot extends DbSourceProxyImpl implements DbSourceProxy
   /**
    * return LDHA_CHICK uniprot entry
    */
+  @Override
   public String getTestQuery()
   {
     return "P00340";
   }
 
+  @Override
   public String getDbName()
   {
     return "Uniprot"; // getDbSource();