Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 6133 was 6133, checked in by gkronber, 13 years ago

#1471: imported generic parts of DataImporter from private code base

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