+ /**
+ * Returns the list of edit commands wrapped by this object.
+ *
+ * @return
+ */
+ public List<Edit> getEdits()
+ {
+ return this.edits;
+ }
+
+ /**
+ * Returns a map whose keys are the dataset sequences, and values their
+ * aligned sequences before the command edit list was applied. The aligned
+ * sequences are copies, which may be updated without affecting the originals.
+ *
+ * The command holds references to the aligned sequences (after editing). If
+ * the command is an 'undo',then the prior state is simply the aligned state.
+ * Otherwise, we have to derive the prior state by working backwards through
+ * the edit list to infer the aligned sequences before editing.
+ *
+ * Note: an alternative solution would be to cache the 'before' state of each
+ * edit, but this would be expensive in space in the common case that the
+ * original is never needed (edits are not mirrored).
+ *
+ * @return
+ * @throws IllegalStateException
+ * on detecting an edit command of a type that can't be unwound
+ */
+ public Map<SequenceI, SequenceI> priorState(boolean forUndo)
+ {
+ Map<SequenceI, SequenceI> result = new HashMap<SequenceI, SequenceI>();
+ if (getEdits() == null)
+ {
+ return result;
+ }
+ if (forUndo)
+ {
+ for (Edit e : getEdits())
+ {
+ for (SequenceI seq : e.getSequences())
+ {
+ SequenceI ds = seq.getDatasetSequence();
+ SequenceI preEdit = result.get(ds);
+ if (preEdit == null)
+ {
+ preEdit = new Sequence("", seq.getSequenceAsString());
+ preEdit.setDatasetSequence(ds);
+ result.put(ds, preEdit);
+ }
+ }
+ }
+ return result;
+ }
+
+ /*
+ * Work backwards through the edit list, deriving the sequences before each
+ * was applied. The final result is the sequence set before any edits.
+ */
+ Iterator<Edit> edits = new ReverseListIterator<Edit>(getEdits());
+ while (edits.hasNext())
+ {
+ Edit oldEdit = edits.next();
+ Action action = oldEdit.getAction();
+ int position = oldEdit.getPosition();
+ int number = oldEdit.getNumber();
+ final char gap = oldEdit.getGapCharacter();
+ for (SequenceI seq : oldEdit.getSequences())
+ {
+ SequenceI ds = seq.getDatasetSequence();
+ SequenceI preEdit = result.get(ds);
+ if (preEdit == null)
+ {
+ preEdit = new Sequence("", seq.getSequenceAsString());
+ preEdit.setDatasetSequence(ds);
+ result.put(ds, preEdit);
+ }
+ /*
+ * 'Undo' this edit action on the sequence (updating the value in the
+ * map).
+ */
+ if (ds != null)
+ {
+ if (action == Action.DELETE_GAP)
+ {
+ preEdit.setSequence(new String(StringUtils.insertCharAt(
+ preEdit.getSequence(), position,
+ number, gap)));
+ }
+ else if (action == Action.INSERT_GAP)
+ {
+ preEdit.setSequence(new String(StringUtils.deleteChars(
+ preEdit.getSequence(), position, position + number)));
+ }
+ else
+ {
+ System.err.println("Can't undo edit action " + action);
+ // throw new IllegalStateException("Can't undo edit action " +
+ // action);
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ public class Edit