JAL-1712 fixes/tests for Castor binding and 'show flanking regions'
[jalview.git] / src / jalview / datamodel / Sequence.java
index 0267f45..cab1ac7 100755 (executable)
@@ -20,8 +20,6 @@
  */
 package jalview.datamodel;
 
-import jalview.analysis.AlignSeq;
-
 import java.util.ArrayList;
 import java.util.Enumeration;
 import java.util.List;
@@ -29,6 +27,9 @@ 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.
@@ -50,7 +51,7 @@ public class Sequence implements SequenceI
 
   int end;
 
-  Vector pdbIds;
+  Vector<PDBEntry> pdbIds;
 
   String vamsasId;
 
@@ -120,7 +121,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();
@@ -326,34 +327,60 @@ public class Sequence implements SequenceI
   }
 
   /**
-   * DOCUMENT ME!
+   * Returns the sequence features (if any), looking first on the sequence, then
+   * on its dataset sequence, and so on until a non-null value is found (or
+   * none). This supports retrieval of sequence features stored on the sequence
+   * (as in the applet) or on the dataset sequence (as in the Desktop version).
    * 
-   * @return DOCUMENT ME!
+   * @return
    */
   public SequenceFeature[] getSequenceFeatures()
   {
-    return sequenceFeatures;
+    SequenceFeature[] features = sequenceFeatures;
+
+    SequenceI seq = this;
+    int count = 0; // failsafe against loop in sequence.datasetsequence...
+    while (features == null && seq.getDatasetSequence() != null
+            && count++ < 10)
+    {
+      seq = seq.getDatasetSequence();
+      features = ((Sequence) seq).sequenceFeatures;
+    }
+    return features;
   }
 
   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;
   }
@@ -363,7 +390,8 @@ public class Sequence implements SequenceI
    * 
    * @return DOCUMENT ME!
    */
-  public Vector getPDBId()
+  @Override
+  public Vector<PDBEntry> getPDBId()
   {
     return pdbIds;
   }
@@ -726,24 +754,12 @@ public class Sequence implements SequenceI
       return;
     }
 
-    char[] tmp;
-
-    if (j >= sequence.length)
-    {
-      tmp = new char[i];
-      System.arraycopy(sequence, 0, tmp, 0, i);
-      j = sequence.length;
-    }
-    else
-    {
-      tmp = new char[sequence.length - j + i];
-      System.arraycopy(sequence, 0, tmp, 0, i);
-      System.arraycopy(sequence, j, tmp, i, sequence.length - j);
-    }
+    char[] tmp = StringUtils.deleteChars(sequence, i, j);
     boolean createNewDs = false;
-    // TODO: take a look at the new dataset creation validation method below -
-    // this could become time comsuming for large sequences - consider making it
-    // more efficient
+    // TODO: take a (second look) at the dataset creation validation method for
+    // the very large sequence case
+    int eindex = -1, sindex = -1;
+    boolean ecalc = false, scalc = false;
     for (int s = i; s < j; s++)
     {
       if (jalview.schemes.ResidueProperties.aaIndex[sequence[s]] != 23)
@@ -754,7 +770,11 @@ public class Sequence implements SequenceI
         }
         else
         {
-          int sindex = findIndex(start) - 1;
+          if (!scalc)
+          {
+            sindex = findIndex(start) - 1;
+            scalc = true;
+          }
           if (sindex == s)
           {
             // delete characters including start of sequence
@@ -764,7 +784,11 @@ public class Sequence implements SequenceI
           else
           {
             // delete characters after start.
-            int eindex = findIndex(end) - 1;
+            if (!ecalc)
+            {
+              eindex = findIndex(end) - 1;
+              ecalc = true;
+            }
             if (eindex < j)
             {
               // delete characters at end of sequence
@@ -925,7 +949,7 @@ public class Sequence implements SequenceI
   {
     if (this.annotation == null)
     {
-      this.annotation = new Vector();
+      this.annotation = new Vector<AlignmentAnnotation>();
     }
     if (!this.annotation.contains(annotation))
     {
@@ -1024,7 +1048,7 @@ public class Sequence implements SequenceI
           AlignmentAnnotation _aa = new AlignmentAnnotation(aa);
           _aa.sequenceRef = datasetSequence;
           _aa.adjustForAlignment(); // uses annotation's own record of
-                                   // sequence-column mapping
+                                    // sequence-column mapping
           datasetSequence.addAlignmentAnnotation(_aa);
         }
       }
@@ -1245,8 +1269,10 @@ public class Sequence implements SequenceI
           String label)
   {
     List<AlignmentAnnotation> result = new ArrayList<AlignmentAnnotation>();
-    if (this.annotation != null) {
-      for (AlignmentAnnotation ann : annotation) {
+    if (this.annotation != null)
+    {
+      for (AlignmentAnnotation ann : annotation)
+      {
         if (ann.calcId != null && ann.calcId.equals(calcId)
                 && ann.label != null && ann.label.equals(label))
         {