Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 12947 was 9615, checked in by mkommend, 11 years ago

#1734: Updated copyright information in all DataImporter classes.

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