JAL-1926 added supporting model changes to enable saving sourceDBRef data for sequences
[jalview.git] / src / jalview / datamodel / Sequence.java
index 5c1fba5..9f65f71 100755 (executable)
@@ -21,6 +21,7 @@
 package jalview.datamodel;
 
 import jalview.analysis.AlignSeq;
+import jalview.api.DBRefEntryI;
 import jalview.util.StringUtils;
 
 import java.util.ArrayList;
@@ -37,7 +38,7 @@ import fr.orsay.lri.varna.models.rna.RNA;
  * @author $author$
  * @version $Revision$
  */
-public class Sequence implements SequenceI
+public class Sequence extends ASequence implements SequenceI
 {
   SequenceI datasetSequence;
 
@@ -51,10 +52,12 @@ public class Sequence implements SequenceI
 
   int end;
 
-  Vector pdbIds;
+  Vector<PDBEntry> pdbIds;
 
   String vamsasId;
 
+  DBRefEntryI sourceDBRef;
+
   DBRefEntry[] dbrefs;
 
   RNA rna;
@@ -90,20 +93,30 @@ public class Sequence implements SequenceI
    */
   public Sequence(String name, String sequence, int start, int end)
   {
-    this.name = name;
-    this.sequence = sequence.toCharArray();
-    this.start = start;
-    this.end = end;
-    parseId();
-    checkValidRange();
+    initSeqAndName(name, sequence.toCharArray(), start, end);
   }
 
   public Sequence(String name, char[] sequence, int start, int end)
   {
-    this.name = name;
-    this.sequence = sequence;
-    this.start = start;
-    this.end = end;
+    initSeqAndName(name, sequence, start, end);
+  }
+
+  /**
+   * Stage 1 constructor - assign name, sequence, and set start and end fields.
+   * start and end are updated values from name2 if it ends with /start-end
+   * 
+   * @param name2
+   * @param sequence2
+   * @param start2
+   * @param end2
+   */
+  protected void initSeqAndName(String name2, char[] sequence2, int start2,
+          int end2)
+  {
+    this.name = name2;
+    this.sequence = sequence2;
+    this.start = start2;
+    this.end = end2;
     parseId();
     checkValidRange();
   }
@@ -121,7 +134,7 @@ public class Sequence implements SequenceI
               .println("POSSIBLE IMPLEMENTATION ERROR: null sequence name passed to constructor.");
       name = "";
     }
-    // Does sequence have the /start-end signiature?
+    // Does sequence have the /start-end signature?
     if (limitrx.search(name))
     {
       name = limitrx.left();
@@ -196,7 +209,15 @@ public class Sequence implements SequenceI
    */
   public Sequence(SequenceI seq, AlignmentAnnotation[] alAnnotation)
   {
-    this(seq.getName(), seq.getSequence(), seq.getStart(), seq.getEnd());
+    initSeqFrom(seq, alAnnotation);
+
+  }
+
+  protected void initSeqFrom(SequenceI seq,
+          AlignmentAnnotation[] alAnnotation)
+  {
+    initSeqAndName(seq.getName(), seq.getSequence(), seq.getStart(),
+            seq.getEnd());
     description = seq.getDescription();
     if (seq.getSequenceFeatures() != null)
     {
@@ -241,9 +262,9 @@ public class Sequence implements SequenceI
         }
       }
     }
