Free cookie consent management tool by TermsFeed Policy Generator

source: branches/DataPreprocessing/HeuristicLab.DataPreprocessing/3.3/Implementations/TransactionalPreprocessingData.cs @ 10884

Last change on this file since 10884 was 10814, checked in by pfleck, 11 years ago
  • Considered Transformations in Undo.
  • Renamed PDSnapshot in Snapshot.
File size: 6.8 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2013 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections;
24using System.Collections.Generic;
25using HeuristicLab.Common;
26using HeuristicLab.Core;
27using HeuristicLab.Problems.DataAnalysis;
28using HeuristicLab.Problems.DataAnalysis.Transformations;
29
30namespace HeuristicLab.DataPreprocessing {
31
32  internal class Snapshot {
33    public IList<IList> VariableValues { get; set; }
34
35    public IList<string> VariableNames { get; set; }
36
37    public double TrainingToTestRatio { get; set; }
38
39    public IList<ITransformation> Transformations { get; set; }
40
41    public DataPreprocessingChangedEventType ChangedType { get; set; }
42
43    public int ChangedColumn { get; set; }
44
45    public int ChangedRow { get; set; }
46  }
47
48  [Item("PreprocessingData", "Represents data used for preprocessing.")]
49  public class TransactionalPreprocessingData : PreprocessingData, ITransactionalPreprocessingData {
50
51    private const int MAX_UNDO_DEPTH = 5;
52
53    private IList<Snapshot> undoHistory;
54
55    private Stack<DataPreprocessingChangedEventType> eventStack = new Stack<DataPreprocessingChangedEventType>();
56
57    private DataPreprocessingChangedEventType lastOccuredChangedType = DataPreprocessingChangedEventType.Any;
58
59    public bool IsInTransaction { get { return eventStack.Count > 0; } }
60
61    public TransactionalPreprocessingData(IDataAnalysisProblemData problemData)
62      : base(problemData) {
63      undoHistory = new List<Snapshot>();
64    }
65
66    private TransactionalPreprocessingData(TransactionalPreprocessingData original, Cloner cloner)
67      : base(original, cloner) {
68      undoHistory = new List<Snapshot>();
69    }
70
71    private void SaveSnapshot(DataPreprocessingChangedEventType changedType, int column, int row) {
72      if (eventStack.Count > 0) return;
73
74      var currentSnapshot = new Snapshot {
75        VariableValues = CopyVariableValues(variableValues),
76        VariableNames = new List<string>(variableNames),
77        TrainingToTestRatio = trainingToTestRatio,
78        Transformations = new List<ITransformation>(transformations),
79        ChangedType = changedType,
80        ChangedColumn = column,
81        ChangedRow = row
82      };
83
84      if (undoHistory.Count >= MAX_UNDO_DEPTH)
85        undoHistory.RemoveAt(0);
86
87      undoHistory.Add(currentSnapshot);
88    }
89
90    #region NamedItem abstract Member Implementations
91
92    public override IDeepCloneable Clone(Cloner cloner) {
93      return new TransactionalPreprocessingData(this, cloner);
94    }
95
96    #endregion
97
98    #region Overridden IPreprocessingData Members
99
100    public override void SetCell<T>(int columnIndex, int rowIndex, T value) {
101      SaveSnapshot(DataPreprocessingChangedEventType.ChangeItem, columnIndex, rowIndex);
102      base.SetCell<T>(columnIndex, rowIndex, value);
103      if (!IsInTransaction)
104        OnChanged(DataPreprocessingChangedEventType.ChangeItem, columnIndex, rowIndex);
105    }
106
107    public override void SetValues<T>(int columnIndex, IList<T> values) {
108      SaveSnapshot(DataPreprocessingChangedEventType.ChangeColumn, columnIndex, -1);
109      base.SetValues<T>(columnIndex, values);
110      if (!IsInTransaction)
111        OnChanged(DataPreprocessingChangedEventType.ChangeColumn, columnIndex, -1);
112    }
113
114    public override void InsertRow(int rowIndex) {
115      SaveSnapshot(DataPreprocessingChangedEventType.DeleteRow, -1, rowIndex);
116      base.InsertRow(rowIndex);
117      if (!IsInTransaction)
118        OnChanged(DataPreprocessingChangedEventType.AddRow, -1, rowIndex);
119    }
120
121    public override void DeleteRow(int rowIndex) {
122      SaveSnapshot(DataPreprocessingChangedEventType.AddRow, -1, rowIndex);
123      base.DeleteRow(rowIndex);
124      if (!IsInTransaction)
125        OnChanged(DataPreprocessingChangedEventType.DeleteRow, -1, rowIndex);
126    }
127
128    public override void InsertColumn<T>(string variableName, int columnIndex) {
129      SaveSnapshot(DataPreprocessingChangedEventType.DeleteColumn, columnIndex, -1);
130      base.InsertColumn<T>(variableName, columnIndex);
131      if (!IsInTransaction)
132        OnChanged(DataPreprocessingChangedEventType.AddColumn, columnIndex, -1);
133    }
134
135    public override void DeleteColumn(int columnIndex) {
136      SaveSnapshot(DataPreprocessingChangedEventType.AddColumn, columnIndex, -1);
137      base.DeleteColumn(columnIndex);
138      if (!IsInTransaction)
139        OnChanged(DataPreprocessingChangedEventType.DeleteColumn, columnIndex, -1);
140    }
141
142    #endregion
143
144    #region TransactionalPreprocessingData members
145
146    public event DataPreprocessingChangedEventHandler Changed;
147    protected virtual void OnChanged(DataPreprocessingChangedEventType type, int column, int row) {
148      var listeners = Changed;
149      if (listeners != null) listeners(this, new DataPreprocessingChangedEventArgs(type, column, row));
150    }
151
152    public bool IsUndoAvailable {
153      get { return undoHistory.Count > 0; }
154    }
155
156    public void Undo() {
157      if (IsUndoAvailable) {
158        Snapshot previousSnapshot = undoHistory[undoHistory.Count - 1];
159        variableValues = previousSnapshot.VariableValues;
160        variableNames = previousSnapshot.VariableNames;
161        trainingToTestRatio = previousSnapshot.TrainingToTestRatio;
162        transformations = previousSnapshot.Transformations;
163        undoHistory.Remove(previousSnapshot);
164        OnChanged(previousSnapshot.ChangedType,
165          previousSnapshot.ChangedColumn,
166          previousSnapshot.ChangedRow);
167      }
168    }
169
170    public void InTransaction(Action action, DataPreprocessingChangedEventType type = DataPreprocessingChangedEventType.Any) {
171      BeginTransaction(type);
172      action();
173      EndTransaction();
174    }
175
176    public void BeginTransaction(DataPreprocessingChangedEventType type) {
177      SaveSnapshot(type, -1, -1);
178      eventStack.Push(type);
179    }
180
181    public void EndTransaction() {
182      if (eventStack.Count == 0)
183        throw new InvalidOperationException("There is no open transaction that can be ended.");
184
185      var @event = eventStack.Pop();
186      OnChanged(@event, -1, -1);
187    }
188
189    #endregion
190  }
191}
Note: See TracBrowser for help on using the repository browser.