JAL-2822 JAL-2684 only create dataset seq for an edit as needed, adjust start/end...
authorJim Procter <jprocter@issues.jalview.org>
Tue, 7 Nov 2017 15:57:26 +0000 (15:57 +0000)
committerJim Procter <jprocter@issues.jalview.org>
Tue, 7 Nov 2017 15:57:26 +0000 (15:57 +0000)
src/jalview/commands/EditCommand.java

index 50822ec..d02dbc3 100644 (file)
@@ -732,6 +732,7 @@ public class EditCommand implements CommandI
     {
       boolean newDSWasNeeded = command.oldds != null
               && command.oldds[i] != null;
+      boolean newStartEndWasNeeded = command.oldStartEnd!=null && command.oldStartEnd[i]!=null;
 
       /**
        * cut addHistoryItem(new EditCommand("Cut Sequences", EditCommand.CUT,
@@ -744,6 +745,11 @@ public class EditCommand implements CommandI
        * EditCommand.PASTE, sequences, 0, alignment.getWidth(), alignment) );
        * 
        */
+
+      Range beforeEditedPositions = command.seqs[i].findPositions(1, start);
+      Range afterEditedPositions = command.seqs[i]
+              .findPositions(start + end + 1, command.seqs[i].getLength());
+      
       oldstring = command.seqs[i].getSequenceAsString();
       tmp = new StringBuffer(oldstring.substring(0, start));
       tmp.append(command.string[i]);
@@ -757,35 +763,100 @@ public class EditCommand implements CommandI
       command.string[i] = oldstring.substring(start, end).toCharArray();
       String nogapold = AlignSeq.extractGaps(Comparison.GapChars,
               new String(command.string[i]));
+
       if (!nogaprep.toLowerCase().equals(nogapold.toLowerCase()))
       {
+        // probably need a new dataset sequence
         if (newDSWasNeeded)
         {
+          // then just switch the dataset sequence
           SequenceI oldds = command.seqs[i].getDatasetSequence();
           command.seqs[i].setDatasetSequence(command.oldds[i]);
           command.oldds[i] = oldds;
         }
         else
+        if (newStartEndWasNeeded)
         {
-          if (command.oldds == null)
-          {
-            command.oldds = new SequenceI[command.seqs.length];
-          }
-          command.oldds[i] = command.seqs[i].getDatasetSequence();
-          SequenceI newds = new Sequence(
-                  command.seqs[i].getDatasetSequence());
-          String fullseq, osp = newds.getSequenceAsString();
+          Range newStart = command.oldStartEnd[i];
+          command.oldStartEnd[i] = new Range(command.seqs[i].getStart(),
+                  command.seqs[i].getEnd());
+          command.seqs[i].setStart(newStart.getBegin());
+          command.seqs[i].setEnd(newStart.getEnd());
+        }
+        else         
+        {
+          // first edit the original dataset sequence string
+          SequenceI oldds = command.seqs[i].getDatasetSequence();
+          String fullseq, osp = oldds.getSequenceAsString();
+
           fullseq = osp.substring(0, ipos) + nogaprep
                   + osp.substring(ipos + nogaprep.length());
-          newds.setSequence(fullseq.toUpperCase());
-          // TODO: JAL-1131 ensure newly created dataset sequence is added to
-          // the set of
-          // dataset sequences associated with the alignment.
-          // TODO: JAL-1131 fix up any annotation associated with new dataset
-          // sequence to ensure that original sequence/annotation relationships
-          // are preserved.
-          command.seqs[i].setDatasetSequence(newds);
 
+          // and check if new sequence data is different..
+          if (!fullseq.equalsIgnoreCase(osp))
+          {
+            // old ds and edited ds are different, so
+            // create the new dataset sequence
+            SequenceI newds = new Sequence(oldds);
+            newds.setSequence(fullseq.toUpperCase());
+
+            if (command.oldds == null)
+            {
+              command.oldds = new SequenceI[command.seqs.length];
+            }
+            command.oldds[i] = command.seqs[i].getDatasetSequence();
+            // TODO: JAL-1131 ensure newly created dataset sequence is added to
+            // the set of
+            // dataset sequences associated with the alignment.
+            // TODO: JAL-1131 fix up any annotation associated with new dataset
+            // sequence to ensure that original sequence/annotation
+            // relationships
+            // are preserved.
+            command.seqs[i].setDatasetSequence(newds);
+          }
+          else
+          {
+            if (command.oldStartEnd == null)
+            {
+              command.oldStartEnd = new Range[command.seqs.length];
+            }
+            command.oldStartEnd[i] = new Range(command.seqs[i].getStart(),
+                    command.seqs[i].getEnd());
+            if (beforeEditedPositions != null
+                    && afterEditedPositions == null)
+            {
+              // modification at end
+              command.seqs[i].setEnd(
+                      beforeEditedPositions.getEnd() + nogaprep.length());
+            }
+            else if (afterEditedPositions != null
+                    && beforeEditedPositions == null)
+            {
+              // modification at start
+              command.seqs[i].setStart(
+                      afterEditedPositions.getBegin() - nogaprep.length());
+            }
+            else
+            {
+              // edit covered both start and end. Here we can only guess the
+              // new
+              // start/end
+              String nogapalseq = jalview.analysis.AlignSeq.extractGaps(
+                      jalview.util.Comparison.GapChars,
+                      command.seqs[i].getSequenceAsString().toUpperCase());
+              int newStart = command.seqs[i].getDatasetSequence()
+                      .getSequenceAsString().indexOf(nogapalseq);
+              if (newStart == -1)
+              {
+                throw new Error(
+                        "Implementation Error: could not locate start/end "
+                                + "in dataset sequence after an edit of the sequence string");
+              }
+              int newEnd = newStart + nogapalseq.length() - 1;
+              command.seqs[i].setStart(newStart);
+              command.seqs[i].setEnd(newEnd);
+            }
+          }
         }
       }
       tmp = null;
@@ -1327,6 +1398,11 @@ public class EditCommand implements CommandI
   {
     public SequenceI[] oldds;
 
+    /**
+     * start and end of sequence prior to edit
+     */
+    public Range[] oldStartEnd;
+
     boolean fullAlignmentHeight = false;
 
     Map<SequenceI, AlignmentAnnotation[]> deletedAnnotationRows;