JAL-2541 revised cut with features (work in progress)
[jalview.git] / src / jalview / commands / EditCommand.java
index cac843f..5248dc9 100644 (file)
  */
 package jalview.commands;
 
+import jalview.analysis.AlignSeq;
 import jalview.datamodel.AlignmentAnnotation;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.Annotation;
 import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
+import jalview.util.Comparison;
 import jalview.util.ReverseListIterator;
 import jalview.util.StringUtils;
 
@@ -559,12 +561,21 @@ public class EditCommand implements CommandI
             }
             command.oldds[i] = oldds;
             // FIXME JAL-2541 JAL-2526 get correct positions if on a gap
-            adjustFeatures(
-                    command,
-                    i,
-                    sequence.findPosition(command.position),
-                    sequence.findPosition(command.position + command.number),
-                    false);
+            List<SequenceFeature[]> amendedFeatures = sequence
+                    .adjustFeatures(command.position, command.position
+                            + command.number - 1);
+            if (command.editedFeatures == null)
+            {
+              command.editedFeatures = new HashMap<>();
+            }
+            command.editedFeatures.put(sequence, amendedFeatures);
+            //
+            // adjustFeatures(
+            // command,
+            // i,
+            // sequence.findPosition(command.position),
+            // sequence.findPosition(command.position + command.number),
+            // false);
           }
         }
       }
@@ -599,7 +610,8 @@ public class EditCommand implements CommandI
     {
       newDSNeeded = false;
       newDSWasNeeded = command.oldds != null && command.oldds[i] != null;
-      if (command.seqs[i].getLength() < 1)
+      SequenceI sequence = command.seqs[i];
+      if (sequence.getLength() < 1)
       {
         // ie this sequence was deleted, we need to
         // readd it to the alignment
@@ -610,21 +622,21 @@ public class EditCommand implements CommandI
           {
             if (!(command.alIndex[i] < 0))
             {
-              sequences.add(command.alIndex[i], command.seqs[i]);
+              sequences.add(command.alIndex[i], sequence);
             }
           }
         }
         else
         {
-          command.al.addSequence(command.seqs[i]);
+          command.al.addSequence(sequence);
         }
         seqWasDeleted = true;
       }
-      newstart = command.seqs[i].getStart();
-      newend = command.seqs[i].getEnd();
+      newstart = sequence.getStart();
+      newend = sequence.getEnd();
 
       tmp = new StringBuffer();
-      tmp.append(command.seqs[i].getSequence());
+      tmp.append(sequence.getSequence());
       // Undo of a delete does not replace original dataset sequence on to
       // alignment sequence.
 
