JAL-1115 refactor base collection for Alignment from Vector to locally synchronized...
[jalview.git] / src / jalview / datamodel / Alignment.java
index 23fe057..f9de115 100755 (executable)
@@ -32,9 +32,10 @@ public class Alignment implements AlignmentI
 {
   protected Alignment dataset;
 
-  protected Vector sequences;
+  protected List<SequenceI> sequences;
 
-  protected Vector groups = new Vector();
+  protected List<SequenceGroup> groups = java.util.Collections
+          .synchronizedList(new ArrayList<SequenceGroup>());
 
   protected char gapCharacter = '-';
 
@@ -66,11 +67,12 @@ public class Alignment implements AlignmentI
       type = PROTEIN;
     }
 
-    sequences = new Vector();
+    sequences = java.util.Collections
+            .synchronizedList(new ArrayList<SequenceI>());
 
     for (i = 0; i < seqs.length; i++)
     {
-      sequences.addElement(seqs[i]);
+      sequences.add(seqs[i]);
     }
 
   }
@@ -118,7 +120,8 @@ public class Alignment implements AlignmentI
    * 
    * @return DOCUMENT ME!
    */
-  public Vector getSequences()
+  @Override
+  public List<SequenceI> getSequences()
   {
     return sequences;
   }
@@ -134,12 +137,10 @@ public class Alignment implements AlignmentI
   {
     if (sequences == null)
       return null;
-    SequenceI[] reply = new SequenceI[sequences.size()];
-    for (int i = 0; i < sequences.size(); i++)
+    synchronized (sequences)
     {
-      reply[i] = (SequenceI) sequences.elementAt(i);
+      return sequences.toArray(new SequenceI[sequences.size()]);
     }
-    return reply;
   }
 
   /**
@@ -152,11 +153,13 @@ public class Alignment implements AlignmentI
    */
   public SequenceI getSequenceAt(int i)
   {
-    if (i>-1 && i < sequences.size())
+    synchronized (sequences)
     {
-      return (SequenceI) sequences.elementAt(i);
+      if (i > -1 && i < sequences.size())
+      {
+        return sequences.get(i);
+      }
     }
-
     return null;
   }
 
@@ -189,7 +192,10 @@ public class Alignment implements AlignmentI
     }
     else
     {
-      sequences.addElement(snew);
+      synchronized (sequences)
+      {
+        sequences.add(snew);
+      }
     }
     if (hiddenSequences != null)
       hiddenSequences.adjustHeightSequenceAdded();
@@ -203,9 +209,11 @@ public class Alignment implements AlignmentI
   public void setSequenceAt(int i, SequenceI snew)
   {
     SequenceI oldseq = getSequenceAt(i);
-    deleteSequence(oldseq);
-
-    sequences.setElementAt(snew, i);
+    deleteSequence(i);
+    synchronized (sequences)
+    {
+      sequences.set(i, snew);
+    }
   }
 
   /**
@@ -263,24 +271,34 @@ public class Alignment implements AlignmentI
   {
     if (i > -1 && i < getHeight())
     {
-      sequences.removeElementAt(i);
+      synchronized (sequences)
+      {
+        sequences.remove(i);
+      }
       hiddenSequences.adjustHeightSequenceDeleted(i);
     }
   }
 
-  /**    */
+  /*
+   * (non-Javadoc)
+   *
+   * @see jalview.datamodel.AlignmentI#findGroup(jalview.datamodel.SequenceI)
+   */
+  @Override
   public SequenceGroup findGroup(SequenceI s)
   {
-    for (int i = 0; i < this.groups.size(); i++)
+    synchronized (groups)
     {
-      SequenceGroup sg = (SequenceGroup) groups.elementAt(i);
-
-      if (sg.getSequences(null).contains(s))
+      for (int i = 0; i < this.groups.size(); i++)
       {
-        return sg;
+        SequenceGroup sg = groups.get(i);
+
+        if (sg.getSequences(null).contains(s))
+        {
+          return sg;
+        }
       }
     }
-
     return null;
   }
 
@@ -294,60 +312,59 @@ public class Alignment implements AlignmentI
    */
   public SequenceGroup[] findAllGroups(SequenceI s)
   {
-    Vector temp = new Vector();
+    ArrayList<SequenceGroup> temp = new ArrayList<SequenceGroup>();
 
-    int gSize = groups.size();
-    for (int i = 0; i < gSize; i++)
+    synchronized (groups)
     {
-      SequenceGroup sg = (SequenceGroup) groups.elementAt(i);
-      if (sg == null || sg.getSequences(null) == null)
+      int gSize = groups.size();
+      for (int i = 0; i < gSize; i++)
       {
-        this.deleteGroup(sg);
-        gSize--;
-        continue;
-      }
+        SequenceGroup sg = groups.get(i);
+        if (sg == null || sg.getSequences(null) == null)
+        {
+          this.deleteGroup(sg);
+          gSize--;
+          continue;
+        }
 
-      if (sg.getSequences(null).contains(s))
-      {
-        temp.addElement(sg);
+        if (sg.getSequences(null).contains(s))
+        {
+          temp.add(sg);
+        }
       }
     }
-
     SequenceGroup[] ret = new SequenceGroup[temp.size()];
-
-    for (int i = 0; i < temp.size(); i++)
-    {
-      ret[i] = (SequenceGroup) temp.elementAt(i);
-    }
-
-    return ret;
+    return temp.toArray(ret);
   }
 
   /**    */
   public void addGroup(SequenceGroup sg)
   {
-    if (!groups.contains(sg))
+    synchronized (groups)
     {
-      if (hiddenSequences.getSize() > 0)
+      if (!groups.contains(sg))
       {
-        int i, iSize = sg.getSize();
-        for (i = 0; i < iSize; i++)
+        if (hiddenSequences.getSize() > 0)
         {
-          if (!sequences.contains(sg.getSequenceAt(i)))
+          int i, iSize = sg.getSize();
+          for (i = 0; i < iSize; i++)
           {
-            sg.deleteSequence(sg.getSequenceAt(i), false);
-            iSize--;
-            i--;
+            if (!sequences.contains(sg.getSequenceAt(i)))
+            {
+              sg.deleteSequence(sg.getSequenceAt(i), false);
+              iSize--;
+              i--;
+            }
           }
-        }
 
-        if (sg.getSize() < 1)
-        {
-          return;
+          if (sg.getSize() < 1)
+          {
+            return;
+          }
         }
-      }
 
-      groups.addElement(sg);
+        groups.add(sg);
+      }
     }
   }
 
