JAL-2046 explicitly copy char[] when cloning sequence data for copy-constructor/deriv...
[jalview.git] / src / jalview / datamodel / Sequence.java
index a2513ba..cb3ae70 100755 (executable)
@@ -25,6 +25,7 @@ import jalview.api.DBRefEntryI;
 import jalview.util.StringUtils;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Enumeration;
 import java.util.List;
 import java.util.Vector;
@@ -216,8 +217,12 @@ public class Sequence extends ASequence implements SequenceI
   protected void initSeqFrom(SequenceI seq,
           AlignmentAnnotation[] alAnnotation)
   {
-    initSeqAndName(seq.getName(), seq.getSequence(), seq.getStart(),
+    {
+      char[] oseq = seq.getSequence();
+      initSeqAndName(seq.getName(), Arrays.copyOf(oseq, oseq.length),
+              seq.getStart(),
             seq.getEnd());
+    }
     description = seq.getDescription();
     sourceDBRef = seq.getSourceDBRef() == null ? null : new DBRefEntry(
             seq.getSourceDBRef());
@@ -266,11 +271,10 @@ public class Sequence extends ASequence implements SequenceI
     }
     if (seq.getAllPDBEntries() != null)
     {
-      Vector ids = seq.getAllPDBEntries();
-      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));
       }
     }
   }
@@ -290,6 +294,7 @@ public class Sequence extends ASequence implements SequenceI
   @Override
   public synchronized void addSequenceFeature(SequenceFeature sf)
   {
+    // TODO add to dataset sequence instead if there is one?
     if (sequenceFeatures == null)
     {
       sequenceFeatures = new SequenceFeature[0];
@@ -612,17 +617,15 @@ public class Sequence extends ASequence implements SequenceI
   }
 
   /**
-   * DOCUMENT ME!
-   * 
-   * @param i
-   *          DOCUMENT ME!
+   * Returns the character of the aligned sequence at the given position (base
+   * zero), or space if the position is not within the sequence's bounds
    * 
-   * @return DOCUMENT ME!
+   * @return
    */
   @Override
   public char getCharAt(int i)
   {
-    if (i < sequence.length)
+    if (i >= 0 && i < sequence.length)
     {
       return sequence[i];
     }
@@ -932,6 +935,7 @@ public class Sequence extends ASequence 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];
@@ -965,6 +969,7 @@ public class Sequence extends ASequence implements SequenceI
   @Override
   public void setDatasetSequence(SequenceI seq)
   {
+    // TODO check for circular reference before setting?
     datasetSequence = seq;
   }
 
@@ -1074,20 +1079,27 @@ public class Sequence extends ASequence implements SequenceI
   {
     if (datasetSequence == null)
     {
-      datasetSequence = new Sequence(getName(), AlignSeq.extractGaps(
+      Sequence dsseq = new Sequence(getName(), AlignSeq.extractGaps(
               jalview.util.Comparison.GapChars, getSequenceAsString()),
               getStart(), getEnd());
-      datasetSequence.setSequenceFeatures(getSequenceFeatures());
-      datasetSequence.setDescription(getDescription());
-      setSequenceFeatures(null);
-      // move database references onto dataset sequence
-      datasetSequence.setDBRefs(getDBRefs());
-      setDBRefs(null);
-      datasetSequence.setPDBId(getAllPDBEntries());
-      setPDBId(null);
+
+      datasetSequence = dsseq;
+
+      dsseq.setDescription(description);
+      // move features and database references onto dataset sequence
+      dsseq.sequenceFeatures = sequenceFeatures;
+      sequenceFeatures=null;
+      dsseq.dbrefs = dbrefs;
+      dbrefs=null;
+      // TODO: search and replace any references to this sequence with
+      // references to the dataset sequence in Mappings on dbref
+      dsseq.pdbIds = pdbIds;
+      pdbIds = null;
       datasetSequence.updatePDBIds();
       if (annotation != null)
       {
+        // annotation is cloned rather than moved, to preserve what's currently
+        // on the alignment
         for (AlignmentAnnotation aa : annotation)
         {
           AlignmentAnnotation _aa = new AlignmentAnnotation(aa);