JAL-2541 clean unit test of cut/undo (ungapped sequence)
authorgmungoc <g.m.carstairs@dundee.ac.uk>
Wed, 28 Jun 2017 07:27:10 +0000 (08:27 +0100)
committergmungoc <g.m.carstairs@dundee.ac.uk>
Thu, 14 Sep 2017 10:10:42 +0000 (11:10 +0100)
src/jalview/commands/EditCommand.java
test/jalview/commands/EditCommandTest.java

index 7dbcd6d..6484224 100644 (file)
@@ -593,8 +593,6 @@ public class EditCommand implements CommandI
 
     for (int i = 0; i < command.seqs.length; i++)
     {
-      int start = 0;
-      int end = 0;
       boolean newDSNeeded = false;
       boolean newDSWasNeeded = command.oldds != null
               && command.oldds[i] != null;
@@ -629,17 +627,20 @@ public class EditCommand implements CommandI
       // Undo of a delete does not replace original dataset sequence on to
       // alignment sequence.
 
+      int start = 0;
+      int length = 0;
+
       if (command.string != null && command.string[i] != null)
       {
         if (command.position >= tmp.length())
         {
           // This occurs if padding is on, and residues
           // are removed from end of alignment
-          int length = command.position - tmp.length();
-          while (length > 0)
+          int len = command.position - tmp.length();
+          while (len > 0)
           {
             tmp.append(command.gapChar);
-            length--;
+            len--;
           }
         }
         tmp.insert(command.position, command.string[i]);
@@ -647,12 +648,13 @@ public class EditCommand implements CommandI
         {
           if (!Comparison.isGap(command.string[i][s]))
           {
+            length++;
             if (!newDSNeeded)
             {
               newDSNeeded = true;
               start = sequence.findPosition(command.position);
-              end = sequence.findPosition(command.position
-                      + command.number);
+              // end = sequence
+              // .findPosition(command.position + command.number);
             }
             if (sequence.getStart() == start)
             {
@@ -704,7 +706,8 @@ public class EditCommand implements CommandI
           ds.setSequenceFeatures(sequence.getSequenceFeatures());
           sequence.setDatasetSequence(ds);
         }
-        undoCutFeatures(command, i, start, end, sameDatasetSequence);
+        undoCutFeatures(command, command.seqs[i], start, length,
+                sameDatasetSequence);
       }
     }
     adjustAnnotations(command, true, seqWasDeleted, views);
@@ -1117,10 +1120,29 @@ public class EditCommand implements CommandI
     }
   }
 
-  final static void undoCutFeatures(Edit command, int index, final int i,
-          final int j, boolean sameDatasetSequence)
+  /**
+   * Restores features to the state before a Cut.
+   * <ul>
+   * <li>re-add any features deleted by the cut</li>
+   * <li>remove any truncated features created by the cut</li>
+   * <li>shift right any features to the right of the cut</li>
+   * </ul>
+   * 
+   * @param command
+   *          the Cut command
+   * @param seq
+   *          the sequence the Cut applied to
+   * @param start
+   *          the start residue position of the cut
+   * @param length
+   *          the number of residues cut
+   * @param sameDatasetSequence
+   *          true if dataset sequence and frame of reference were left
+   *          unchanged by the Cut
+   */
+  final static void undoCutFeatures(Edit command, SequenceI seq,
+          final int start, final int length, boolean sameDatasetSequence)
   {
-    SequenceI seq = command.seqs[index];
     SequenceI sequence = seq.getDatasetSequence();
     if (sequence == null)
     {
@@ -1128,12 +1150,41 @@ public class EditCommand implements CommandI
     }
 
     /*
-     * shift right features that lie to the right of the restored cut
-     * (but not if dataset sequence unchanged - coordinates left unchanged by Cut)
+     * shift right features that lie to the right of the restored cut (but not 
+     * if dataset sequence unchanged - so coordinates were changed by Cut)
      */
     if (!sameDatasetSequence)
     {
-      seq.getFeatures().shiftFeatures(i + 1, j - i);
+      /*
+       * shift right all features right of and not 
+       * contiguous with the cut position
+       */
+      seq.getFeatures().shiftFeatures(start + 1, length);
+
+      /*
+       * shift right any features that start at the cut position,
+       * unless they were truncated
+       */
+      List<SequenceFeature> sfs = seq.findFeatures(start, start);
+      for (SequenceFeature sf : sfs)
+      {
+        if (sf.getBegin() == start)
+        {
+          if (!command.truncatedFeatures.containsKey(seq)
+                  || !command.truncatedFeatures.get(seq).contains(sf))
+          {
+            /*
+             * feature was shifted left to cut position (not truncated),
+             * so shift it back right
+             */
+            SequenceFeature shifted = new SequenceFeature(sf, sf.getBegin()
+                    + length, sf.getEnd() + length, sf.getFeatureGroup(),
+                    sf.getScore());
+            seq.addSequenceFeature(shifted);
+            seq.deleteFeature(sf);
+          }
+        }
+      }
     }
 
     /*
index ac47555..a415338 100644 (file)
@@ -772,7 +772,7 @@ public class EditCommandTest
          * number of features within the cut region i.e. by
          * func(length of cut)
          */
-        String msg = String.format("Cut %d-%d ", from, to);
+        String msg = String.format("Cut %d-%d ", from + 1, to + 1);
         if (to - from == 4)
         {
           // all columns were cut