Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Optimization/3.3/RunCollection.cs @ 8238

Last change on this file since 8238 was 7798, checked in by mkommend, 13 years ago

#1843: Cleared dataType cache in RunCollection on collection reset.

File size: 17.2 KB
RevLine 
[3260]1#region License Information
2/* HeuristicLab
[7259]3 * Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
[3260]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
[3329]22using System;
[3260]23using System.Collections.Generic;
24using System.Linq;
[4068]25using HeuristicLab.Collections;
[3376]26using HeuristicLab.Common;
[3260]27using HeuristicLab.Core;
[3329]28using HeuristicLab.Data;
[3260]29using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
30
31namespace HeuristicLab.Optimization {
[3716]32  [Item("Run Collection", "Represents a collection of runs.")]
33  [Creatable("Testing & Analysis")]
[3260]34  [StorableClass]
[4419]35  public class RunCollection : ItemCollection<IRun>, IStringConvertibleMatrix, IStorableContent {
36    public string Filename { get; set; }
37
[4164]38    [StorableConstructor]
[4888]39    protected RunCollection(bool deserializing)
40      : base(deserializing) {
41      updateOfRunsInProgress = false;
42    }
[4722]43    protected RunCollection(RunCollection original, Cloner cloner)
44      : base(original, cloner) {
[4888]45      updateOfRunsInProgress = false;
[4722]46      resultNames = new List<string>(original.resultNames);
47      parameterNames = new List<string>(original.parameterNames);
48      dataTypes = new Dictionary<string, HashSet<Type>>();
49      foreach (string s in original.dataTypes.Keys)
50        dataTypes[s] = new HashSet<Type>(original.dataTypes[s]);
51
52      constraints = new RunCollectionConstraintCollection(original.constraints.Select(x => cloner.Clone(x)));
[6693]53      modifiers = new CheckedItemList<IRunCollectionModifier>(original.modifiers.Select(cloner.Clone));
[4722]54      foreach (IRunCollectionConstraint constraint in constraints)
55        constraint.ConstrainedValue = this;
56      RegisterConstraintsEvents();
57      RegisterConstraintEvents(constraints);
58
59      UpdateFiltering(true);
60    }
[3329]61    public RunCollection() : base() { Initialize(); }
62    public RunCollection(int capacity) : base(capacity) { Initialize(); }
63    public RunCollection(IEnumerable<IRun> collection) : base(collection) { Initialize(); this.OnItemsAdded(collection); }
[3447]64    private void Initialize() {
[4888]65      updateOfRunsInProgress = false;
[3447]66      parameterNames = new List<string>();
67      resultNames = new List<string>();
[3614]68      dataTypes = new Dictionary<string, HashSet<Type>>();
69      constraints = new RunCollectionConstraintCollection();
[6693]70      modifiers = new CheckedItemList<IRunCollectionModifier>();
[4164]71      RegisterConstraintsEvents();
[3447]72    }
[4164]73
[3625]74    [Storable]
[3614]75    private Dictionary<string, HashSet<Type>> dataTypes;
76    public IEnumerable<Type> GetDataType(string columnName) {
77      if (!dataTypes.ContainsKey(columnName))
78        return new Type[0];
79      return dataTypes[columnName];
80    }
[4164]81
82    [Storable]
[3614]83    private RunCollectionConstraintCollection constraints;
84    public RunCollectionConstraintCollection Constraints {
[3625]85      get { return constraints; }
[3614]86    }
[3329]87
[6693]88    [Storable]
89    private CheckedItemList<IRunCollectionModifier> modifiers;
90    public CheckedItemList<IRunCollectionModifier> Modifiers {
91      get { return modifiers; }
92    }
93
94
[4888]95    private bool updateOfRunsInProgress;
96    public bool UpdateOfRunsInProgress {
97      get { return updateOfRunsInProgress; }
98      set {
99        if (updateOfRunsInProgress != value) {
100          updateOfRunsInProgress = value;
101          OnUpdateOfRunsInProgressChanged();
102        }
103      }
104    }
105
106    [StorableHook(HookType.AfterDeserialization)]
107    private void AfterDeserialization() {
108      if (constraints == null) constraints = new RunCollectionConstraintCollection();
[6693]109      if (modifiers == null) modifiers = new CheckedItemList<IRunCollectionModifier>();
[4888]110      RegisterConstraintsEvents();
111      RegisterConstraintEvents(constraints);
112      UpdateFiltering(true);
113    }
114
115    public override IDeepCloneable Clone(Cloner cloner) {
116      return new RunCollection(this, cloner);
117    }
118
119    public event EventHandler UpdateOfRunsInProgressChanged;
120    protected virtual void OnUpdateOfRunsInProgressChanged() {
121      var handler = UpdateOfRunsInProgressChanged;
122      if (handler != null) handler(this, EventArgs.Empty);
123    }
124
[3329]125    protected override void OnCollectionReset(IEnumerable<IRun> items, IEnumerable<IRun> oldItems) {
126      parameterNames.Clear();
127      resultNames.Clear();
[7798]128      dataTypes.Clear();
[3329]129      foreach (IRun run in items) {
130        foreach (KeyValuePair<string, IItem> parameter in run.Parameters)
131          AddParameter(parameter.Key, parameter.Value);
132        foreach (KeyValuePair<string, IItem> result in run.Results)
133          AddResult(result.Key, result.Value);
134      }
[4200]135      columnNameCache = null;
[5150]136      OnColumnsChanged();
[3329]137      OnColumnNamesChanged();
[4200]138      rowNamesCache = null;
[4518]139      base.OnCollectionReset(items, oldItems);
[5150]140      OnRowsChanged();
[3329]141      OnRowNamesChanged();
[4518]142      OnReset();
143      UpdateFiltering(false);
[3329]144    }
145    protected override void OnItemsAdded(IEnumerable<IRun> items) {
[5150]146      bool columnsChanged = false;
[3329]147      foreach (IRun run in items) {
148        foreach (KeyValuePair<string, IItem> parameter in run.Parameters)
[5150]149          columnsChanged |= AddParameter(parameter.Key, parameter.Value);
[3329]150        foreach (KeyValuePair<string, IItem> result in run.Results)
[5150]151          columnsChanged |= AddResult(result.Key, result.Value);
[3329]152      }
[5150]153      if (columnsChanged) columnNameCache = null;
[4200]154      rowNamesCache = null;
[4518]155      base.OnItemsAdded(items);
[4707]156      OnReset();
[5150]157      OnRowsChanged();
[3329]158      OnRowNamesChanged();
[5150]159      if (columnsChanged) {
160        OnColumnsChanged();
161        OnColumnNamesChanged();
162      }
[4518]163      UpdateFiltering(false);
[3329]164    }
165    protected override void OnItemsRemoved(IEnumerable<IRun> items) {
[5150]166      bool columnsChanged = false;
[3329]167      foreach (IRun run in items) {
168        foreach (string parameterName in run.Parameters.Keys)
[5150]169          columnsChanged |= RemoveParameterName(parameterName);
[3329]170        foreach (string resultName in run.Results.Keys)
[5150]171          columnsChanged |= RemoveResultName(resultName);
[3329]172      }
[5150]173      if (columnsChanged) columnNameCache = null;
[4200]174      rowNamesCache = null;
[4518]175      base.OnItemsRemoved(items);
[4707]176      OnReset();
[5152]177      OnRowsChanged();
[3329]178      OnRowNamesChanged();
[5150]179      if (columnsChanged) {
180        OnColumnsChanged();
181        OnColumnNamesChanged();
182      }
[3329]183    }
184
185    private bool AddParameter(string name, IItem value) {
186      if (value == null)
187        return false;
[3441]188      if (!parameterNames.Contains(name)) {
[3329]189        parameterNames.Add(name);
[3614]190        dataTypes[name] = new HashSet<Type>();
191        dataTypes[name].Add(value.GetType());
[3329]192        return true;
193      }
[3614]194      dataTypes[name].Add(value.GetType());
[3329]195      return false;
196    }
197    private bool AddResult(string name, IItem value) {
198      if (value == null)
199        return false;
[3441]200      if (!resultNames.Contains(name)) {
[3329]201        resultNames.Add(name);
[3614]202        dataTypes[name] = new HashSet<Type>();
203        dataTypes[name].Add(value.GetType());
[3329]204        return true;
205      }
[3614]206      dataTypes[name].Add(value.GetType());
[3329]207      return false;
208    }
209    private bool RemoveParameterName(string name) {
210      if (!list.Any(x => x.Parameters.ContainsKey(name))) {
211        parameterNames.Remove(name);
212        return true;
213      }
214      return false;
215    }
216    private bool RemoveResultName(string name) {
217      if (!list.Any(x => x.Results.ContainsKey(name))) {
218        resultNames.Remove(name);
219        return true;
220      }
221      return false;
222    }
223
[3447]224    public IItem GetValue(int rowIndex, int columnIndex) {
225      IRun run = this.list[rowIndex];
[3492]226      return GetValue(run, columnIndex);
227    }
228
229    public IItem GetValue(IRun run, int columnIndex) {
[3717]230      string name = ((IStringConvertibleMatrix)this).ColumnNames.ElementAt(columnIndex);
231      return GetValue(run, name);
232    }
233
234    public IItem GetValue(IRun run, string columnName) {
[3447]235      IItem value = null;
[3767]236      if (run.Parameters.ContainsKey(columnName))
237        value = run.Parameters[columnName];
238      else if (run.Results.ContainsKey(columnName))
239        value = run.Results[columnName];
[3447]240      return value;
241    }
242
[3329]243    #region IStringConvertibleMatrix Members
[3347]244    [Storable]
[3329]245    private List<string> parameterNames;
[3492]246    public IEnumerable<string> ParameterNames {
247      get { return this.parameterNames; }
248    }
[3347]249    [Storable]
[3329]250    private List<string> resultNames;
[3492]251    public IEnumerable<string> ResultNames {
252      get { return this.resultNames; }
253    }
[3447]254    int IStringConvertibleMatrix.Rows {
[3329]255      get { return this.Count; }
[3447]256      set { throw new NotSupportedException(); }
[3329]257    }
[3447]258    int IStringConvertibleMatrix.Columns {
[3329]259      get { return parameterNames.Count + resultNames.Count; }
260      set { throw new NotSupportedException(); }
261    }
[4200]262    private List<string> columnNameCache;
[3447]263    IEnumerable<string> IStringConvertibleMatrix.ColumnNames {
[3329]264      get {
[4200]265        if (columnNameCache == null) {
266          columnNameCache = new List<string>(parameterNames);
267          columnNameCache.AddRange(resultNames);
268          columnNameCache.Sort();
269        }
270        return columnNameCache;
[3329]271      }
272      set { throw new NotSupportedException(); }
273    }
[4200]274    private List<string> rowNamesCache;
[3447]275    IEnumerable<string> IStringConvertibleMatrix.RowNames {
[4200]276      get {
277        if (rowNamesCache == null)
278          rowNamesCache = list.Select(x => x.Name).ToList();
279        return rowNamesCache;
280      }
[3329]281      set { throw new NotSupportedException(); }
282    }
[3447]283    bool IStringConvertibleMatrix.SortableView {
[3329]284      get { return true; }
285      set { throw new NotSupportedException(); }
286    }
[3447]287    bool IStringConvertibleMatrix.ReadOnly {
288      get { return true; }
[3430]289    }
[3329]290
[3447]291    string IStringConvertibleMatrix.GetValue(int rowIndex, int columnIndex) {
292      IItem value = GetValue(rowIndex, columnIndex);
293      if (value == null)
294        return string.Empty;
295      return value.ToString();
[3329]296    }
297
298    public event EventHandler<EventArgs<int, int>> ItemChanged;
299    protected virtual void OnItemChanged(int rowIndex, int columnIndex) {
[4722]300      EventHandler<EventArgs<int, int>> handler = ItemChanged;
301      if (handler != null) handler(this, new EventArgs<int, int>(rowIndex, columnIndex));
[3329]302      OnToStringChanged();
303    }
304    public event EventHandler Reset;
305    protected virtual void OnReset() {
[4722]306      EventHandler handler = Reset;
307      if (handler != null) handler(this, EventArgs.Empty);
[3329]308      OnToStringChanged();
309    }
[5150]310    public event EventHandler ColumnsChanged;
311    protected virtual void OnColumnsChanged() {
312      var handler = ColumnsChanged;
313      if (handler != null) handler(this, EventArgs.Empty);
314    }
315    public event EventHandler RowsChanged;
316    protected virtual void OnRowsChanged() {
317      var handler = RowsChanged;
318      if (handler != null) handler(this, EventArgs.Empty);
319    }
[3329]320    public event EventHandler ColumnNamesChanged;
321    protected virtual void OnColumnNamesChanged() {
322      EventHandler handler = ColumnNamesChanged;
[4722]323      if (handler != null) handler(this, EventArgs.Empty);
[3329]324    }
325    public event EventHandler RowNamesChanged;
326    protected virtual void OnRowNamesChanged() {
327      EventHandler handler = RowNamesChanged;
[4722]328      if (handler != null) handler(this, EventArgs.Empty);
[3329]329    }
330    public event EventHandler SortableViewChanged;
[3333]331    protected virtual void OnSortableViewChanged() {
332      EventHandler handler = SortableViewChanged;
[4722]333      if (handler != null) handler(this, EventArgs.Empty);
[3333]334    }
335
[3329]336    public bool Validate(string value, out string errorMessage) { throw new NotSupportedException(); }
337    public bool SetValue(string value, int rowIndex, int columnIndex) { throw new NotSupportedException(); }
338    #endregion
[3614]339
[4888]340    #region Filtering
[3632]341    private void UpdateFiltering(bool reset) {
[4888]342      UpdateOfRunsInProgress = true;
[3632]343      if (reset)
344        list.ForEach(r => r.Visible = true);
[3614]345      foreach (IRunCollectionConstraint constraint in this.constraints)
346        constraint.Check();
[4888]347      UpdateOfRunsInProgress = false;
[3614]348    }
349
[4164]350    private void RegisterConstraintsEvents() {
351      constraints.ItemsAdded += new CollectionItemsChangedEventHandler<IRunCollectionConstraint>(Constraints_ItemsAdded);
352      constraints.ItemsRemoved += new CollectionItemsChangedEventHandler<IRunCollectionConstraint>(Constraints_ItemsRemoved);
353      constraints.CollectionReset += new CollectionItemsChangedEventHandler<IRunCollectionConstraint>(Constraints_CollectionReset);
354    }
355
[3614]356    protected virtual void RegisterConstraintEvents(IEnumerable<IRunCollectionConstraint> constraints) {
357      foreach (IRunCollectionConstraint constraint in constraints) {
358        constraint.ActiveChanged += new EventHandler(Constraint_ActiveChanged);
359        constraint.ConstrainedValueChanged += new EventHandler(Constraint_ConstrainedValueChanged);
360        constraint.ConstraintOperationChanged += new EventHandler(Constraint_ConstraintOperationChanged);
361        constraint.ConstraintDataChanged += new EventHandler(Constraint_ConstraintDataChanged);
362      }
363    }
364    protected virtual void DeregisterConstraintEvents(IEnumerable<IRunCollectionConstraint> constraints) {
365      foreach (IRunCollectionConstraint constraint in constraints) {
366        constraint.ActiveChanged -= new EventHandler(Constraint_ActiveChanged);
367        constraint.ConstrainedValueChanged -= new EventHandler(Constraint_ConstrainedValueChanged);
368        constraint.ConstraintOperationChanged -= new EventHandler(Constraint_ConstraintOperationChanged);
369        constraint.ConstraintDataChanged -= new EventHandler(Constraint_ConstraintDataChanged);
370      }
371    }
372
373    protected virtual void Constraints_CollectionReset(object sender, CollectionItemsChangedEventArgs<IRunCollectionConstraint> e) {
374      DeregisterConstraintEvents(e.OldItems);
375      RegisterConstraintEvents(e.Items);
[3632]376      this.UpdateFiltering(true);
[3614]377    }
378    protected virtual void Constraints_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IRunCollectionConstraint> e) {
379      RegisterConstraintEvents(e.Items);
380      foreach (IRunCollectionConstraint constraint in e.Items)
381        constraint.ConstrainedValue = this;
[3632]382      this.UpdateFiltering(false);
[3614]383    }
384    protected virtual void Constraints_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IRunCollectionConstraint> e) {
385      DeregisterConstraintEvents(e.Items);
[3632]386      this.UpdateFiltering(true);
[3614]387    }
388    protected virtual void Constraint_ActiveChanged(object sender, EventArgs e) {
[3632]389      IRunCollectionConstraint constraint = (IRunCollectionConstraint)sender;
390      this.UpdateFiltering(!constraint.Active);
[3614]391    }
392    protected virtual void Constraint_ConstrainedValueChanged(object sender, EventArgs e) {
393      //mkommend: this method is intentionally left empty, because the constrainedValue is set in the ItemsAdded method
394    }
395    protected virtual void Constraint_ConstraintOperationChanged(object sender, EventArgs e) {
[3632]396      IRunCollectionConstraint constraint = (IRunCollectionConstraint)sender;
397      if (constraint.Active)
398        this.UpdateFiltering(true);
[3614]399    }
400    protected virtual void Constraint_ConstraintDataChanged(object sender, EventArgs e) {
[3632]401      IRunCollectionConstraint constraint = (IRunCollectionConstraint)sender;
402      if (constraint.Active)
403        this.UpdateFiltering(true);
[3614]404    }
405    #endregion
[6693]406
407    #region Modification
408    public void Modify() {
409      UpdateOfRunsInProgress = true;
410      var runs = this.ToList();
411      var selectedRuns = runs.Where(r => r.Visible).ToList();
412      int nSelected = selectedRuns.Count;
413      if (nSelected > 0) {
414        foreach (var modifier in Modifiers.CheckedItems)
415          modifier.Value.Modify(selectedRuns);
416        if (nSelected != selectedRuns.Count || HaveDifferentOrder(selectedRuns, runs.Where(r => r.Visible))) {
417          Clear();
418          AddRange(ReplaceVisibleRuns(runs, selectedRuns));
419        } else if (runs.Count > 0) {
420          OnCollectionReset(this, runs);
421        }
422      }
423      UpdateOfRunsInProgress = false;
424    }
425
426    private static IEnumerable<IRun> ReplaceVisibleRuns(IEnumerable<IRun> runs, IEnumerable<IRun> visibleRuns) {
427      var newRuns = new List<IRun>();
428      var runIt = runs.GetEnumerator();
429      var visibleRunIt = visibleRuns.GetEnumerator();
430      while (runIt.MoveNext()) {
431        if (runIt.Current != null && !runIt.Current.Visible)
432          newRuns.Add(runIt.Current);
433        else if (visibleRunIt.MoveNext())
434          newRuns.Add(visibleRunIt.Current);
435      }
436      while (visibleRunIt.MoveNext())
437        newRuns.Add(visibleRunIt.Current);
438      return newRuns;
439    }
440
441    private static bool HaveDifferentOrder(IEnumerable<IRun> l1, IEnumerable<IRun> l2) {
442      return l1.Zip(l2, (r1, r2) => r1 != r2).Any();
443    }
444    #endregion
[3260]445  }
446}
Note: See TracBrowser for help on using the repository browser.