@@ -413,20 +430,26 @@ public class Alignment implements AlignmentI
 
   public void deleteAllGroups()
   {
-    if (annotations != null)
+    synchronized (groups)
     {
-      removeAnnotationForGroup(null);
+      if (annotations != null)
+      {
+        removeAnnotationForGroup(null);
+      }
+      groups.clear();
     }
-    groups.removeAllElements();
   }
 
   /**    */
   public void deleteGroup(SequenceGroup g)
   {
-    if (groups.contains(g))
+    synchronized (groups)
     {
-      removeAnnotationForGroup(g);
-      groups.removeElement(g);
+      if (groups.contains(g))
+      {
+        removeAnnotationForGroup(g);
+        groups.remove(g);
+      }
     }
   }
 
@@ -598,12 +621,13 @@ public class Alignment implements AlignmentI
   public void setGapCharacter(char gc)
   {
     gapCharacter = gc;
-
-    for (int i = 0; i < sequences.size(); i++)
+    synchronized (sequences)
     {
-      Sequence seq = (Sequence) sequences.elementAt(i);
-      seq.setSequence(seq.getSequenceAsString().replace('.', gc)
-              .replace('-', gc).replace(' ', gc));
+      for (SequenceI seq : sequences)
+      {
+        seq.setSequence(seq.getSequenceAsString().replace('.', gc)
+                .replace('-', gc).replace(' ', gc));
+      }
     }
   }
 
@@ -1054,16 +1078,21 @@ public class Alignment implements AlignmentI
 
   public CigarArray getCompactAlignment()
   {
-    SeqCigar alseqs[] = new SeqCigar[sequences.size()];
-    for (int i = 0; i < sequences.size(); i++)
+    synchronized (sequences)
     {
-      alseqs[i] = new SeqCigar((SequenceI) sequences.elementAt(i));
+      SeqCigar alseqs[] = new SeqCigar[sequences.size()];
+      int i = 0;
+      for (SequenceI seq : sequences)
+      {
+        alseqs[i++] = new SeqCigar(seq);
+      }
+      CigarArray cal = new CigarArray(alseqs);
+      cal.addOperation(CigarArray.M, getWidth());
+      return cal;
     }
-    CigarArray cal = new CigarArray(alseqs);
-    cal.addOperation(CigarArray.M, getWidth());
-    return cal;
   }
 
+  @Override
   public void setProperty(Object key, Object value)
   {
     if (alignmentProperties == null)
@@ -1187,6 +1216,10 @@ public class Alignment implements AlignmentI
 
   public void append(AlignmentI toappend)
   {
+    if (toappend == this)
+    {
+      System.err.println("Self append may cause a deadlock.");
+    }
     // TODO test this method for a future 2.5 release
     // currently tested for use in jalview.gui.SequenceFetcher
     boolean samegap = toappend.getGapCharacter() == getGapCharacter();
@@ -1194,26 +1227,27 @@ public class Alignment implements AlignmentI
     boolean hashidden = toappend.getHiddenSequences() != null
             && toappend.getHiddenSequences().hiddenSequences != null;
     // get all sequences including any hidden ones
-    Vector sqs = (hashidden) ? toappend.getHiddenSequences()
+    List<SequenceI> sqs = (hashidden) ? toappend.getHiddenSequences()
             .getFullAlignment().getSequences() : toappend.getSequences();
     if (sqs != null)
     {
-      Enumeration sq = sqs.elements();
-      while (sq.hasMoreElements())
+      synchronized (sqs)
       {
-        SequenceI addedsq = (SequenceI) sq.nextElement();
-        if (!samegap)
+        for (SequenceI addedsq : sqs)
         {
-          char[] oldseq = addedsq.getSequence();
-          for (int c = 0; c < oldseq.length; c++)
+          if (!samegap)
           {
-            if (oldseq[c] == oldc)
+            char[] oldseq = addedsq.getSequence();
+            for (int c = 0; c < oldseq.length; c++)
             {
-              oldseq[c] = gapCharacter;
+              if (oldseq[c] == oldc)
+              {
+                oldseq[c] = gapCharacter;
+              }
             }
           }
+          addSequence(addedsq);
         }
-        addSequence(addedsq);
       }
     }
     AlignmentAnnotation[] alan = toappend.getAlignmentAnnotation();