Index: /branches/DataPreprocessing Cleanup/HeuristicLab.DataPreprocessing.Views/3.4/DataGridContentView.cs
===================================================================
--- /branches/DataPreprocessing Cleanup/HeuristicLab.DataPreprocessing.Views/3.4/DataGridContentView.cs	(revision 15269)
+++ /branches/DataPreprocessing Cleanup/HeuristicLab.DataPreprocessing.Views/3.4/DataGridContentView.cs	(revision 15270)
@@ -167,5 +167,5 @@
 
       ReplaceTransaction(() => {
-        Content.PreProcessingData.InTransaction(() => {
+        Content.PreprocessingData.InTransaction(() => {
           for (int row = containsHeader ? 1 : 0; row < values.GetLength(1); row++) {
             for (int col = 0; col < values.GetLength(0); col++) {
@@ -177,5 +177,5 @@
               if (string.IsNullOrWhiteSpace(firstRow[i]))
                 firstRow[i] = string.Format("<{0}>", i);
-            Content.PreProcessingData.RenameColumns(firstRow);
+            Content.PreprocessingData.RenameColumns(firstRow);
           }
         });
@@ -224,5 +224,5 @@
       if (e.Button == MouseButtons.Middle) {
         int newIndex = e.ColumnIndex >= 0 ? e.ColumnIndex : 0;
-        Content.PreProcessingData.InsertColumn<double>(newIndex.ToString(), newIndex);
+        Content.PreprocessingData.InsertColumn<double>(newIndex.ToString(), newIndex);
       } else if (e.Button == MouseButtons.Right && Content.SortableView) {
         SortColumn(e.ColumnIndex);
@@ -235,5 +235,5 @@
         if (e.Button == MouseButtons.Middle) {
           int newIndex = e.RowIndex >= 0 ? e.RowIndex : 0;
-          Content.PreProcessingData.InsertRow(newIndex);
+          Content.PreprocessingData.InsertRow(newIndex);
         }
       }
@@ -531,10 +531,10 @@
             medianToolStripMenuItem_Selection.Enabled =
             randomToolStripMenuItem_Column.Enabled =
-            randomToolStripMenuItem_Selection.Enabled = !Content.PreProcessingData.AreAllStringColumns(columnIndices);
+            randomToolStripMenuItem_Selection.Enabled = !Content.PreprocessingData.AreAllStringColumns(columnIndices);
 
           smoothingToolStripMenuItem_Column.Enabled =
             interpolationToolStripMenuItem_Column.Enabled = !dataGridView.SelectedCells.Contains(dataGridView[e.ColumnIndex, 0])
             && !dataGridView.SelectedCells.Contains(dataGridView[e.ColumnIndex, Content.Rows - 1])
-            && !Content.PreProcessingData.AreAllStringColumns(columnIndices);
+            && !Content.PreprocessingData.AreAllStringColumns(columnIndices);
 
           replaceValueOverColumnToolStripMenuItem.Visible = true;
@@ -675,9 +675,9 @@
 
     private void addRowButton_Click(object sender, EventArgs e) {
-      Content.PreProcessingData.InsertRow(Content.Rows);
+      Content.PreprocessingData.InsertRow(Content.Rows);
     }
 
     private void addColumnButton_Click(object sender, EventArgs e) {
-      Content.PreProcessingData.InsertColumn<double>(Content.Columns.ToString(), Content.Columns);
+      Content.PreprocessingData.InsertColumn<double>(Content.Columns.ToString(), Content.Columns);
     }
 
@@ -686,5 +686,5 @@
 
       if (renameDialog.ShowDialog(this) == DialogResult.OK) {
-        Content.PreProcessingData.RenameColumns(renameDialog.ColumnNames);
+        Content.PreprocessingData.RenameColumns(renameDialog.ColumnNames);
       }
     }
@@ -693,6 +693,6 @@
       foreach (DataGridViewColumn column in DataGridView.Columns) {
         var variable = column.HeaderText;
-        bool isInputTarget = Content.PreProcessingData.InputVariables.Contains(variable)
-          || Content.PreProcessingData.TargetVariable == variable;
+        bool isInputTarget = Content.PreprocessingData.InputVariables.Contains(variable)
+          || Content.PreprocessingData.TargetVariable == variable;
         column.Visible = isInputTarget;
       }
Index: /branches/DataPreprocessing Cleanup/HeuristicLab.DataPreprocessing/3.4/Content/CorrelationMatrixContent.cs
===================================================================
--- /branches/DataPreprocessing Cleanup/HeuristicLab.DataPreprocessing/3.4/Content/CorrelationMatrixContent.cs	(revision 15269)
+++ /branches/DataPreprocessing Cleanup/HeuristicLab.DataPreprocessing/3.4/Content/CorrelationMatrixContent.cs	(revision 15270)
@@ -33,5 +33,5 @@
 
     public PreprocessingContext Context { get; private set; }
-    public ITransactionalPreprocessingData PreprocessingData {
+    public IPreprocessingData PreprocessingData {
       get { return Context.Data; }
     }
Index: /branches/DataPreprocessing Cleanup/HeuristicLab.DataPreprocessing/3.4/Content/DataCompletenessChartContent.cs
===================================================================
--- /branches/DataPreprocessing Cleanup/HeuristicLab.DataPreprocessing/3.4/Content/DataCompletenessChartContent.cs	(revision 15269)
+++ /branches/DataPreprocessing Cleanup/HeuristicLab.DataPreprocessing/3.4/Content/DataCompletenessChartContent.cs	(revision 15270)
@@ -32,7 +32,7 @@
     }
 
-    public ITransactionalPreprocessingData PreprocessingData { get; private set; }
+    public IPreprocessingData PreprocessingData { get; private set; }
 
-    public DataCompletenessChartContent(ITransactionalPreprocessingData preprocessingData) {
+    public DataCompletenessChartContent(IPreprocessingData preprocessingData) {
       PreprocessingData = preprocessingData;
     }
Index: /branches/DataPreprocessing Cleanup/HeuristicLab.DataPreprocessing/3.4/Content/DataGridContent.cs
===================================================================
--- /branches/DataPreprocessing Cleanup/HeuristicLab.DataPreprocessing/3.4/Content/DataGridContent.cs	(revision 15269)
+++ /branches/DataPreprocessing Cleanup/HeuristicLab.DataPreprocessing/3.4/Content/DataGridContent.cs	(revision 15270)
@@ -36,5 +36,5 @@
     }
 
-    public ITransactionalPreprocessingData PreProcessingData { get; private set; }
+    public IPreprocessingData PreprocessingData { get; private set; }
 
     public ManipulationLogic ManipulationLogic { get; private set; }
@@ -42,15 +42,15 @@
 
     public int Rows {
-      get { return PreProcessingData.Rows; }
+      get { return PreprocessingData.Rows; }
       set { }
     }
 
     public int Columns {
-      get { return PreProcessingData.Columns; }
+      get { return PreprocessingData.Columns; }
       set { }
     }
 
     public IEnumerable<string> ColumnNames {
-      get { return PreProcessingData.VariableNames; }
+      get { return PreprocessingData.VariableNames; }
       set { }
     }
@@ -71,12 +71,12 @@
 
     public IDictionary<int, IList<int>> Selection {
-      get { return PreProcessingData.Selection; }
-      set { PreProcessingData.Selection = value; }
+      get { return PreprocessingData.Selection; }
+      set { PreprocessingData.Selection = value; }
     }
 
-    public DataGridContent(ITransactionalPreprocessingData preProcessingData, ManipulationLogic theManipulationLogic, FilterLogic theFilterLogic) {
+    public DataGridContent(IPreprocessingData preprocessingData, ManipulationLogic theManipulationLogic, FilterLogic theFilterLogic) {
       ManipulationLogic = theManipulationLogic;
       FilterLogic = theFilterLogic;
-      PreProcessingData = preProcessingData;
+      PreprocessingData = preprocessingData;
     }
 
@@ -90,26 +90,26 @@
 
     public void DeleteRows(IEnumerable<int> rows) {
-      PreProcessingData.DeleteRowsWithIndices(rows);
+      PreprocessingData.DeleteRowsWithIndices(rows);
     }
 
     public void DeleteColumn(int column) {
-      PreProcessingData.DeleteColumn(column);
+      PreprocessingData.DeleteColumn(column);
     }
 
     public bool Validate(string value, out string errorMessage, int columnIndex) {
-      return PreProcessingData.Validate(value, out errorMessage, columnIndex);
+      return PreprocessingData.Validate(value, out errorMessage, columnIndex);
     }
 
     public string GetValue(int rowIndex, int columnIndex) {
-      return PreProcessingData.GetCellAsString(columnIndex, rowIndex);
+      return PreprocessingData.GetCellAsString(columnIndex, rowIndex);
     }
 
     public bool SetValue(string value, int rowIndex, int columnIndex) {
-      return PreProcessingData.SetValue(value, columnIndex, rowIndex);
+      return PreprocessingData.SetValue(value, columnIndex, rowIndex);
     }
 
     public event DataPreprocessingChangedEventHandler Changed {
-      add { PreProcessingData.Changed += value; }
-      remove { PreProcessingData.Changed -= value; }
+      add { PreprocessingData.Changed += value; }
+      remove { PreprocessingData.Changed -= value; }
     }
 
Index: /branches/DataPreprocessing Cleanup/HeuristicLab.DataPreprocessing/3.4/Content/StatisticsContent.cs
===================================================================
--- /branches/DataPreprocessing Cleanup/HeuristicLab.DataPreprocessing/3.4/Content/StatisticsContent.cs	(revision 15269)
+++ /branches/DataPreprocessing Cleanup/HeuristicLab.DataPreprocessing/3.4/Content/StatisticsContent.cs	(revision 15270)
@@ -31,8 +31,8 @@
     }
 
-    public ITransactionalPreprocessingData PreprocessingData { get; private set; }
+    public IPreprocessingData PreprocessingData { get; private set; }
     public StatisticsLogic StatisticsLogic { get; private set; }
 
-    public StatisticsContent(ITransactionalPreprocessingData preProcessingData, StatisticsLogic statisticsLogic) {
+    public StatisticsContent(IPreprocessingData preProcessingData, StatisticsLogic statisticsLogic) {
       PreprocessingData = preProcessingData;
       StatisticsLogic = statisticsLogic;
Index: /branches/DataPreprocessing Cleanup/HeuristicLab.DataPreprocessing/3.4/Data/FilteredPreprocessingData.cs
===================================================================
--- /branches/DataPreprocessing Cleanup/HeuristicLab.DataPreprocessing/3.4/Data/FilteredPreprocessingData.cs	(revision 15269)
+++ /branches/DataPreprocessing Cleanup/HeuristicLab.DataPreprocessing/3.4/Data/FilteredPreprocessingData.cs	(revision 15270)
@@ -25,57 +25,23 @@
 using HeuristicLab.Core;
 using HeuristicLab.Data;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
 using HeuristicLab.Problems.DataAnalysis;
 
 namespace HeuristicLab.DataPreprocessing {
+  [Item("FilteredPreprocessingData", "Represents filtered data used for preprocessing.")]
+  [StorableClass]
   public sealed class FilteredPreprocessingData : NamedItem, IFilteredPreprocessingData {
-    private readonly ITransactionalPreprocessingData originalData;
-    private ITransactionalPreprocessingData filteredData;
-
-    public IntRange TrainingPartition {
-      get { return originalData.TrainingPartition; }
-    }
-
-    public IntRange TestPartition {
-      get { return originalData.TestPartition; }
-    }
-
-    public IList<ITransformation> Transformations {
-      get { return originalData.Transformations; }
-    }
-
-    public IEnumerable<string> VariableNames {
-      get { return ActiveData.VariableNames; }
-    }
-
-    public IList<string> InputVariables { get { return ActiveData.InputVariables; } }
-    public string TargetVariable { get { return ActiveData.TargetVariable; } } // optional
-
-    public IDictionary<int, IList<int>> Selection {
-      get { return originalData.Selection; }
-      set { originalData.Selection = value; }
-    }
-
-    public int Columns {
-      get { return ActiveData.Columns; }
-    }
-
-    public int Rows {
-      get { return ActiveData.Rows; }
-    }
-
-    public ITransactionalPreprocessingData ActiveData {
+
+    [Storable]
+    private readonly IPreprocessingData originalData;
+    [Storable]
+    private IPreprocessingData filteredData;
+
+    public IPreprocessingData ActiveData {
       get { return IsFiltered ? filteredData : originalData; }
     }
 
-    public bool IsUndoAvailable {
-      get { return IsFiltered ? false : originalData.IsUndoAvailable; }
-    }
-
-    public bool IsFiltered {
-      get { return filteredData != null; }
-    }
-
-
-    public FilteredPreprocessingData(ITransactionalPreprocessingData preporcessingData)
+    #region Constructor, Cloning & Persistance
+    public FilteredPreprocessingData(IPreprocessingData preporcessingData)
       : base() {
       originalData = preporcessingData;
@@ -92,4 +58,10 @@
     }
 
+    [StorableConstructor]
+    private FilteredPreprocessingData(bool deserializing)
+      : base(deserializing) { }
+    #endregion
+
+    #region Cells
     public bool IsCellEmpty(int columnIndex, int rowIndex) {
       return ActiveData.IsCellEmpty(columnIndex, rowIndex);
@@ -121,4 +93,20 @@
     }
 
+    public bool SetValue(string value, int columnIndex, int rowIndex) {
+      if (IsFiltered)
+        throw new InvalidOperationException("SetValue not possible while data is filtered");
+      return originalData.SetValue(value, columnIndex, rowIndex);
+    }
+
+    public int Columns {
+      get { return ActiveData.Columns; }
+    }
+
+    public int Rows {
+      get { return ActiveData.Rows; }
+    }
+    #endregion
+
+    #region Rows
     public void InsertRow(int rowIndex) {
       if (IsFiltered)
@@ -133,4 +121,11 @@
 
       originalData.DeleteRow(rowIndex);
+    }
+
+    public void DeleteRowsWithIndices(IEnumerable<int> rows) {
+      if (IsFiltered)
+        throw new InvalidOperationException("DeleteRowsWithIndices not possible while data is filtered");
+
+      originalData.DeleteRowsWithIndices(rows);
     }
 
@@ -160,4 +155,16 @@
     }
 
+    public bool AreAllStringColumns(IEnumerable<int> columnIndices) {
+      return originalData.AreAllStringColumns(columnIndices);
+    }
+    #endregion
+
+    #region Variables
+    public IEnumerable<string> VariableNames {
+      get { return ActiveData.VariableNames; }
+    }
+    public IEnumerable<string> GetDoubleVariableNames() {
+      return originalData.GetDoubleVariableNames();
+    }
     public string GetVariableName(int columnIndex) {
       return ActiveData.GetVariableName(columnIndex);
@@ -172,10 +179,100 @@
     }
 
+    public IList<string> InputVariables {
+      get { return ActiveData.InputVariables; }
+    }
+
+    public string TargetVariable {
+      get { return ActiveData.TargetVariable; }
+    } // optional
+    #endregion
+
+    #region Partitions
+    public IntRange TrainingPartition {
+      get { return originalData.TrainingPartition; }
+    }
+
+    public IntRange TestPartition {
+      get { return originalData.TestPartition; }
+    }
+    #endregion
+
+    #region Transformations
+    public IList<ITransformation> Transformations {
+      get { return originalData.Transformations; }
+    }
+    #endregion
+
+    #region Validation
+    public bool Validate(string value, out string errorMessage, int columnIndex) {
+      return originalData.Validate(value, out errorMessage, columnIndex);
+    }
+    #endregion
+
+    #region Import & Export
+    public void Import(IDataAnalysisProblemData problemData) {
+      if (IsFiltered)
+        throw new InvalidOperationException("Import not possible while data is filtered");
+      originalData.Import(problemData);
+    }
+
     public Dataset ExportToDataset() {
       return originalData.ExportToDataset();
     }
-
+    #endregion
+
+    #region Selection
+    public IDictionary<int, IList<int>> Selection {
+      get { return originalData.Selection; }
+      set { originalData.Selection = value; }
+    }
+
+    public void ClearSelection() {
+      originalData.ClearSelection();
+    }
+
+    public event EventHandler SelectionChanged {
+      add { originalData.SelectionChanged += value; }
+      remove { originalData.SelectionChanged -= value; }
+    }
+    #endregion
+
+    #region Transactions
+    public event DataPreprocessingChangedEventHandler Changed {
+      add { originalData.Changed += value; }
+      remove { originalData.Changed -= value; }
+    }
+
+    public bool IsUndoAvailable {
+      get { return IsFiltered ? false : originalData.IsUndoAvailable; }
+    }
+
+    public void Undo() {
+      if (IsFiltered)
+        throw new InvalidOperationException("Undo not possible while data is filtered");
+
+      originalData.Undo();
+    }
+
+    public void InTransaction(Action action, DataPreprocessingChangedEventType type = DataPreprocessingChangedEventType.Any) {
+      if (IsFiltered)
+        throw new InvalidOperationException("Transaction not possible while data is filtered");
+      originalData.InTransaction(action, type);
+    }
+
+    public void BeginTransaction(DataPreprocessingChangedEventType type) {
+      if (IsFiltered)
+        throw new InvalidOperationException("Transaction not possible while data is filtered");
+      originalData.BeginTransaction(type);
+    }
+
+    public void EndTransaction() {
+      originalData.EndTransaction();
+    }
+    #endregion
+
+    #region Filters
     public void SetFilter(bool[] rowFilters) {
-      filteredData = (ITransactionalPreprocessingData)originalData.Clone();
+      filteredData = (IPreprocessingData)originalData.Clone();
       filteredData.InTransaction(() => {
         for (int row = (rowFilters.Length - 1); row >= 0; --row) {
@@ -210,4 +307,10 @@
     }
 
+    public bool IsFiltered {
+      get { return filteredData != null; }
+    }
+
+    public event EventHandler FilterChanged;
+
     private void OnFilterChanged() {
       if (FilterChanged != null) {
@@ -215,69 +318,4 @@
       }
     }
-
-    public event DataPreprocessingChangedEventHandler Changed {
-      add { originalData.Changed += value; }
-      remove { originalData.Changed -= value; }
-    }
-
-    public bool SetValue(string value, int columnIndex, int rowIndex) {
-      if (IsFiltered)
-        throw new InvalidOperationException("SetValue not possible while data is filtered");
-      return originalData.SetValue(value, columnIndex, rowIndex);
-    }
-
-    public bool AreAllStringColumns(IEnumerable<int> columnIndices) {
-      return originalData.AreAllStringColumns(columnIndices);
-    }
-
-    public void DeleteRowsWithIndices(IEnumerable<int> rows) {
-      if (IsFiltered)
-        throw new InvalidOperationException("DeleteRowsWithIndices not possible while data is filtered");
-
-      originalData.DeleteRowsWithIndices(rows);
-    }
-
-    public void Undo() {
-      if (IsFiltered)
-        throw new InvalidOperationException("Undo not possible while data is filtered");
-
-      originalData.Undo();
-    }
-
-    public void InTransaction(Action action, DataPreprocessingChangedEventType type = DataPreprocessingChangedEventType.Any) {
-      if (IsFiltered)
-        throw new InvalidOperationException("Transaction not possible while data is filtered");
-      originalData.InTransaction(action, type);
-    }
-
-    public void BeginTransaction(DataPreprocessingChangedEventType type) {
-      if (IsFiltered)
-        throw new InvalidOperationException("Transaction not possible while data is filtered");
-      originalData.BeginTransaction(type);
-    }
-
-    public void EndTransaction() {
-      originalData.EndTransaction();
-    }
-
-    public IEnumerable<string> GetDoubleVariableNames() {
-      return originalData.GetDoubleVariableNames();
-    }
-
-    public void ClearSelection() {
-      originalData.ClearSelection();
-    }
-
-    public event EventHandler SelectionChanged {
-      add { originalData.SelectionChanged += value; }
-      remove { originalData.SelectionChanged -= value; }
-    }
-
-    #region IPreprocessingData Members
-    public bool Validate(string value, out string errorMessage, int columnIndex) {
-      return originalData.Validate(value, out errorMessage, columnIndex);
-    }
-
-    public event EventHandler FilterChanged;
     #endregion
   }
Index: /branches/DataPreprocessing Cleanup/HeuristicLab.DataPreprocessing/3.4/Data/IFilteredPreprocessingData.cs
===================================================================
--- /branches/DataPreprocessing Cleanup/HeuristicLab.DataPreprocessing/3.4/Data/IFilteredPreprocessingData.cs	(revision 15269)
+++ /branches/DataPreprocessing Cleanup/HeuristicLab.DataPreprocessing/3.4/Data/IFilteredPreprocessingData.cs	(revision 15270)
@@ -23,5 +23,6 @@
 
 namespace HeuristicLab.DataPreprocessing {
-  public interface IFilteredPreprocessingData : ITransactionalPreprocessingData {
+  public interface IFilteredPreprocessingData : IPreprocessingData {
+    #region Filters
     void SetFilter(bool[] rowFilters);
     void PersistFilter();
@@ -30,4 +31,5 @@
 
     event EventHandler FilterChanged;
+    #endregion
   }
 }
Index: /branches/DataPreprocessing Cleanup/HeuristicLab.DataPreprocessing/3.4/Data/IPreprocessingData.cs
===================================================================
--- /branches/DataPreprocessing Cleanup/HeuristicLab.DataPreprocessing/3.4/Data/IPreprocessingData.cs	(revision 15269)
+++ /branches/DataPreprocessing Cleanup/HeuristicLab.DataPreprocessing/3.4/Data/IPreprocessingData.cs	(revision 15270)
@@ -28,4 +28,5 @@
 namespace HeuristicLab.DataPreprocessing {
   public interface IPreprocessingData : INamedItem {
+    #region Cells
     bool IsCellEmpty(int columnIndex, int rowIndex);
     T GetCell<T>(int columnIndex, int rowIndex);
@@ -40,4 +41,9 @@
     bool SetValue(string value, int columnIndex, int rowIndex);
 
+    int Columns { get; }
+    int Rows { get; }
+    #endregion
+
+    #region Rows
     void InsertRow(int rowIndex);
     void DeleteRow(int rowIndex);
@@ -51,11 +57,7 @@
 
     bool AreAllStringColumns(IEnumerable<int> columnIndices);
-    bool Validate(string value, out string errorMessage, int columnIndex);
+    #endregion
 
-    IntRange TrainingPartition { get; }
-    IntRange TestPartition { get; }
-
-    IList<ITransformation> Transformations { get; }
-
+    #region Variables
     IEnumerable<string> VariableNames { get; }
     IEnumerable<string> GetDoubleVariableNames();
@@ -67,14 +69,40 @@
     IList<string> InputVariables { get; }
     string TargetVariable { get; } // optional
+    #endregion
 
-    int Columns { get; }
-    int Rows { get; }
+    #region Partitions
+    IntRange TrainingPartition { get; }
+    IntRange TestPartition { get; }
+    #endregion
 
+    #region Transformations
+    IList<ITransformation> Transformations { get; }
+    #endregion
+
+    #region Validation
+    bool Validate(string value, out string errorMessage, int columnIndex);
+    #endregion
+
+    #region Import & Export
+    void Import(IDataAnalysisProblemData problemData);
     Dataset ExportToDataset();
+    #endregion
 
+    #region Selection
     IDictionary<int, IList<int>> Selection { get; set; }
     void ClearSelection();
 
     event EventHandler SelectionChanged;
+    #endregion
+
+    #region Transactions
+    event DataPreprocessingChangedEventHandler Changed;
+
+    bool IsUndoAvailable { get; }
+    void Undo();
+    void InTransaction(Action action, DataPreprocessingChangedEventType type = DataPreprocessingChangedEventType.Any);
+    void BeginTransaction(DataPreprocessingChangedEventType type);
+    void EndTransaction();
+    #endregion
   }
 }
Index: anches/DataPreprocessing Cleanup/HeuristicLab.DataPreprocessing/3.4/Data/ITransactionalPreprocessingData.cs
===================================================================
--- /branches/DataPreprocessing Cleanup/HeuristicLab.DataPreprocessing/3.4/Data/ITransactionalPreprocessingData.cs	(revision 15269)
+++ 	(revision )
@@ -1,34 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2016 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
- *
- * This file is part of HeuristicLab.
- *
- * HeuristicLab is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * HeuristicLab is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
- */
-#endregion
-
-using System;
-
-namespace HeuristicLab.DataPreprocessing {
-  public interface ITransactionalPreprocessingData : IPreprocessingData {
-    event DataPreprocessingChangedEventHandler Changed;
-
-    bool IsUndoAvailable { get; }
-    void Undo();
-    void InTransaction(Action action, DataPreprocessingChangedEventType type = DataPreprocessingChangedEventType.Any);
-    void BeginTransaction(DataPreprocessingChangedEventType type);
-    void EndTransaction();
-  }
-}
Index: /branches/DataPreprocessing Cleanup/HeuristicLab.DataPreprocessing/3.4/Data/PreprocessingData.cs
===================================================================
--- /branches/DataPreprocessing Cleanup/HeuristicLab.DataPreprocessing/3.4/Data/PreprocessingData.cs	(revision 15269)
+++ /branches/DataPreprocessing Cleanup/HeuristicLab.DataPreprocessing/3.4/Data/PreprocessingData.cs	(revision 15270)
@@ -23,8 +23,10 @@
 using System.Collections;
 using System.Collections.Generic;
+using System.Globalization;
 using System.Linq;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
 using HeuristicLab.Data;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
 using HeuristicLab.Problems.DataAnalysis;
 
@@ -32,45 +34,23 @@
 
   [Item("PreprocessingData", "Represents data used for preprocessing.")]
-  public abstract class PreprocessingData : NamedItem, IPreprocessingData {
-    public IntRange TrainingPartition { get; set; }
-    public IntRange TestPartition { get; set; }
-
-    public IList<ITransformation> Transformations { get; protected set; }
-
+  [StorableClass]
+  public class PreprocessingData : NamedItem, IPreprocessingData {
+
+    [Storable]
     protected IList<IList> variableValues;
+    [Storable]
     protected IList<string> variableNames;
 
-    public IEnumerable<string> VariableNames {
-      get { return variableNames; }
-    }
-
-    public IEnumerable<string> GetDoubleVariableNames() {
-      var doubleVariableNames = new List<string>();
-      for (int i = 0; i < Columns; ++i) {
-        if (VariableHasType<double>(i)) {
-          doubleVariableNames.Add(variableNames[i]);
-        }
-      }
-      return doubleVariableNames;
-    }
-
-    public IList<string> InputVariables { get; private set; }
-    public string TargetVariable { get; private set; } // optional
-
-    public int Columns {
-      get { return variableNames.Count; }
-    }
-
-    public int Rows {
-      get { return variableValues.Count > 0 ? variableValues[0].Count : 0; }
-    }
-
-    protected IDictionary<int, IList<int>> selection;
-    public IDictionary<int, IList<int>> Selection {
-      get { return selection; }
-      set {
-        selection = value;
-        OnSelectionChanged();
-      }
+    #region Constructor, Cloning & Persistance
+    public PreprocessingData(IDataAnalysisProblemData problemData)
+      : base() {
+      Name = "Preprocessing Data";
+
+      Transformations = new List<ITransformation>();
+      selection = new Dictionary<int, IList<int>>();
+
+      Import(problemData);
+
+      RegisterEventHandler();
     }
 
@@ -88,17 +68,313 @@
       RegisterEventHandler();
     }
-
-    protected PreprocessingData(IDataAnalysisProblemData problemData)
-      : base() {
-      Name = "Preprocessing Data";
-
-      Transformations = new List<ITransformation>();
-      selection = new Dictionary<int, IList<int>>();
-
-      Import(problemData);
-
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PreprocessingData(this, cloner);
+    }
+
+    [StorableConstructor]
+    protected PreprocessingData(bool deserializing)
+      : base(deserializing) { }
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
       RegisterEventHandler();
     }
 
+    private void RegisterEventHandler() {
+      Changed += (s, e) => {
+        switch (e.Type) {
+          case DataPreprocessingChangedEventType.DeleteRow:
+          case DataPreprocessingChangedEventType.Any:
+          case DataPreprocessingChangedEventType.Transformation:
+            int maxRowIndex = Math.Max(0, Rows);
+            TrainingPartition.Start = Math.Min(TrainingPartition.Start, maxRowIndex);
+            TrainingPartition.End = Math.Min(TrainingPartition.End, maxRowIndex);
+            TestPartition.Start = Math.Min(TestPartition.Start, maxRowIndex);
+            TestPartition.End = Math.Min(TestPartition.End, maxRowIndex);
+            break;
+        }
+      };
+    }
+    #endregion
+
+    #region Cells
+    public bool IsCellEmpty(int columnIndex, int rowIndex) {
+      var value = variableValues[columnIndex][rowIndex];
+      return IsMissingValue(value);
+    }
+
+    public T GetCell<T>(int columnIndex, int rowIndex) {
+      return (T)variableValues[columnIndex][rowIndex];
+    }
+
+    public void SetCell<T>(int columnIndex, int rowIndex, T value) {
+      SaveSnapshot(DataPreprocessingChangedEventType.ChangeItem, columnIndex, rowIndex);
+
+      for (int i = Rows; i <= rowIndex; i++)
+        InsertRow(i);
+      for (int i = Columns; i <= columnIndex; i++)
+        InsertColumn<T>(i.ToString(), i);
+
+      variableValues[columnIndex][rowIndex] = value;
+      if (!IsInTransaction)
+        OnChanged(DataPreprocessingChangedEventType.ChangeItem, columnIndex, rowIndex);
+    }
+
+    public string GetCellAsString(int columnIndex, int rowIndex) {
+      return variableValues[columnIndex][rowIndex].ToString();
+    }
+
+    public IList<T> GetValues<T>(int columnIndex, bool considerSelection) {
+      if (considerSelection) {
+        var list = new List<T>();
+        foreach (var rowIdx in selection[columnIndex]) {
+          list.Add((T)variableValues[columnIndex][rowIdx]);
+        }
+        return list;
+      } else {
+        return (IList<T>)variableValues[columnIndex];
+      }
+    }
+
+    public void SetValues<T>(int columnIndex, IList<T> values) {
+      SaveSnapshot(DataPreprocessingChangedEventType.ChangeColumn, columnIndex, -1);
+      if (VariableHasType<T>(columnIndex)) {
+        variableValues[columnIndex] = (IList)values;
+      } else {
+        throw new ArgumentException("The datatype of column " + columnIndex + " must be of type " + variableValues[columnIndex].GetType().Name + " but was " + typeof(T).Name);
+      }
+      if (!IsInTransaction)
+        OnChanged(DataPreprocessingChangedEventType.ChangeColumn, columnIndex, -1);
+    }
+
+    public bool SetValue(string value, int columnIndex, int rowIndex) {
+      bool valid = false;
+      if (VariableHasType<double>(columnIndex)) {
+        double val;
+        valid = double.TryParse(value, out val);
+        if (valid)
+          SetCell(columnIndex, rowIndex, val);
+      } else if (VariableHasType<string>(columnIndex)) {
+        valid = value != null;
+        if (valid)
+          SetCell(columnIndex, rowIndex, value);
+      } else if (VariableHasType<DateTime>(columnIndex)) {
+        DateTime date;
+        valid = DateTime.TryParse(value, out date);
+        if (valid)
+          SetCell(columnIndex, rowIndex, date);
+      } else {
+        throw new ArgumentException("column " + columnIndex + " contains a non supported type.");
+      }
+
+      if (!IsInTransaction)
+        OnChanged(DataPreprocessingChangedEventType.ChangeColumn, columnIndex, -1);
+
+      return valid;
+    }
+
+    public int Columns {
+      get { return variableNames.Count; }
+    }
+
+    public int Rows {
+      get { return variableValues.Count > 0 ? variableValues[0].Count : 0; }
+    }
+
+    public static bool IsMissingValue(object value) {
+      if (value is double) return double.IsNaN((double)value);
+      if (value is string) return string.IsNullOrEmpty((string)value);
+      if (value is DateTime) return ((DateTime)value).Equals(DateTime.MinValue);
+      throw new ArgumentException();
+    }
+    #endregion
+
+    #region Rows
+    public void InsertRow(int rowIndex) {
+      SaveSnapshot(DataPreprocessingChangedEventType.DeleteRow, -1, rowIndex);
+      foreach (IList column in variableValues) {
+        Type type = column.GetType().GetGenericArguments()[0];
+        column.Insert(rowIndex, type.IsValueType ? Activator.CreateInstance(type) : null);
+      }
+      if (TrainingPartition.Start <= rowIndex && rowIndex <= TrainingPartition.End) {
+        TrainingPartition.End++;
+        if (TrainingPartition.End <= TestPartition.Start) {
+          TestPartition.Start++;
+          TestPartition.End++;
+        }
+      } else if (TestPartition.Start <= rowIndex && rowIndex <= TestPartition.End) {
+        TestPartition.End++;
+        if (TestPartition.End <= TrainingPartition.Start) {
+          TestPartition.Start++;
+          TestPartition.End++;
+        }
+      }
+      if (!IsInTransaction)
+        OnChanged(DataPreprocessingChangedEventType.AddRow, -1, rowIndex);
+    }
+    public void DeleteRow(int rowIndex) {
+      SaveSnapshot(DataPreprocessingChangedEventType.AddRow, -1, rowIndex);
+      foreach (IList column in variableValues) {
+        column.RemoveAt(rowIndex);
+      }
+      if (TrainingPartition.Start <= rowIndex && rowIndex <= TrainingPartition.End) {
+        TrainingPartition.End--;
+        if (TrainingPartition.End <= TestPartition.Start) {
+          TestPartition.Start--;
+          TestPartition.End--;
+        }
+      } else if (TestPartition.Start <= rowIndex && rowIndex <= TestPartition.End) {
+        TestPartition.End--;
+        if (TestPartition.End <= TrainingPartition.Start) {
+          TestPartition.Start--;
+          TestPartition.End--;
+        }
+      }
+      if (!IsInTransaction)
+        OnChanged(DataPreprocessingChangedEventType.DeleteRow, -1, rowIndex);
+    }
+    public void DeleteRowsWithIndices(IEnumerable<int> rows) {
+      SaveSnapshot(DataPreprocessingChangedEventType.AddRow, -1, -1);
+      foreach (int rowIndex in rows.OrderByDescending(x => x)) {
+        foreach (IList column in variableValues) {
+          column.RemoveAt(rowIndex);
+        }
+        if (TrainingPartition.Start <= rowIndex && rowIndex <= TrainingPartition.End) {
+          TrainingPartition.End--;
+          if (TrainingPartition.End <= TestPartition.Start) {
+            TestPartition.Start--;
+            TestPartition.End--;
+          }
+        } else if (TestPartition.Start <= rowIndex && rowIndex <= TestPartition.End) {
+          TestPartition.End--;
+          if (TestPartition.End <= TrainingPartition.Start) {
+            TestPartition.Start--;
+            TestPartition.End--;
+          }
+        }
+      }
+      if (!IsInTransaction)
+        OnChanged(DataPreprocessingChangedEventType.DeleteRow, -1, -1);
+    }
+
+    public void InsertColumn<T>(string variableName, int columnIndex) {
+      SaveSnapshot(DataPreprocessingChangedEventType.DeleteColumn, columnIndex, -1);
+      variableValues.Insert(columnIndex, new List<T>(Enumerable.Repeat(default(T), Rows)));
+      variableNames.Insert(columnIndex, variableName);
+      if (!IsInTransaction)
+        OnChanged(DataPreprocessingChangedEventType.AddColumn, columnIndex, -1);
+    }
+
+    public void DeleteColumn(int columnIndex) {
+      SaveSnapshot(DataPreprocessingChangedEventType.AddColumn, columnIndex, -1);
+      variableValues.RemoveAt(columnIndex);
+      variableNames.RemoveAt(columnIndex);
+      if (!IsInTransaction)
+        OnChanged(DataPreprocessingChangedEventType.DeleteColumn, columnIndex, -1);
+    }
+
+    public void RenameColumn(int columnIndex, string name) {
+      SaveSnapshot(DataPreprocessingChangedEventType.ChangeColumn, columnIndex, -1);
+      if (columnIndex < 0 || columnIndex > variableNames.Count)
+        throw new ArgumentOutOfRangeException("columnIndex");
+      variableNames[columnIndex] = name;
+
+      if (!IsInTransaction)
+        OnChanged(DataPreprocessingChangedEventType.ChangeColumn, -1, -1);
+    }
+
+    public void RenameColumns(IList<string> names) {
+      if (names == null) throw new ArgumentNullException("names");
+      if (names.Count != variableNames.Count) throw new ArgumentException("number of names must match the number of columns.", "names");
+
+      SaveSnapshot(DataPreprocessingChangedEventType.ChangeColumn, -1, -1);
+      for (int i = 0; i < names.Count; i++)
+        variableNames[i] = names[i];
+
+      if (!IsInTransaction)
+        OnChanged(DataPreprocessingChangedEventType.ChangeColumn, -1, -1);
+    }
+
+    public bool AreAllStringColumns(IEnumerable<int> columnIndices) {
+      return columnIndices.All(x => VariableHasType<string>(x));
+    }
+    #endregion
+
+    #region Variables
+    public IEnumerable<string> VariableNames {
+      get { return variableNames; }
+    }
+
+    public IEnumerable<string> GetDoubleVariableNames() {
+      var doubleVariableNames = new List<string>();
+      for (int i = 0; i < Columns; ++i) {
+        if (VariableHasType<double>(i)) {
+          doubleVariableNames.Add(variableNames[i]);
+        }
+      }
+      return doubleVariableNames;
+    }
+
+    public string GetVariableName(int columnIndex) {
+      return variableNames[columnIndex];
+    }
+
+    public int GetColumnIndex(string variableName) {
+      return variableNames.IndexOf(variableName);
+    }
+
+    public bool VariableHasType<T>(int columnIndex) {
+      return columnIndex >= variableValues.Count || variableValues[columnIndex] is List<T>;
+    }
+
+    public IList<string> InputVariables { get; private set; }
+    public string TargetVariable { get; private set; } // optional
+    #endregion
+
+    #region Partitions
+    [Storable]
+    public IntRange TrainingPartition { get; set; }
+    [Storable]
+    public IntRange TestPartition { get; set; }
+    #endregion
+
+    #region Transformations
+    [Storable]
+    public IList<ITransformation> Transformations { get; protected set; }
+    #endregion
+
+    #region Validation
+    public bool Validate(string value, out string errorMessage, int columnIndex) {
+      if (columnIndex < 0 || columnIndex > VariableNames.Count()) {
+        throw new ArgumentOutOfRangeException("column index is out of range");
+      }
+
+      bool valid = false;
+      errorMessage = string.Empty;
+      if (VariableHasType<double>(columnIndex)) {
+        double val;
+        valid = double.TryParse(value, out val);
+        if (!valid) {
+          errorMessage = "Invalid Value (Valid Value Format: \"" + FormatPatterns.GetDoubleFormatPattern() + "\")";
+        }
+      } else if (VariableHasType<string>(columnIndex)) {
+        valid = value != null;
+        if (!valid) {
+          errorMessage = "Invalid Value (string must not be null)";
+        }
+      } else if (VariableHasType<DateTime>(columnIndex)) {
+        DateTime date;
+        valid = DateTime.TryParse(value, out date);
+        if (!valid) {
+          errorMessage = "Invalid Value (Valid Value Format: \"" + CultureInfo.CurrentCulture.DateTimeFormat + "\"";
+        }
+      } else {
+        throw new ArgumentException("column " + columnIndex + " contains a non supported type.");
+      }
+
+      return valid;
+    }
+    #endregion
+
+    #region Import & Export
     public void Import(IDataAnalysisProblemData problemData) {
       Dataset dataset = (Dataset)problemData.Dataset;
@@ -107,5 +383,5 @@
       TargetVariable = (problemData is IRegressionProblemData) ? ((IRegressionProblemData)problemData).TargetVariable
         : (problemData is IClassificationProblemData) ? ((IClassificationProblemData)problemData).TargetVariable
-        : null;
+          : null;
 
       int columnIndex = 0;
@@ -128,86 +404,51 @@
     }
 
-    private void RegisterEventHandler() {
-      Changed += (s, e) => {
-        switch (e.Type) {
-          case DataPreprocessingChangedEventType.DeleteRow:
-            CheckPartitionRanges();
-            break;
-          case DataPreprocessingChangedEventType.Any:
-            CheckPartitionRanges();
-            break;
-          case DataPreprocessingChangedEventType.Transformation:
-            CheckPartitionRanges();
-            break;
-        }
-      };
-    }
-
-    private void CheckPartitionRanges() {
-      int maxRowIndex = Math.Max(0, Rows);
-      TrainingPartition.Start = Math.Min(TrainingPartition.Start, maxRowIndex);
-      TrainingPartition.End = Math.Min(TrainingPartition.End, maxRowIndex);
-      TestPartition.Start = Math.Min(TestPartition.Start, maxRowIndex);
-      TestPartition.End = Math.Min(TestPartition.End, maxRowIndex);
-    }
-
-    protected IList<IList> CopyVariableValues(IList<IList> original) {
-      var copy = new List<IList>(original);
-      for (int i = 0; i < original.Count; ++i) {
-        copy[i] = (IList)Activator.CreateInstance(original[i].GetType(), original[i]);
-      }
-      return copy;
-    }
-
-    public static bool IsMissingValue(object value) {
-      if (value is double) return double.IsNaN((double)value);
-      if (value is string) return string.IsNullOrEmpty((string)value);
-      if (value is DateTime) return ((DateTime)value).Equals(DateTime.MinValue);
-      throw new ArgumentException();
-    }
-
-    #region IPreprocessingData Members
-    public abstract bool IsCellEmpty(int columnIndex, int rowIndex);
-    public abstract T GetCell<T>(int columnIndex, int rowIndex);
-
-    public abstract void SetCell<T>(int columnIndex, int rowIndex, T value);
-
-    public abstract string GetCellAsString(int columnIndex, int rowIndex);
-
-    public abstract string GetVariableName(int columnIndex);
-
-    public abstract int GetColumnIndex(string variableName);
-
-    public abstract bool VariableHasType<T>(int columnIndex);
-
-    public abstract IList<T> GetValues<T>(int columnIndex, bool considerSelection);
-
-    public abstract void SetValues<T>(int columnIndex, IList<T> values);
-
-    public abstract bool SetValue(string value, int columnIndex, int rowIndex);
-
-    public abstract bool Validate(string value, out string errorMessage, int columnIndex);
-
-    public abstract bool AreAllStringColumns(IEnumerable<int> columnIndices);
-
-    public abstract void DeleteRowsWithIndices(IEnumerable<int> rows);
-
-    public abstract void InsertRow(int rowIndex);
-
-    public abstract void DeleteRow(int rowIndex);
-
-    public abstract void InsertColumn<T>(string variableName, int columnIndex);
-
-    public abstract void DeleteColumn(int columnIndex);
-
-    public abstract void RenameColumn(int columnIndex, string name);
-    public abstract void RenameColumns(IList<string> list);
-
-    public abstract Dataset ExportToDataset();
-
-    public abstract void ClearSelection();
-
-    public abstract event EventHandler SelectionChanged;
-    protected abstract void OnSelectionChanged();
+    public Dataset ExportToDataset() {
+      IList<IList> values = new List<IList>();
+
+      for (int i = 0; i < Columns; ++i) {
+        values.Add(variableValues[i]);
+      }
+
+      var dataset = new Dataset(variableNames, values);
+      return dataset;
+    }
+    #endregion
+
+    #region Selection
+    [Storable]
+    protected IDictionary<int, IList<int>> selection;
+    public IDictionary<int, IList<int>> Selection {
+      get { return selection; }
+      set {
+        selection = value;
+        OnSelectionChanged();
+      }
+    }
+    public void ClearSelection() {
+      Selection = new Dictionary<int, IList<int>>();
+    }
+
+    public event EventHandler SelectionChanged;
+    protected void OnSelectionChanged() {
+      var listeners = SelectionChanged;
+      if (listeners != null) listeners(this, EventArgs.Empty);
+    }
+    #endregion
+
+    #region Transactions
+    // Stapshot/History are nost storable/cloneable on purpose
+    private class Snapshot {
+      public IList<IList> VariableValues { get; set; }
+      public IList<string> VariableNames { get; set; }
+
+      public IntRange TrainingPartition { get; set; }
+      public IntRange TestPartition { get; set; }
+      public IList<ITransformation> Transformations { get; set; }
+      public DataPreprocessingChangedEventType ChangedType { get; set; }
+
+      public int ChangedColumn { get; set; }
+      public int ChangedRow { get; set; }
+    }
 
     public event DataPreprocessingChangedEventHandler Changed;
@@ -216,4 +457,79 @@
       if (listeners != null) listeners(this, new DataPreprocessingChangedEventArgs(type, column, row));
     }
+
+    private const int MAX_UNDO_DEPTH = 5;
+
+    private readonly IList<Snapshot> undoHistory = new List<Snapshot>();
+    private readonly Stack<DataPreprocessingChangedEventType> eventStack = new Stack<DataPreprocessingChangedEventType>();
+
+    public bool IsInTransaction { get { return eventStack.Count > 0; } }
+
+    private void SaveSnapshot(DataPreprocessingChangedEventType changedType, int column, int row) {
+      if (IsInTransaction) return;
+
+      var currentSnapshot = new Snapshot {
+        VariableValues = CopyVariableValues(variableValues),
+        VariableNames = new List<string>(variableNames),
+        TrainingPartition = new IntRange(TrainingPartition.Start, TrainingPartition.End),
+        TestPartition = new IntRange(TestPartition.Start, TestPartition.End),
+        Transformations = new List<ITransformation>(Transformations),
+        ChangedType = changedType,
+        ChangedColumn = column,
+        ChangedRow = row
+      };
+
+      if (undoHistory.Count >= MAX_UNDO_DEPTH)
+        undoHistory.RemoveAt(0);
+
+      undoHistory.Add(currentSnapshot);
+    }
+
+    public bool IsUndoAvailable {
+      get { return undoHistory.Count > 0; }
+    }
+
+    public void Undo() {
+      if (IsUndoAvailable) {
+        Snapshot previousSnapshot = undoHistory[undoHistory.Count - 1];
+        variableValues = previousSnapshot.VariableValues;
+        variableNames = previousSnapshot.VariableNames;
+        TrainingPartition = previousSnapshot.TrainingPartition;
+        TestPartition = previousSnapshot.TestPartition;
+        Transformations = previousSnapshot.Transformations;
+        undoHistory.Remove(previousSnapshot);
+        OnChanged(previousSnapshot.ChangedType,
+          previousSnapshot.ChangedColumn,
+          previousSnapshot.ChangedRow);
+      }
+    }
+
+    public void InTransaction(Action action, DataPreprocessingChangedEventType type = DataPreprocessingChangedEventType.Any) {
+      BeginTransaction(type);
+      action();
+      EndTransaction();
+    }
+
+    public void BeginTransaction(DataPreprocessingChangedEventType type) {
+      SaveSnapshot(type, -1, -1);
+      eventStack.Push(type);
+    }
+
+    public void EndTransaction() {
+      if (eventStack.Count == 0)
+        throw new InvalidOperationException("There is no open transaction that can be ended.");
+
+      var @event = eventStack.Pop();
+      OnChanged(@event, -1, -1);
+    }
+    #endregion
+
+    #region Helpers
+    private static IList<IList> CopyVariableValues(IList<IList> original) {
+      var copy = new List<IList>(original);
+      for (int i = 0; i < original.Count; ++i) {
+        copy[i] = (IList)Activator.CreateInstance(original[i].GetType(), original[i]);
+      }
+      return copy;
+    }
     #endregion
   }
Index: anches/DataPreprocessing Cleanup/HeuristicLab.DataPreprocessing/3.4/Data/TransactionalPreprocessingData.cs
===================================================================
--- /branches/DataPreprocessing Cleanup/HeuristicLab.DataPreprocessing/3.4/Data/TransactionalPreprocessingData.cs	(revision 15269)
+++ 	(revision )
@@ -1,382 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2016 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
- *
- * This file is part of HeuristicLab.
- *
- * HeuristicLab is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * HeuristicLab is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
- */
-#endregion
-
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Globalization;
-using System.Linq;
-using HeuristicLab.Common;
-using HeuristicLab.Core;
-using HeuristicLab.Data;
-using HeuristicLab.Problems.DataAnalysis;
-
-namespace HeuristicLab.DataPreprocessing {
-  [Item("PreprocessingData", "Represents data used for preprocessing.")]
-  public class TransactionalPreprocessingData : PreprocessingData, ITransactionalPreprocessingData {
-    private class Snapshot {
-      public IList<IList> VariableValues { get; set; }
-      public IList<string> VariableNames { get; set; }
-
-      public IntRange TrainingPartition { get; set; }
-      public IntRange TestPartition { get; set; }
-      public IList<ITransformation> Transformations { get; set; }
-      public DataPreprocessingChangedEventType ChangedType { get; set; }
-
-      public int ChangedColumn { get; set; }
-      public int ChangedRow { get; set; }
-    }
-
-    private const int MAX_UNDO_DEPTH = 5;
-
-    private readonly IList<Snapshot> undoHistory = new List<Snapshot>();
-    private readonly Stack<DataPreprocessingChangedEventType> eventStack = new Stack<DataPreprocessingChangedEventType>();
-
-    public bool IsInTransaction { get { return eventStack.Count > 0; } }
-
-    public TransactionalPreprocessingData(IDataAnalysisProblemData problemData)
-      : base(problemData) {
-    }
-
-    protected TransactionalPreprocessingData(TransactionalPreprocessingData original, Cloner cloner)
-      : base(original, cloner) {
-    }
-
-    private void SaveSnapshot(DataPreprocessingChangedEventType changedType, int column, int row) {
-      if (IsInTransaction) return;
-
-      var currentSnapshot = new Snapshot {
-        VariableValues = CopyVariableValues(variableValues),
-        VariableNames = new List<string>(variableNames),
-        TrainingPartition = new IntRange(TrainingPartition.Start, TrainingPartition.End),
-        TestPartition = new IntRange(TestPartition.Start, TestPartition.End),
-        Transformations = new List<ITransformation>(Transformations),
-        ChangedType = changedType,
-        ChangedColumn = column,
-        ChangedRow = row
-      };
-
-      if (undoHistory.Count >= MAX_UNDO_DEPTH)
-        undoHistory.RemoveAt(0);
-
-      undoHistory.Add(currentSnapshot);
-    }
-
-    #region NamedItem abstract Member Implementations
-    public override IDeepCloneable Clone(Cloner cloner) {
-      return new TransactionalPreprocessingData(this, cloner);
-    }
-    #endregion
-
-    #region Overridden IPreprocessingData Members
-    public override bool IsCellEmpty(int columnIndex, int rowIndex) {
-      var value = variableValues[columnIndex][rowIndex];
-      return IsMissingValue(value);
-    }
-
-    public override T GetCell<T>(int columnIndex, int rowIndex) {
-      return (T)variableValues[columnIndex][rowIndex];
-    }
-
-    public override void SetCell<T>(int columnIndex, int rowIndex, T value) {
-      SaveSnapshot(DataPreprocessingChangedEventType.ChangeItem, columnIndex, rowIndex);
-
-      for (int i = Rows; i <= rowIndex; i++)
-        InsertRow(i);
-      for (int i = Columns; i <= columnIndex; i++)
-        InsertColumn<T>(i.ToString(), i);
-
-      variableValues[columnIndex][rowIndex] = value;
-      if (!IsInTransaction)
-        OnChanged(DataPreprocessingChangedEventType.ChangeItem, columnIndex, rowIndex);
-    }
-
-    public override string GetCellAsString(int columnIndex, int rowIndex) {
-      return variableValues[columnIndex][rowIndex].ToString();
-    }
-
-    public override string GetVariableName(int columnIndex) {
-      return variableNames[columnIndex];
-    }
-
-    public override int GetColumnIndex(string variableName) {
-      return variableNames.IndexOf(variableName);
-    }
-
-    public override bool VariableHasType<T>(int columnIndex) {
-      return columnIndex >= variableValues.Count || variableValues[columnIndex] is List<T>;
-    }
-
-    public override IList<T> GetValues<T>(int columnIndex, bool considerSelection) {
-      if (considerSelection) {
-        var list = new List<T>();
-        foreach (var rowIdx in selection[columnIndex]) {
-          list.Add((T)variableValues[columnIndex][rowIdx]);
-        }
-        return list;
-      } else {
-        return (IList<T>)variableValues[columnIndex];
-      }
-    }
-
-    public override void SetValues<T>(int columnIndex, IList<T> values) {
-      SaveSnapshot(DataPreprocessingChangedEventType.ChangeColumn, columnIndex, -1);
-      if (VariableHasType<T>(columnIndex)) {
-        variableValues[columnIndex] = (IList)values;
-      } else {
-        throw new ArgumentException("The datatype of column " + columnIndex + " must be of type " + variableValues[columnIndex].GetType().Name + " but was " + typeof(T).Name);
-      }
-      if (!IsInTransaction)
-        OnChanged(DataPreprocessingChangedEventType.ChangeColumn, columnIndex, -1);
-    }
-
-    public override bool SetValue(string value, int columnIndex, int rowIndex) {
-      bool valid = false;
-      if (VariableHasType<double>(columnIndex)) {
-        double val;
-        valid = double.TryParse(value, out val);
-        SetValueIfValid(columnIndex, rowIndex, valid, val);
-      } else if (VariableHasType<string>(columnIndex)) {
-        valid = value != null;
-        SetValueIfValid(columnIndex, rowIndex, valid, value);
-      } else if (VariableHasType<DateTime>(columnIndex)) {
-        DateTime date;
-        valid = DateTime.TryParse(value, out date);
-        SetValueIfValid(columnIndex, rowIndex, valid, date);
-      } else {
-        throw new ArgumentException("column " + columnIndex + " contains a non supported type.");
-      }
-
-      if (!IsInTransaction)
-        OnChanged(DataPreprocessingChangedEventType.ChangeColumn, columnIndex, -1);
-
-      return valid;
-    }
-
-    public override bool Validate(string value, out string errorMessage, int columnIndex) {
-      if (columnIndex < 0 || columnIndex > VariableNames.Count()) {
-        throw new ArgumentOutOfRangeException("column index is out of range");
-      }
-
-      bool valid = false;
-      errorMessage = string.Empty;
-      if (VariableHasType<double>(columnIndex)) {
-        double val;
-        valid = double.TryParse(value, out val);
-        if (!valid) {
-          errorMessage = "Invalid Value (Valid Value Format: \"" + FormatPatterns.GetDoubleFormatPattern() + "\")";
-        }
-      } else if (VariableHasType<string>(columnIndex)) {
-        valid = value != null;
-        if (!valid) {
-          errorMessage = "Invalid Value (string must not be null)";
-        }
-      } else if (VariableHasType<DateTime>(columnIndex)) {
-        DateTime date;
-        valid = DateTime.TryParse(value, out date);
-        if (!valid) {
-          errorMessage = "Invalid Value (Valid Value Format: \"" + CultureInfo.CurrentCulture.DateTimeFormat + "\"";
-        }
-      } else {
-        throw new ArgumentException("column " + columnIndex + " contains a non supported type.");
-      }
-
-      return valid;
-    }
-
-    private void SetValueIfValid<T>(int columnIndex, int rowIndex, bool valid, T value) {
-      if (valid)
-        SetCell<T>(columnIndex, rowIndex, value);
-    }
-
-    public override bool AreAllStringColumns(IEnumerable<int> columnIndices) {
-      return columnIndices.All(x => VariableHasType<string>(x));
-    }
-
-    public override void InsertRow(int rowIndex) {
-      SaveSnapshot(DataPreprocessingChangedEventType.DeleteRow, -1, rowIndex);
-      foreach (IList column in variableValues) {
-        Type type = column.GetType().GetGenericArguments()[0];
-        column.Insert(rowIndex, type.IsValueType ? Activator.CreateInstance(type) : null);
-      }
-      if (TrainingPartition.Start <= rowIndex && rowIndex <= TrainingPartition.End) {
-        TrainingPartition.End++;
-        if (TrainingPartition.End <= TestPartition.Start) {
-          TestPartition.Start++;
-          TestPartition.End++;
-        }
-      } else if (TestPartition.Start <= rowIndex && rowIndex <= TestPartition.End) {
-        TestPartition.End++;
-        if (TestPartition.End <= TrainingPartition.Start) {
-          TestPartition.Start++;
-          TestPartition.End++;
-        }
-      }
-      if (!IsInTransaction)
-        OnChanged(DataPreprocessingChangedEventType.AddRow, -1, rowIndex);
-    }
-    public override void DeleteRow(int rowIndex) {
-      SaveSnapshot(DataPreprocessingChangedEventType.AddRow, -1, rowIndex);
-      foreach (IList column in variableValues) {
-        column.RemoveAt(rowIndex);
-      }
-      if (TrainingPartition.Start <= rowIndex && rowIndex <= TrainingPartition.End) {
-        TrainingPartition.End--;
-        if (TrainingPartition.End <= TestPartition.Start) {
-          TestPartition.Start--;
-          TestPartition.End--;
-        }
-      } else if (TestPartition.Start <= rowIndex && rowIndex <= TestPartition.End) {
-        TestPartition.End--;
-        if (TestPartition.End <= TrainingPartition.Start) {
-          TestPartition.Start--;
-          TestPartition.End--;
-        }
-      }
-      if (!IsInTransaction)
-        OnChanged(DataPreprocessingChangedEventType.DeleteRow, -1, rowIndex);
-    }
-    public override void DeleteRowsWithIndices(IEnumerable<int> rows) {
-      SaveSnapshot(DataPreprocessingChangedEventType.AddRow, -1, -1);
-      foreach (int rowIndex in rows.OrderByDescending(x => x)) {
-        foreach (IList column in variableValues) {
-          column.RemoveAt(rowIndex);
-        }
-        if (TrainingPartition.Start <= rowIndex && rowIndex <= TrainingPartition.End) {
-          TrainingPartition.End--;
-          if (TrainingPartition.End <= TestPartition.Start) {
-            TestPartition.Start--;
-            TestPartition.End--;
-          }
-        } else if (TestPartition.Start <= rowIndex && rowIndex <= TestPartition.End) {
-          TestPartition.End--;
-          if (TestPartition.End <= TrainingPartition.Start) {
-            TestPartition.Start--;
-            TestPartition.End--;
-          }
-        }
-      }
-      if (!IsInTransaction)
-        OnChanged(DataPreprocessingChangedEventType.DeleteRow, -1, -1);
-    }
-
-    public override void InsertColumn<T>(string variableName, int columnIndex) {
-      SaveSnapshot(DataPreprocessingChangedEventType.DeleteColumn, columnIndex, -1);
-      variableValues.Insert(columnIndex, new List<T>(Enumerable.Repeat(default(T), Rows)));
-      variableNames.Insert(columnIndex, variableName);
-      if (!IsInTransaction)
-        OnChanged(DataPreprocessingChangedEventType.AddColumn, columnIndex, -1);
-    }
-
-    public override void DeleteColumn(int columnIndex) {
-      SaveSnapshot(DataPreprocessingChangedEventType.AddColumn, columnIndex, -1);
-      variableValues.RemoveAt(columnIndex);
-      variableNames.RemoveAt(columnIndex);
-      if (!IsInTransaction)
-        OnChanged(DataPreprocessingChangedEventType.DeleteColumn, columnIndex, -1);
-    }
-
-    public override void RenameColumn(int columnIndex, string name) {
-      SaveSnapshot(DataPreprocessingChangedEventType.ChangeColumn, columnIndex, -1);
-      if (columnIndex < 0 || columnIndex > variableNames.Count)
-        throw new ArgumentOutOfRangeException("columnIndex");
-      variableNames[columnIndex] = name;
-
-      if (!IsInTransaction)
-        OnChanged(DataPreprocessingChangedEventType.ChangeColumn, -1, -1);
-    }
-
-    public override void RenameColumns(IList<string> names) {
-      if (names == null) throw new ArgumentNullException("names");
-      if (names.Count != variableNames.Count) throw new ArgumentException("number of names must match the number of columns.", "names");
-
-      SaveSnapshot(DataPreprocessingChangedEventType.ChangeColumn, -1, -1);
-      for (int i = 0; i < names.Count; i++)
-        variableNames[i] = names[i];
-
-      if (!IsInTransaction)
-        OnChanged(DataPreprocessingChangedEventType.ChangeColumn, -1, -1);
-    }
-
-    public override Dataset ExportToDataset() {
-      IList<IList> values = new List<IList>();
-
-      for (int i = 0; i < Columns; ++i) {
-        values.Add(variableValues[i]);
-      }
-
-      var dataset = new Dataset(variableNames, values);
-      return dataset;
-    }
-
-    public override void ClearSelection() {
-      Selection = new Dictionary<int, IList<int>>();
-    }
-
-    public override event EventHandler SelectionChanged;
-
-    protected override void OnSelectionChanged() {
-      var listeners = SelectionChanged;
-      if (listeners != null) listeners(this, EventArgs.Empty);
-    }
-    #endregion
-
-    #region TransactionalPreprocessingData members
-    public bool IsUndoAvailable {
-      get { return undoHistory.Count > 0; }
-    }
-
-    public void Undo() {
-      if (IsUndoAvailable) {
-        Snapshot previousSnapshot = undoHistory[undoHistory.Count - 1];
-        variableValues = previousSnapshot.VariableValues;
-        variableNames = previousSnapshot.VariableNames;
-        TrainingPartition = previousSnapshot.TrainingPartition;
-        TestPartition = previousSnapshot.TestPartition;
-        Transformations = previousSnapshot.Transformations;
-        undoHistory.Remove(previousSnapshot);
-        OnChanged(previousSnapshot.ChangedType,
-          previousSnapshot.ChangedColumn,
-          previousSnapshot.ChangedRow);
-      }
-    }
-
-    public void InTransaction(Action action, DataPreprocessingChangedEventType type = DataPreprocessingChangedEventType.Any) {
-      BeginTransaction(type);
-      action();
-      EndTransaction();
-    }
-
-    public void BeginTransaction(DataPreprocessingChangedEventType type) {
-      SaveSnapshot(type, -1, -1);
-      eventStack.Push(type);
-    }
-
-    public void EndTransaction() {
-      if (eventStack.Count == 0)
-        throw new InvalidOperationException("There is no open transaction that can be ended.");
-
-      var @event = eventStack.Pop();
-      OnChanged(@event, -1, -1);
-    }
-    #endregion
-  }
-}
Index: /branches/DataPreprocessing Cleanup/HeuristicLab.DataPreprocessing/3.4/HeuristicLab.DataPreprocessing-3.4.csproj
===================================================================
--- /branches/DataPreprocessing Cleanup/HeuristicLab.DataPreprocessing/3.4/HeuristicLab.DataPreprocessing-3.4.csproj	(revision 15269)
+++ /branches/DataPreprocessing Cleanup/HeuristicLab.DataPreprocessing/3.4/HeuristicLab.DataPreprocessing-3.4.csproj	(revision 15270)
@@ -145,7 +145,5 @@
     <Compile Include="Content\DataGridContent.cs" />
     <Compile Include="PreprocessingContext.cs" />
-    <Compile Include="Data\TransactionalPreprocessingData.cs" />
     <Compile Include="Logic\StatisticsLogic.cs" />
-    <Compile Include="Data\ITransactionalPreprocessingData.cs" />
     <Compile Include="Plugin.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
Index: /branches/DataPreprocessing Cleanup/HeuristicLab.DataPreprocessing/3.4/Logic/ManipulationLogic.cs
===================================================================
--- /branches/DataPreprocessing Cleanup/HeuristicLab.DataPreprocessing/3.4/Logic/ManipulationLogic.cs	(revision 15269)
+++ /branches/DataPreprocessing Cleanup/HeuristicLab.DataPreprocessing/3.4/Logic/ManipulationLogic.cs	(revision 15270)
@@ -28,5 +28,5 @@
 namespace HeuristicLab.DataPreprocessing {
   public class ManipulationLogic {
-    private readonly ITransactionalPreprocessingData preprocessingData;
+    private readonly IPreprocessingData preprocessingData;
     private readonly StatisticsLogic statisticsLogic;
 
@@ -35,9 +35,9 @@
     }
 
-    public ITransactionalPreprocessingData PreProcessingData {
+    public IPreprocessingData PreProcessingData {
       get { return preprocessingData; }
     }
 
-    public ManipulationLogic(ITransactionalPreprocessingData preprocessingData, StatisticsLogic theStatisticsLogic) {
+    public ManipulationLogic(IPreprocessingData preprocessingData, StatisticsLogic theStatisticsLogic) {
       this.preprocessingData = preprocessingData;
       statisticsLogic = theStatisticsLogic;
Index: /branches/DataPreprocessing Cleanup/HeuristicLab.DataPreprocessing/3.4/Logic/StatisticsLogic.cs
===================================================================
--- /branches/DataPreprocessing Cleanup/HeuristicLab.DataPreprocessing/3.4/Logic/StatisticsLogic.cs	(revision 15269)
+++ /branches/DataPreprocessing Cleanup/HeuristicLab.DataPreprocessing/3.4/Logic/StatisticsLogic.cs	(revision 15270)
@@ -27,7 +27,7 @@
 namespace HeuristicLab.DataPreprocessing {
   public class StatisticsLogic {
-    private readonly ITransactionalPreprocessingData preprocessingData;
-
-    public StatisticsLogic(ITransactionalPreprocessingData preprocessingData) {
+    private readonly IPreprocessingData preprocessingData;
+
+    public StatisticsLogic(IPreprocessingData preprocessingData) {
       this.preprocessingData = preprocessingData;
     }
Index: /branches/DataPreprocessing Cleanup/HeuristicLab.DataPreprocessing/3.4/PreprocessingContext.cs
===================================================================
--- /branches/DataPreprocessing Cleanup/HeuristicLab.DataPreprocessing/3.4/PreprocessingContext.cs	(revision 15269)
+++ /branches/DataPreprocessing Cleanup/HeuristicLab.DataPreprocessing/3.4/PreprocessingContext.cs	(revision 15270)
@@ -71,5 +71,5 @@
       if (namedSource != null)
         Name = "Preprocessing " + namedSource.Name;
-      Data = new FilteredPreprocessingData(new TransactionalPreprocessingData(problemData));
+      Data = new FilteredPreprocessingData(new PreprocessingData(problemData));
       OnReset();
       // Reset GUI:
Index: /branches/DataPreprocessing Cleanup/HeuristicLab.DataPreprocessing/3.4/PreprocessingTransformator.cs
===================================================================
--- /branches/DataPreprocessing Cleanup/HeuristicLab.DataPreprocessing/3.4/PreprocessingTransformator.cs	(revision 15269)
+++ /branches/DataPreprocessing Cleanup/HeuristicLab.DataPreprocessing/3.4/PreprocessingTransformator.cs	(revision 15270)
@@ -29,5 +29,5 @@
 namespace HeuristicLab.DataPreprocessing {
   public class PreprocessingTransformator {
-    private readonly ITransactionalPreprocessingData preprocessingData;
+    private readonly IPreprocessingData preprocessingData;
 
     private readonly IDictionary<string, IList<double>> originalColumns;
@@ -36,5 +36,5 @@
 
     public PreprocessingTransformator(IPreprocessingData preprocessingData) {
-      this.preprocessingData = (ITransactionalPreprocessingData)preprocessingData;
+      this.preprocessingData = preprocessingData;
       originalColumns = new Dictionary<string, IList<double>>();
       renamedColumns = new Dictionary<string, string>();
@@ -68,10 +68,8 @@
           preprocessingData.Undo();
         }
-      }
-      catch (Exception e) {
+      } catch (Exception e) {
         preprocessingData.Undo();
         if (string.IsNullOrEmpty(errorMsg)) errorMsg = e.Message;
-      }
-      finally {
+      } finally {
         preprocessingData.EndTransaction();
       }
