Free cookie consent management tool by TermsFeed Policy Generator

source: addons/HeuristicLab.DataImporter/HeuristicLab.DataImporter.Command/ChangeDataset/AlignColumnGroupsCommand.cs @ 16567

Last change on this file since 16567 was 16567, checked in by gkronber, 5 years ago

#2520: changed StorableConstructors and added StorableType attributes in HeuristicLab.DataImporter addon

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