JAL-2046 safer createDatasetSequence manipulates private fields and moves sequenceFea...
[jalview.git] / src / jalview / datamodel / Sequence.java
index 9f65f71..6f1b403 100755 (executable)
@@ -219,6 +219,8 @@ public class Sequence extends ASequence implements SequenceI
     initSeqAndName(seq.getName(), seq.getSequence(), seq.getStart(),
             seq.getEnd());
     description = seq.getDescription();
+    sourceDBRef = seq.getSourceDBRef() == null ? null : new DBRefEntry(
+            seq.getSourceDBRef());
     if (seq.getSequenceFeatures() != null)
     {
       SequenceFeature[] sf = seq.getSequenceFeatures();
@@ -228,10 +230,10 @@ public class Sequence extends ASequence implements SequenceI
       }
     }
     setDatasetSequence(seq.getDatasetSequence());
-    if (datasetSequence == null && seq.getDBRef() != null)
+    if (datasetSequence == null && seq.getDBRefs() != null)
     {
       // only copy DBRefs if we really are a dataset sequence
-      DBRefEntry[] dbr = seq.getDBRef();
+      DBRefEntry[] dbr = seq.getDBRefs();
       for (int i = 0; i < dbr.length; i++)
       {
         addDBRef(new DBRefEntry(dbr[i]));
@@ -264,11 +266,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));
       }
     }
   }
@@ -288,6 +289,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];
@@ -419,7 +421,7 @@ public class Sequence extends ASequence implements SequenceI
   @Override
   public Vector<PDBEntry> getAllPDBEntries()
   {
-    return pdbIds;
+    return pdbIds == null ? new Vector<PDBEntry>() : pdbIds;
   }
 
   /**
@@ -610,17 +612,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];
     }
@@ -911,18 +911,18 @@ public class Sequence extends ASequence implements SequenceI
   }
 
   @Override
-  public void setDBRef(DBRefEntry[] dbref)
+  public void setDBRefs(DBRefEntry[] dbref)
   {
     dbrefs = dbref;
   }
 
   @Override
-  public DBRefEntry[] getDBRef()
+  public DBRefEntry[] getDBRefs()
   {
     if (dbrefs == null && datasetSequence != null
             && this != datasetSequence)
     {
-      return datasetSequence.getDBRef();
+      return datasetSequence.getDBRefs();
     }
     return dbrefs;
   }
@@ -930,6 +930,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];
@@ -963,6 +964,7 @@ public class Sequence extends ASequence implements SequenceI
   @Override
   public void setDatasetSequence(SequenceI seq)
   {
+    // TODO check for circular reference before setting?
     datasetSequence = seq;
   }
 
@@ -1072,20 +1074,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.setDBRef(getDBRef());
-      setDBRef(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);
@@ -1255,7 +1264,7 @@ public class Sequence extends ASequence implements SequenceI
       }
     }
     // transfer database references
-    DBRefEntry[] entryRefs = entry.getDBRef();
+    DBRefEntry[] entryRefs = entry.getDBRefs();
     if (entryRefs != null)
     {
       for (int r = 0; r < entryRefs.length; r++)