-    if (seq.getPDBId() != null)
+    if (seq.getAllPDBEntries() != null)
     {
-      Vector ids = seq.getPDBId();
+      Vector ids = seq.getAllPDBEntries();
       Enumeration e = ids.elements();
       while (e.hasMoreElements())
       {
@@ -258,11 +279,13 @@ public class Sequence implements SequenceI
    * @param v
    *          DOCUMENT ME!
    */
+  @Override
   public void setSequenceFeatures(SequenceFeature[] features)
   {
     sequenceFeatures = features;
   }
 
+  @Override
   public synchronized void addSequenceFeature(SequenceFeature sf)
   {
     if (sequenceFeatures == null)
@@ -285,6 +308,7 @@ public class Sequence implements SequenceI
     sequenceFeatures = temp;
   }
 
+  @Override
   public void deleteFeature(SequenceFeature sf)
   {
     if (sequenceFeatures == null)
@@ -334,6 +358,7 @@ public class Sequence implements SequenceI
    * 
    * @return
    */
+  @Override
   public SequenceFeature[] getSequenceFeatures()
   {
     SequenceFeature[] features = sequenceFeatures;
@@ -349,25 +374,39 @@ public class Sequence implements SequenceI
     return features;
   }
 
+  @Override
   public void addPDBId(PDBEntry entry)
   {
     if (pdbIds == null)
     {
-      pdbIds = new Vector();
+      pdbIds = new Vector<PDBEntry>();
     }
-    if (!pdbIds.contains(entry))
+    if (pdbIds.contains(entry))
+    {
+      updatePDBEntry(pdbIds.get(pdbIds.indexOf(entry)), entry);
+    }
+    else
     {
       pdbIds.addElement(entry);
     }
   }
 
+  private static void updatePDBEntry(PDBEntry oldEntry, PDBEntry newEntry)
+  {
+    if (newEntry.getFile() != null)
+    {
+      oldEntry.setFile(newEntry.getFile());
+    }
+  }
+
   /**
    * DOCUMENT ME!
    * 
    * @param id
    *          DOCUMENT ME!
    */
-  public void setPDBId(Vector id)
+  @Override
+  public void setPDBId(Vector<PDBEntry> id)
   {
     pdbIds = id;
   }
@@ -377,7 +416,8 @@ public class Sequence implements SequenceI
    * 
    * @return DOCUMENT ME!
    */
-  public Vector getPDBId()
+  @Override
+  public Vector<PDBEntry> getAllPDBEntries()
   {
     return pdbIds;
   }
@@ -387,6 +427,7 @@ public class Sequence implements SequenceI
    * 
    * @return DOCUMENT ME!
    */
+  @Override
   public String getDisplayId(boolean jvsuffix)
   {
     StringBuffer result = new StringBuffer(name);
@@ -404,6 +445,7 @@ public class Sequence implements SequenceI
    * @param name
    *          DOCUMENT ME!
    */
+  @Override
   public void setName(String name)
   {
     this.name = name;
@@ -415,6 +457,7 @@ public class Sequence implements SequenceI
    * 
    * @return DOCUMENT ME!
    */
+  @Override
   public String getName()
   {
     return this.name;
@@ -426,6 +469,7 @@ public class Sequence implements SequenceI
    * @param start
    *          DOCUMENT ME!
    */
+  @Override
   public void setStart(int start)
   {
     this.start = start;
@@ -436,6 +480,7 @@ public class Sequence implements SequenceI
    * 
    * @return DOCUMENT ME!
    */
+  @Override
   public int getStart()
   {
     return this.start;
@@ -447,6 +492,7 @@ public class Sequence implements SequenceI
    * @param end
    *          DOCUMENT ME!
    */
+  @Override
   public void setEnd(int end)
   {
     this.end = end;
@@ -457,6 +503,7 @@ public class Sequence implements SequenceI
    * 
    * @return DOCUMENT ME!
    */
+  @Override
   public int getEnd()
   {
     return this.end;
@@ -467,6 +514,7 @@ public class Sequence implements SequenceI
    * 
    * @return DOCUMENT ME!
    */
+  @Override
   public int getLength()
   {
     return this.sequence.length;
@@ -478,22 +526,26 @@ public class Sequence implements SequenceI
    * @param seq
    *          DOCUMENT ME!
    */
+  @Override
   public void setSequence(String seq)
   {
     this.sequence = seq.toCharArray();
     checkValidRange();
   }
 
+  @Override
   public String getSequenceAsString()
   {
     return new String(sequence);
   }
 
+  @Override
   public String getSequenceAsString(int start, int end)
   {
     return new String(getSequence(start, end));
   }
 
+  @Override
   public char[] getSequence()
   {
     return sequence;
@@ -504,6 +556,7 @@ public class Sequence implements SequenceI
    * 
    * @see jalview.datamodel.SequenceI#getSequence(int, int)
    */
+  @Override
   public char[] getSequence(int start, int end)
   {
     if (start < 0)
@@ -564,6 +617,7 @@ public class Sequence implements SequenceI
    * 
    * @return DOCUMENT ME!
    */
+  @Override
   public char getCharAt(int i)
   {
     if (i < sequence.length)
@@ -582,6 +636,7 @@ public class Sequence implements SequenceI
    * @param desc
    *          DOCUMENT ME!
    */
+  @Override
   public void setDescription(String desc)
   {
     this.description = desc;
@@ -592,6 +647,7 @@ public class Sequence implements SequenceI
    * 
    * @return DOCUMENT ME!
    */
+  @Override
   public String getDescription()
   {
     return this.description;
@@ -602,6 +658,7 @@ public class Sequence implements SequenceI
    * 
    * @see jalview.datamodel.SequenceI#findIndex(int)
    */
+  @Override
   public int findIndex(int pos)
   {
     // returns the alignment position for a residue
@@ -654,6 +711,7 @@ public class Sequence implements SequenceI
    * @return int[SequenceI.getEnd()-SequenceI.getStart()+1] or null if no
    *         residues in SequenceI object
    */
+  @Override
   public int[] gapMap()
   {
     String seq = jalview.analysis.AlignSeq.extractGaps(
@@ -715,8 +773,7 @@ public class Sequence implements SequenceI
       {
         if (lastj != -1)
         {
-          map.add(new int[]
-          { lastj, j - 1 });
+          map.add(new int[] { lastj, j - 1 });
           lastj = -1;
         }
       }
@@ -724,8 +781,7 @@ public class Sequence implements SequenceI
     }
     if (lastj != -1)
     {
-      map.add(new int[]
-      { lastj, j - 1 });
+      map.add(new int[] { lastj, j - 1 });
       lastj = -1;
     }
     return map;
@@ -735,7 +791,7 @@ public class Sequence implements SequenceI
   public void deleteChars(int i, int j)
   {
     int newstart = start, newend = end;
-    if (i >= sequence.length)
+    if (i >= sequence.length || i < 0)
     {
       return;
     }
@@ -923,7 +979,6 @@ public class Sequence implements SequenceI
             .toArray(new AlignmentAnnotation[annotation.size()]);
   }
 
-
   @Override
   public boolean hasAnnotation(AlignmentAnnotation ann)
   {
@@ -935,7 +990,7 @@ public class Sequence implements SequenceI
   {
     if (this.annotation == null)
     {
-      this.annotation = new Vector();
+      this.annotation = new Vector<AlignmentAnnotation>();
     }
     if (!this.annotation.contains(annotation))
     {
@@ -944,6 +999,7 @@ public class Sequence implements SequenceI
     annotation.setSequenceRef(this);
   }
 
+  @Override
   public void removeAlignmentAnnotation(AlignmentAnnotation annotation)
   {
     if (this.annotation != null)
@@ -1011,6 +1067,7 @@ public class Sequence implements SequenceI
    * 
    * @see jalview.datamodel.SequenceI#createDatasetSequence()
    */
+  @Override
   public SequenceI createDatasetSequence()
   {
     if (datasetSequence == null)
@@ -1024,7 +1081,7 @@ public class Sequence implements SequenceI
       // move database references onto dataset sequence
       datasetSequence.setDBRef(getDBRef());
       setDBRef(null);
-      datasetSequence.setPDBId(getPDBId());
+      datasetSequence.setPDBId(getAllPDBEntries());
       setPDBId(null);
       datasetSequence.updatePDBIds();
       if (annotation != null)
@@ -1049,6 +1106,7 @@ public class Sequence implements SequenceI
    * jalview.datamodel.SequenceI#setAlignmentAnnotation(AlignmmentAnnotation[]
    * annotations)
    */
+  @Override
   public void setAlignmentAnnotation(AlignmentAnnotation[] annotations)
   {
     if (annotation != null)
@@ -1175,8 +1233,7 @@ public class Sequence implements SequenceI
       for (int si = 0; si < sfs.length; si++)
       {
         SequenceFeature sf[] = (mp != null) ? mp.locateFeature(sfs[si])
-                : new SequenceFeature[]
-                { new SequenceFeature(sfs[si]) };
+                : new SequenceFeature[] { new SequenceFeature(sfs[si]) };
         if (sf != null && sf.length > 0)
         {
           for (int sfi = 0; sfi < sf.length; sfi++)
@@ -1188,9 +1245,9 @@ public class Sequence implements SequenceI
     }
 
     // transfer PDB entries
-    if (entry.getPDBId() != null)
+    if (entry.getAllPDBEntries() != null)
     {
-      Enumeration e = entry.getPDBId().elements();
+      Enumeration e = entry.getAllPDBEntries().elements();
       while (e.hasMoreElements())
       {
         PDBEntry pdb = (PDBEntry) e.nextElement();
@@ -1222,6 +1279,7 @@ public class Sequence implements SequenceI
    * @return The index (zero-based) on this sequence in the MSA. It returns
    *         {@code -1} if this information is not available.
    */
+  @Override
   public int getIndex()
   {
     return index;
@@ -1235,16 +1293,19 @@ public class Sequence implements SequenceI
    *          position for this sequence. This value is zero-based (zero for
    *          this first sequence)
    */
+  @Override
   public void setIndex(int value)
   {
     index = value;
   }
 
+  @Override
   public void setRNA(RNA r)
   {
     rna = r;
   }
 
+  @Override
   public RNA getRNA()
   {
     return rna;
@@ -1269,4 +1330,41 @@ public class Sequence implements SequenceI
     return result;
   }
 
+  @Override
+  public String toString()
+  {
+    return getDisplayId(false);
+  }
+
+  @Override
+  public PDBEntry getPDBEntry(String pdbIdStr)
+  {
+    if (getDatasetSequence() == null
+            || getDatasetSequence().getAllPDBEntries() == null)
+    {
+      return null;
+    }
+    List<PDBEntry> entries = getDatasetSequence().getAllPDBEntries();
+    for (PDBEntry entry : entries)
+    {
+      if (entry.getId().equalsIgnoreCase(pdbIdStr))
+      {
+        return entry;
+      }
+    }
+    return null;
+  }
+
+  @Override
+  public void setSourceDBRef(DBRefEntryI dbRef)
+  {
+    this.sourceDBRef = dbRef;
+  }
+
+  @Override
+  public DBRefEntryI getSourceDBRef()
+  {
+    return this.sourceDBRef;
+  }
+
 }