JAL-1705 todo comment re writing DBRefEntry/SequenceFeature to dataset
[jalview.git] / src / jalview / datamodel / Sequence.java
index cab1ac7..5e3fbc5 100755 (executable)
@@ -20,6 +20,9 @@
  */
 package jalview.datamodel;
 
+import jalview.analysis.AlignSeq;
+import jalview.util.StringUtils;
+
 import java.util.ArrayList;
 import java.util.Enumeration;
 import java.util.List;
@@ -27,9 +30,6 @@ import java.util.Vector;
 
 import fr.orsay.lri.varna.models.rna.RNA;
 
-import jalview.analysis.AlignSeq;
-import jalview.util.StringUtils;
-
 /**
  * 
  * Implements the SequenceI interface for a char[] based sequence object.
@@ -37,7 +37,7 @@ import jalview.util.StringUtils;
  * @author $author$
  * @version $Revision$
  */
-public class Sequence implements SequenceI
+public class Sequence extends ASequence implements SequenceI
 {
   SequenceI datasetSequence;
 
@@ -90,20 +90,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();
   }
@@ -196,7 +206,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,13 +259,12 @@ public class Sequence implements SequenceI
         }
       }
     }
-    if (seq.getPDBId() != null)
+    if (seq.getAllPDBEntries() != null)
     {
-      Vector ids = seq.getPDBId();
-      Enumeration e = ids.elements();
-      while (e.hasMoreElements())
+      Vector<PDBEntry> ids = seq.getAllPDBEntries();
+      for (PDBEntry pdb : ids)
       {
-        this.addPDBId(new PDBEntry((PDBEntry) e.nextElement()));
+        this.addPDBId(new PDBEntry(pdb));
       }
     }
   }
@@ -258,13 +275,16 @@ public class Sequence implements SequenceI
    * @param v
    *          DOCUMENT ME!
    */
+  @Override
   public void setSequenceFeatures(SequenceFeature[] features)
   {
     sequenceFeatures = features;
   }
 