@@ -644,16 +656,18 @@ public class EditCommand implements CommandI
         tmp.insert(command.position, command.string[i]);
         for (int s = 0; s < command.string[i].length; s++)
         {
-          if (jalview.schemes.ResidueProperties.aaIndex[command.string[i][s]] != 23)
+          // if (jalview.schemes.ResidueProperties.aaIndex[command.string[i][s]]
+          // != 23)
+          if (!Comparison.isGap(command.string[i][s]))
           {
             if (!newDSNeeded)
             {
               newDSNeeded = true;
-              start = command.seqs[i].findPosition(command.position);
-              end = command.seqs[i]
-                      .findPosition(command.position + command.number);
+              start = sequence.findPosition(command.position);
+              end = sequence.findPosition(command.position
+                      + command.number);
             }
-            if (command.seqs[i].getStart() == start)
+            if (sequence.getStart() == start)
             {
               newstart--;
             }
@@ -666,12 +680,12 @@ public class EditCommand implements CommandI
         command.string[i] = null;
       }
 
-      command.seqs[i].setSequence(tmp.toString());
-      command.seqs[i].setStart(newstart);
-      command.seqs[i].setEnd(newend);
+      sequence.setSequence(tmp.toString());
+      sequence.setStart(newstart);
+      sequence.setEnd(newend);
       if (newDSNeeded)
       {
-        if (command.seqs[i].getDatasetSequence() != null)
+        if (sequence.getDatasetSequence() != null)
         {
           SequenceI ds;
           if (newDSWasNeeded)
@@ -682,21 +696,20 @@ public class EditCommand implements CommandI
           {
             // make a new DS sequence
             // use new ds mechanism here
-            ds = new Sequence(command.seqs[i].getName(),
-                    jalview.analysis.AlignSeq.extractGaps(
-                            jalview.util.Comparison.GapChars,
-                            command.seqs[i].getSequenceAsString()),
-                    command.seqs[i].getStart(), command.seqs[i].getEnd());
-            ds.setDescription(command.seqs[i].getDescription());
+            String ungapped = AlignSeq.extractGaps(Comparison.GapChars,
+                    sequence.getSequenceAsString());
+            ds = new Sequence(sequence.getName(), ungapped,
+                    sequence.getStart(), sequence.getEnd());
+            ds.setDescription(sequence.getDescription());
           }
           if (command.oldds == null)
           {
             command.oldds = new SequenceI[command.seqs.length];
           }
-          command.oldds[i] = command.seqs[i].getDatasetSequence();
-          command.seqs[i].setDatasetSequence(ds);
+          command.oldds[i] = sequence.getDatasetSequence();
+          sequence.setDatasetSequence(ds);
         }
-        adjustFeatures(command, i, start, end, true);
+        undoCutFeatures(command, i, start, end);
       }
     }
     adjustAnnotations(command, true, seqWasDeleted, views);
@@ -1109,8 +1122,8 @@ public class EditCommand implements CommandI
     }
   }
 
-  final static void adjustFeatures(Edit command, int index, final int i,
-          final int j, boolean insert)
+  final static void undoCutFeatures(Edit command, int index, final int i,
+          final int j)
   {
     SequenceI seq = command.seqs[index];
     SequenceI sequence = seq.getDatasetSequence();
@@ -1119,87 +1132,101 @@ public class EditCommand implements CommandI
       sequence = seq;
     }
 
-    if (insert)
+    /*
+     * insert == true for an Undo of a Cut; restore the original features
+     * and delete the amended ones
+     */
+    if (true)
     {
+      // TODO shift right features that lie to the right of the restored cut
+      // (add a start position parameter to SequenceFeatures.shift)
+
       if (command.editedFeatures != null
               && command.editedFeatures.containsKey(seq))
       {
-        sequence.setSequenceFeatures(command.editedFeatures.get(seq));
+        for (SequenceFeature[] toRestore : command.editedFeatures.get(seq))
+        {
+          sequence.addSequenceFeature(toRestore[0]);
+          if (toRestore[1] != null)
+          {
+            sequence.deleteFeature(toRestore[1]);
+          }
+        }
       }
-
       return;
     }
 
