Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.DataImporter/HeuristicLab.DataImporter.Command/ChangeDataset/AlignColumnGroupsCommand.cs @ 9185

Last change on this file since 9185 was 7625, checked in by mkommend, 12 years ago

#1734: merged changes in data importer from the heureka rep

File size: 10.6 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2012 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.Generic;
24using System.Linq;
25using System.Text;
26using System.Windows.Forms;
27using HeuristicLab.DataImporter.Data;
28using HeuristicLab.DataImporter.Data.CommandBase;
29using HeuristicLab.DataImporter.Data.Model;
30using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
31
32namespace HeuristicLab.DataImporter.Command {
33  [StorableClass]
34  [ViewableCommandInfo("Align ColumnGroups", 2, ColumnGroupState.Sorted, "ColumnGroup Commands", Position = 4)]
35  public class AlignColumnGroupsCommand : DataSetCommandWithAffectedColumnGroupsBase {
36    private ColumnGroup newColumnGroup1;
37    private ColumnGroup newColumnGroup2;
38    private ColumnGroup oldColumnGroup1;
39    private ColumnGroup oldColumnGroup2;
40    private int removePos1;
41    private int removePos2;
42
43    private AlignColumnGroupsCommand()
44      : base(null, null) {
45    }
46
47    public AlignColumnGroupsCommand(DataSet dataSet, List<string> affectedColumnGroupNames)
48      : base(dataSet, affectedColumnGroupNames) {
49    }
50
51    public override void Execute() {
52      base.Execute();
53      this.oldColumnGroup1 = this.DataSet.GetColumnGroup(AffectedColumnGroupNames[0]);
54      this.oldColumnGroup2 = this.DataSet.GetColumnGroup(AffectedColumnGroupNames[1]);
55      this.removePos1 = this.DataSet.IndexOfColumnGroup(oldColumnGroup1);
56      this.removePos2 = this.DataSet.IndexOfColumnGroup(oldColumnGroup2);
57
58      if (!oldColumnGroup1.Columns.Any() || !oldColumnGroup2.Columns.Any()) return;
59
60      if (oldColumnGroup1.SortedColumnsCount < 1 || oldColumnGroup1.SortedColumnsCount != oldColumnGroup2.SortedColumnsCount)
61        throw new CommandExecutionException("Both ColumnGroups must be sorted by at least one column and must be sorted by the same number of columns.", this);
62      for (int i = 0; i < oldColumnGroup1.SortedColumnsCount; i++) {
63        if (this.oldColumnGroup1.SortOrdersForColumns.ElementAt(oldColumnGroup1.SortedColumnIndexes.ElementAt(i)) !=
64            this.oldColumnGroup2.SortOrdersForColumns.ElementAt(oldColumnGroup2.SortedColumnIndexes.ElementAt(i)))
65          throw new CommandExecutionException("Both ColumnGroups must be sorted in the same direction.", this);
66        if (this.oldColumnGroup1.Columns.ElementAt(oldColumnGroup1.SortedColumnIndexes.ElementAt(i)).DataType !=
67            this.oldColumnGroup2.Columns.ElementAt(oldColumnGroup2.SortedColumnIndexes.ElementAt(i)).DataType)
68          throw new CommandExecutionException("Both ColumnGroups must be sorted by columns of the same type", this);
69      }
70
71      foreach (int sortColIndex in oldColumnGroup1.SortedColumnIndexes) {
72        if (oldColumnGroup1.Columns.ElementAt(sortColIndex).ContainsNullValues)
73          throw new CommandExecutionException("KeyColumn " + oldColumnGroup1.GetColumn(sortColIndex).Name + " not contain null values.", this);
74      }
75      foreach (int sortColIndex in oldColumnGroup2.SortedColumnIndexes) {
76        if (oldColumnGroup2.Columns.ElementAt(sortColIndex).ContainsNullValues)
77          throw new CommandExecutionException("KeyColumn " + oldColumnGroup1.GetColumn(sortColIndex).Name + " must not contain null values.", this);
78      }
79      SampleColumnGroup();
80
81      DataSet.ReplaceColumnGroup(removePos1, newColumnGroup1);
82      DataSet.ReplaceColumnGroup(removePos2, newColumnGroup2);
83      newColumnGroup1 = null;
84      newColumnGroup2 = null;
85      DataSet.FireChanged();
86    }
87
88    public override void UndoExecute() {
89      base.UndoExecute();
90      DataSet.ReplaceColumnGroup(removePos1, oldColumnGroup1);
91      DataSet.ReplaceColumnGroup(removePos2, oldColumnGroup2);
92      oldColumnGroup1 = null;
93      oldColumnGroup2 = null;
94      DataSet.FireChanged();
95    }
96
97
98    public void SampleColumnGroup() {
99      var keyColumnIndex1 = oldColumnGroup1.SortedColumnIndexes;
100      var keyColumnIndex2 = oldColumnGroup2.SortedColumnIndexes;
101
102      this.newColumnGroup1 = new ColumnGroup(this.oldColumnGroup1.Name);
103      this.newColumnGroup2 = new ColumnGroup(this.oldColumnGroup2.Name);
104      this.newColumnGroup1.SortedColumnIndexes = this.oldColumnGroup1.SortedColumnIndexes;
105      this.newColumnGroup2.SortedColumnIndexes = this.oldColumnGroup2.SortedColumnIndexes;
106
107      ColumnBase column;
108      foreach (ColumnBase col in this.oldColumnGroup1.Columns) {
109        column = col.CreateCopyOfColumnWithoutValues();
110        column.SortOrder = col.SortOrder;
111        this.newColumnGroup1.AddColumn(column);
112      }
113      foreach (ColumnBase col in this.oldColumnGroup2.Columns) {
114        column = col.CreateCopyOfColumnWithoutValues();
115        column.SortOrder = col.SortOrder;
116        this.newColumnGroup2.AddColumn(column);
117      }
118
119      int compareDirection = this.oldColumnGroup1.SortOrdersForColumns.ElementAt(oldColumnGroup1.SortedColumnIndexes.ElementAt(0))
120        == SortOrder.Ascending ? -1 : +1;
121      int i = 0;
122      int j = 0;
123      IComparable[] row1;
124      IComparable[] row2;
125      while (i < oldColumnGroup1.RowCount && j < oldColumnGroup2.RowCount) {
126        //key1 < key2
127        int cmpResult = CompareRows(oldColumnGroup1, i, keyColumnIndex1, oldColumnGroup2, j, keyColumnIndex2);
128        if (cmpResult == compareDirection) {//keyColumn1.GetValue(i).CompareTo(keyColumn2.GetValue(j)) == compareDirection) {
129          row1 = this.oldColumnGroup1.GetRow(i);
130          row2 = this.oldColumnGroup2.GetEmptyRow();
131          CopyRow(row1, keyColumnIndex1, row2, keyColumnIndex2);// row2[keyColumnIndex2] = row1[keyColumnIndex1];
132          i++;
133        }
134          //key1 == key2
135        else if (/*keyColumn1.GetValue(i).CompareTo(keyColumn2.GetValue(j))*/ cmpResult == 0) {
136          row1 = this.oldColumnGroup1.GetRow(i);
137          row2 = this.oldColumnGroup2.GetRow(j);
138          bool columnGroup1Dup = false;
139          bool columnGroup2Dup = false;
140          if (i + 1 < oldColumnGroup1.RowCount) {
141            columnGroup1Dup = CompareRows(oldColumnGroup1, i, keyColumnIndex1, oldColumnGroup1, i + 1, keyColumnIndex1) == 0;
142          }
143          if (j + 1 < oldColumnGroup2.RowCount) {
144            columnGroup2Dup = CompareRows(oldColumnGroup2, j, keyColumnIndex2, oldColumnGroup2, j + 1, keyColumnIndex2) == 0;
145          }
146          if (columnGroup1Dup && !columnGroup2Dup) {
147            i++; // only advance to the row of the duplicate
148          } else if (!columnGroup1Dup && columnGroup2Dup) {
149            j++;
150          } else {
151            // either both are a duplicates or neither is
152            i++;
153            j++;
154          }
155        }
156          //key1 > key2
157        else {
158          row1 = this.oldColumnGroup1.GetEmptyRow();
159          row2 = this.oldColumnGroup2.GetRow(j);
160          CopyRow(row2, keyColumnIndex2, row1, keyColumnIndex1);// row1[keyColumnIndex1] = row2[keyColumnIndex2];
161          j++;
162        }
163        this.newColumnGroup1.AddRow(row1);
164        this.newColumnGroup2.AddRow(row2);
165      }
166      for (; i < oldColumnGroup1.RowCount; i++) {
167        this.newColumnGroup1.AddRow(this.oldColumnGroup1.GetRow(i));
168        this.newColumnGroup2.AddRow(this.oldColumnGroup2.GetEmptyRow());
169        CopyRow(newColumnGroup2.GetRow(newColumnGroup2.RowCount - 1), keyColumnIndex2, oldColumnGroup1.GetRow(i), keyColumnIndex1);
170        ChangeRow(newColumnGroup2, newColumnGroup2.RowCount - 1, keyColumnIndex2, oldColumnGroup1, i, keyColumnIndex1);
171      }
172      for (; j < oldColumnGroup2.RowCount; j++) {
173        this.newColumnGroup1.AddRow(oldColumnGroup1.GetEmptyRow());
174        this.newColumnGroup2.AddRow(oldColumnGroup2.GetRow(j));
175        ChangeRow(newColumnGroup1, newColumnGroup1.RowCount - 1, keyColumnIndex1, oldColumnGroup2, j, keyColumnIndex2);
176      }
177    }
178
179    private void ChangeRow(ColumnGroup destGroup, int destRowIndex, IEnumerable<int> destColumnIndexes, ColumnGroup srcGroup, int srcRowIndex, IEnumerable<int> srcColumnIndexes) {
180      foreach (var indexPair in Zip(destColumnIndexes, srcColumnIndexes, (d, s) => new { DestIndex = d, SrcIndex = s })) {
181        destGroup.GetColumn(indexPair.DestIndex).ChangeValue(destRowIndex, srcGroup.GetColumn(indexPair.SrcIndex).GetValue(srcRowIndex));
182      }
183    }
184
185    private void CopyRow(IComparable[] src, IEnumerable<int> srcIndexes, IComparable[] dest, IEnumerable<int> destIndexes) {
186      if (srcIndexes.Count() != destIndexes.Count()) throw new ArgumentException();
187      foreach (var indexPair in Zip(srcIndexes, destIndexes, (k, l) => new { First = k, Second = l })) {
188        dest[indexPair.Second] = src[indexPair.First];
189      }
190    }
191
192    int CompareRows(ColumnGroup oldColumnGroup1, int i, IEnumerable<int> keyColumnIndex1, ColumnGroup oldColumnGroup2, int j, IEnumerable<int> keyColumnIndex2) {
193      if (keyColumnIndex1.Count() != keyColumnIndex2.Count()) throw new ArgumentException();
194      var valuePairs = from x in
195                         Zip(from index in keyColumnIndex1
196                             select oldColumnGroup1.GetColumn(index).GetValue(i),
197                             from index in keyColumnIndex2
198                             select oldColumnGroup2.GetColumn(index).GetValue(j),
199                             (k, l) => new { First = k, Second = l })
200                       select x;
201      foreach (var p in valuePairs) {
202        var result = p.First.CompareTo(p.Second);
203        if (result != 0) return result;
204      }
205      return 0;
206    }
207
208
209    private static IEnumerable<TResult> Zip<TFirst, TSecond, TResult>
210     (IEnumerable<TFirst> first,
211     IEnumerable<TSecond> second,
212     Func<TFirst, TSecond, TResult> resultSelector) {
213      using (IEnumerator<TFirst> e1 = first.GetEnumerator())
214      using (IEnumerator<TSecond> e2 = second.GetEnumerator())
215        while (e1.MoveNext() && e2.MoveNext())
216          yield return resultSelector(e1.Current, e2.Current);
217    }
218
219    public override string Description {
220      get { return "Align column groups"; }
221    }
222  }
223}
Note: See TracBrowser for help on using the repository browser.