+  @Override
   public synchronized void addSequenceFeature(SequenceFeature sf)
   {
+    // TODO add to dataset sequence instead if there is one?
     if (sequenceFeatures == null)
     {
       sequenceFeatures = new SequenceFeature[0];
@@ -285,6 +305,7 @@ public class Sequence implements SequenceI
     sequenceFeatures = temp;
   }
 
+  @Override
   public void deleteFeature(SequenceFeature sf)
   {
     if (sequenceFeatures == null)
@@ -334,6 +355,7 @@ public class Sequence implements SequenceI
    * 
    * @return
    */
+  @Override
   public SequenceFeature[] getSequenceFeatures()
   {
     SequenceFeature[] features = sequenceFeatures;
@@ -349,6 +371,7 @@ public class Sequence implements SequenceI
     return features;
   }
 
+  @Override
   public void addPDBId(PDBEntry entry)
   {
     if (pdbIds == null)
@@ -391,7 +414,7 @@ public class Sequence implements SequenceI
    * @return DOCUMENT ME!
    */
   @Override
-  public Vector<PDBEntry> getPDBId()
+  public Vector<PDBEntry> getAllPDBEntries()
   {
     return pdbIds;
   }
@@ -401,6 +424,7 @@ public class Sequence implements SequenceI
    * 
    * @return DOCUMENT ME!
    */
+  @Override
   public String getDisplayId(boolean jvsuffix)
   {
     StringBuffer result = new StringBuffer(name);
@@ -418,6 +442,7 @@ public class Sequence implements SequenceI
    * @param name
    *          DOCUMENT ME!
    */
+  @Override
   public void setName(String name)
   {
     this.name = name;
@@ -429,6 +454,7 @@ public class Sequence implements SequenceI
    * 
    * @return DOCUMENT ME!
    */
+  @Override
   public String getName()
   {
     return this.name;
@@ -440,6 +466,7 @@ public class Sequence implements SequenceI
    * @param start
    *          DOCUMENT ME!
    */
+  @Override
   public void setStart(int start)
   {
     this.start = start;
@@ -450,6 +477,7 @@ public class Sequence implements SequenceI
    * 
    * @return DOCUMENT ME!
    */
+  @Override
   public int getStart()
   {
     return this.start;
@@ -461,6 +489,7 @@ public class Sequence implements SequenceI
    * @param end
    *          DOCUMENT ME!
    */
+  @Override
   public void setEnd(int end)
   {
     this.end = end;
@@ -471,6 +500,7 @@ public class Sequence implements SequenceI
    * 
    * @return DOCUMENT ME!
    */
+  @Override
   public int getEnd()
   {
     return this.end;
@@ -481,6 +511,7 @@ public class Sequence implements SequenceI
    * 
    * @return DOCUMENT ME!
    */
+  @Override
   public int getLength()
   {
     return this.sequence.length;
@@ -492,22 +523,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;
@@ -518,6 +553,7 @@ public class Sequence implements SequenceI
    * 
    * @see jalview.datamodel.SequenceI#getSequence(int, int)
    */
+  @Override
   public char[] getSequence(int start, int end)
   {
     if (start < 0)
@@ -578,6 +614,7 @@ public class Sequence implements SequenceI
    * 
    * @return DOCUMENT ME!
    */
+  @Override
   public char getCharAt(int i)
   {
     if (i < sequence.length)
@@ -596,6 +633,7 @@ public class Sequence implements SequenceI
    * @param desc
    *          DOCUMENT ME!
    */
+  @Override
   public void setDescription(String desc)
   {
     this.description = desc;
@@ -606,6 +644,7 @@ public class Sequence implements SequenceI
    * 
    * @return DOCUMENT ME!
    */
+  @Override
   public String getDescription()
   {
     return this.description;
@@ -616,6 +655,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
@@ -668,6 +708,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(
@@ -729,8 +770,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;
         }
       }
@@ -738,8 +778,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;
@@ -749,7 +788,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;
     }
@@ -888,6 +927,7 @@ public class Sequence implements SequenceI
   @Override
   public void addDBRef(DBRefEntry entry)
   {
+    // TODO add to dataset sequence instead if there is one?
     if (dbrefs == null)
     {
       dbrefs = new DBRefEntry[0];
@@ -921,6 +961,7 @@ public class Sequence implements SequenceI
   @Override
   public void setDatasetSequence(SequenceI seq)
   {
+    // TODO check for circular reference before setting?
     datasetSequence = seq;
   }
 
@@ -937,7 +978,6 @@ public class Sequence implements SequenceI
             .toArray(new AlignmentAnnotation[annotation.size()]);
   }
 
-
   @Override
   public boolean hasAnnotation(AlignmentAnnotation ann)
   {
@@ -958,6 +998,7 @@ public class Sequence implements SequenceI
     annotation.setSequenceRef(this);
   }
 
+  @Override
   public void removeAlignmentAnnotation(AlignmentAnnotation annotation)
   {
     if (this.annotation != null)
@@ -1025,6 +1066,7 @@ public class Sequence implements SequenceI
    * 
    * @see jalview.datamodel.SequenceI#createDatasetSequence()
    */
+  @Override
   public SequenceI createDatasetSequence()
   {
     if (datasetSequence == null)
@@ -1038,7 +1080,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)
@@ -1063,6 +1105,7 @@ public class Sequence implements SequenceI
    * jalview.datamodel.SequenceI#setAlignmentAnnotation(AlignmmentAnnotation[]
    * annotations)
    */
+  @Override
   public void setAlignmentAnnotation(AlignmentAnnotation[] annotations)
   {
     if (annotation != null)
@@ -1189,8 +1232,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++)
@@ -1202,9 +1244,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();
@@ -1236,6 +1278,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;
@@ -1249,16 +1292,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;
@@ -1283,4 +1329,29 @@ 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;
+  }
+
 }