-    List<SequenceFeature> sf = sequence.getFeatures()
-            .getPositionalFeatures();
-
-    if (sf.isEmpty())
-    {
-      return;
-    }
-
-    List<SequenceFeature> oldsf = new ArrayList<SequenceFeature>();
-
-    int cSize = j - i;
-
-    for (SequenceFeature feature : sf)
-    {
-      SequenceFeature copy = new SequenceFeature(feature);
-
-      oldsf.add(copy);
-
-      if (feature.getEnd() < i)
-      {
-        continue;
-      }
-
-      if (feature.getBegin() > j)
-      {
-        int newBegin = copy.getBegin() - cSize;
-        int newEnd = copy.getEnd() - cSize;
-        SequenceFeature newSf = new SequenceFeature(feature, newBegin,
-                newEnd, feature.getFeatureGroup(), feature.getScore());
-        sequence.deleteFeature(feature);
-        sequence.addSequenceFeature(newSf);
-        // feature.setBegin(newBegin);
-        // feature.setEnd(newEnd);
-        continue;
-      }
-
-      int newBegin = feature.getBegin();
-      int newEnd = feature.getEnd();
-      if (newBegin >= i)
-      {
-        newBegin = i;
-        // feature.setBegin(i);
-      }
-
-      if (newEnd < j)
-      {
-        newEnd = j - 1;
-        // feature.setEnd(j - 1);
-      }
-      newEnd = newEnd - cSize;
-      // feature.setEnd(feature.getEnd() - (cSize));
-
-      sequence.deleteFeature(feature);
-      if (newEnd >= newBegin)
-      {
-        sequence.addSequenceFeature(new SequenceFeature(feature, newBegin,
-                newEnd, feature.getFeatureGroup(), feature.getScore()));
-      }
-      // if (feature.getBegin() > feature.getEnd())
-      // {
-      // sequence.deleteFeature(feature);
-      // }
-    }
-
-    if (command.editedFeatures == null)
-    {
-      command.editedFeatures = new Hashtable<SequenceI, List<SequenceFeature>>();
-    }
-
-    command.editedFeatures.put(seq, oldsf);
+    // List<SequenceFeature> sf = sequence.getFeatures()
+    // .getPositionalFeatures();
+    //
+    // if (sf.isEmpty())
+    // {
+    // return;
+    // }
+    //
+    // List<SequenceFeature> oldsf = new ArrayList<SequenceFeature>();
+    //
+    // int cSize = j - i;
+    //
+    // for (SequenceFeature feature : sf)
+    // {
+    // SequenceFeature copy = new SequenceFeature(feature);
+    //
+    // oldsf.add(copy);
+    //
+    // if (feature.getEnd() < i)
+    // {
+    // continue;
+    // }
+    //
+    // if (feature.getBegin() > j)
+    // {
+    // int newBegin = copy.getBegin() - cSize;
+    // int newEnd = copy.getEnd() - cSize;
+    // SequenceFeature newSf = new SequenceFeature(feature, newBegin,
+    // newEnd, feature.getFeatureGroup(), feature.getScore());
+    // sequence.deleteFeature(feature);
+    // sequence.addSequenceFeature(newSf);
+    // // feature.setBegin(newBegin);
+    // // feature.setEnd(newEnd);
+    // continue;
+    // }
+    //
+    // int newBegin = feature.getBegin();
+    // int newEnd = feature.getEnd();
+    // if (newBegin >= i)
+    // {
+    // newBegin = i;
+    // // feature.setBegin(i);
+    // }
+    //
+    // if (newEnd < j)
+    // {
+    // newEnd = j - 1;
+    // // feature.setEnd(j - 1);
+    // }
+    // newEnd = newEnd - cSize;
+    // // feature.setEnd(feature.getEnd() - (cSize));
+    //
+    // sequence.deleteFeature(feature);
+    // if (newEnd >= newBegin)
+    // {
+    // sequence.addSequenceFeature(new SequenceFeature(feature, newBegin,
+    // newEnd, feature.getFeatureGroup(), feature.getScore()));
+    // }
+    // // if (feature.getBegin() > feature.getEnd())
+    // // {
+    // // sequence.deleteFeature(feature);
+    // // }
+    // }
+    //
+    // if (command.editedFeatures == null)
+    // {
+    // command.editedFeatures = new Hashtable<SequenceI,
+    // List<SequenceFeature>>();
+    // }
+    //
+    // command.editedFeatures.put(seq, oldsf);
 
   }
 
@@ -1319,11 +1346,11 @@ public class EditCommand implements CommandI
 
     boolean fullAlignmentHeight = false;
 
-    Hashtable<SequenceI, AlignmentAnnotation[]> deletedAnnotationRows;
+    Map<SequenceI, AlignmentAnnotation[]> deletedAnnotationRows;
 
-    Hashtable<String, Annotation[]> deletedAnnotations;
+    Map<String, Annotation[]> deletedAnnotations;
 
-    Hashtable<SequenceI, List<SequenceFeature>> editedFeatures;
+    Map<SequenceI, List<SequenceFeature[]>> editedFeatures;
 
     AlignmentI al;