#region License Information /* HeuristicLab * Copyright (C) 2002-2010 Heuristic and Evolutionary Algorithms Laboratory (HEAL) * * This file is part of HeuristicLab. * * HeuristicLab is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * HeuristicLab is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with HeuristicLab. If not, see . */ #endregion using System; using System.Collections.Generic; using System.Linq; using HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.Data; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; using HeuristicLab.Collections; namespace HeuristicLab.Optimization { [Item("Run Collection", "Represents a collection of runs.")] [Creatable("Testing & Analysis")] [StorableClass] public class RunCollection : ItemCollection, IStringConvertibleMatrix { public RunCollection() : base() { Initialize(); } public RunCollection(int capacity) : base(capacity) { Initialize(); } public RunCollection(IEnumerable collection) : base(collection) { Initialize(); this.OnItemsAdded(collection); } private void Initialize() { parameterNames = new List(); resultNames = new List(); dataTypes = new Dictionary>(); constraints = new RunCollectionConstraintCollection(); constraints.ItemsAdded += new CollectionItemsChangedEventHandler(Constraints_ItemsAdded); constraints.ItemsRemoved += new CollectionItemsChangedEventHandler(Constraints_ItemsRemoved); constraints.CollectionReset += new CollectionItemsChangedEventHandler(Constraints_CollectionReset); } [Storable] private Dictionary> dataTypes; public IEnumerable GetDataType(string columnName) { if (!dataTypes.ContainsKey(columnName)) return new Type[0]; return dataTypes[columnName]; } private RunCollectionConstraintCollection constraints; public RunCollectionConstraintCollection Constraints { get { return constraints; } } protected override void OnCollectionReset(IEnumerable items, IEnumerable oldItems) { parameterNames.Clear(); resultNames.Clear(); foreach (IRun run in items) { foreach (KeyValuePair parameter in run.Parameters) AddParameter(parameter.Key, parameter.Value); foreach (KeyValuePair result in run.Results) AddResult(result.Key, result.Value); } base.OnCollectionReset(items, oldItems); OnReset(); OnColumnNamesChanged(); OnRowNamesChanged(); } protected override void OnItemsAdded(IEnumerable items) { bool columnNamesChanged = false; foreach (IRun run in items) { foreach (KeyValuePair parameter in run.Parameters) columnNamesChanged |= AddParameter(parameter.Key, parameter.Value); foreach (KeyValuePair result in run.Results) columnNamesChanged |= AddResult(result.Key, result.Value); } base.OnItemsAdded(items); OnReset(); if (columnNamesChanged) OnColumnNamesChanged(); OnRowNamesChanged(); this.UpdateFiltering(false); } protected override void OnItemsRemoved(IEnumerable items) { bool columnNamesChanged = false; foreach (IRun run in items) { foreach (string parameterName in run.Parameters.Keys) columnNamesChanged |= RemoveParameterName(parameterName); foreach (string resultName in run.Results.Keys) columnNamesChanged |= RemoveResultName(resultName); } base.OnItemsRemoved(items); OnReset(); if (columnNamesChanged) OnColumnNamesChanged(); OnRowNamesChanged(); } private bool AddParameter(string name, IItem value) { if (value == null) return false; if (!parameterNames.Contains(name)) { parameterNames.Add(name); dataTypes[name] = new HashSet(); dataTypes[name].Add(value.GetType()); return true; } dataTypes[name].Add(value.GetType()); return false; } private bool AddResult(string name, IItem value) { if (value == null) return false; if (!resultNames.Contains(name)) { resultNames.Add(name); dataTypes[name] = new HashSet(); dataTypes[name].Add(value.GetType()); return true; } dataTypes[name].Add(value.GetType()); return false; } private bool RemoveParameterName(string name) { if (!list.Any(x => x.Parameters.ContainsKey(name))) { parameterNames.Remove(name); return true; } return false; } private bool RemoveResultName(string name) { if (!list.Any(x => x.Results.ContainsKey(name))) { resultNames.Remove(name); return true; } return false; } public IItem GetValue(int rowIndex, int columnIndex) { IRun run = this.list[rowIndex]; return GetValue(run, columnIndex); } public IItem GetValue(IRun run, int columnIndex) { IItem value = null; if (columnIndex < parameterNames.Count) { string parameterName = parameterNames[columnIndex]; if (run.Parameters.ContainsKey(parameterName)) value = run.Parameters[parameterName]; } else if (columnIndex < parameterNames.Count + resultNames.Count) { string resultName = resultNames[columnIndex - parameterNames.Count]; if (run.Results.ContainsKey(resultName)) value = run.Results[resultName]; } return value; } public override IDeepCloneable Clone(Cloner cloner) { RunCollection clone = (RunCollection)base.Clone(cloner); clone.resultNames = new List(this.resultNames); clone.parameterNames = new List(this.parameterNames); clone.dataTypes = new Dictionary>(); foreach (string s in this.dataTypes.Keys) clone.dataTypes[s] = new HashSet(this.dataTypes[s]); return clone; } #region IStringConvertibleMatrix Members [Storable] private List parameterNames; public IEnumerable ParameterNames { get { return this.parameterNames; } } [Storable] private List resultNames; public IEnumerable ResultNames { get { return this.resultNames; } } int IStringConvertibleMatrix.Rows { get { return this.Count; } set { throw new NotSupportedException(); } } int IStringConvertibleMatrix.Columns { get { return parameterNames.Count + resultNames.Count; } set { throw new NotSupportedException(); } } IEnumerable IStringConvertibleMatrix.ColumnNames { get { List value = new List(parameterNames); value.AddRange(resultNames); return value; } set { throw new NotSupportedException(); } } IEnumerable IStringConvertibleMatrix.RowNames { get { return list.Select(x => x.Name).ToList(); } set { throw new NotSupportedException(); } } bool IStringConvertibleMatrix.SortableView { get { return true; } set { throw new NotSupportedException(); } } bool IStringConvertibleMatrix.ReadOnly { get { return true; } } string IStringConvertibleMatrix.GetValue(int rowIndex, int columnIndex) { IItem value = GetValue(rowIndex, columnIndex); if (value == null) return string.Empty; return value.ToString(); } public event EventHandler> ItemChanged; protected virtual void OnItemChanged(int rowIndex, int columnIndex) { if (ItemChanged != null) ItemChanged(this, new EventArgs(rowIndex, columnIndex)); OnToStringChanged(); } public event EventHandler Reset; protected virtual void OnReset() { if (Reset != null) Reset(this, EventArgs.Empty); OnToStringChanged(); } public event EventHandler ColumnNamesChanged; protected virtual void OnColumnNamesChanged() { EventHandler handler = ColumnNamesChanged; if (handler != null) handler(this, EventArgs.Empty); } public event EventHandler RowNamesChanged; protected virtual void OnRowNamesChanged() { EventHandler handler = RowNamesChanged; if (handler != null) handler(this, EventArgs.Empty); } public event EventHandler SortableViewChanged; protected virtual void OnSortableViewChanged() { EventHandler handler = SortableViewChanged; if (handler != null) handler(this, EventArgs.Empty); } public bool Validate(string value, out string errorMessage) { throw new NotSupportedException(); } public bool SetValue(string value, int rowIndex, int columnIndex) { throw new NotSupportedException(); } #endregion #region filtering private void UpdateFiltering(bool reset) { if (reset) list.ForEach(r => r.Visible = true); foreach (IRunCollectionConstraint constraint in this.constraints) constraint.Check(); } protected virtual void RegisterConstraintEvents(IEnumerable constraints) { foreach (IRunCollectionConstraint constraint in constraints) { constraint.ActiveChanged += new EventHandler(Constraint_ActiveChanged); constraint.ConstrainedValueChanged += new EventHandler(Constraint_ConstrainedValueChanged); constraint.ConstraintOperationChanged += new EventHandler(Constraint_ConstraintOperationChanged); constraint.ConstraintDataChanged += new EventHandler(Constraint_ConstraintDataChanged); } } protected virtual void DeregisterConstraintEvents(IEnumerable constraints) { foreach (IRunCollectionConstraint constraint in constraints) { constraint.ActiveChanged -= new EventHandler(Constraint_ActiveChanged); constraint.ConstrainedValueChanged -= new EventHandler(Constraint_ConstrainedValueChanged); constraint.ConstraintOperationChanged -= new EventHandler(Constraint_ConstraintOperationChanged); constraint.ConstraintDataChanged -= new EventHandler(Constraint_ConstraintDataChanged); } } protected virtual void Constraints_CollectionReset(object sender, CollectionItemsChangedEventArgs e) { DeregisterConstraintEvents(e.OldItems); RegisterConstraintEvents(e.Items); this.UpdateFiltering(true); } protected virtual void Constraints_ItemsAdded(object sender, CollectionItemsChangedEventArgs e) { RegisterConstraintEvents(e.Items); foreach (IRunCollectionConstraint constraint in e.Items) constraint.ConstrainedValue = this; this.UpdateFiltering(false); } protected virtual void Constraints_ItemsRemoved(object sender, CollectionItemsChangedEventArgs e) { DeregisterConstraintEvents(e.Items); this.UpdateFiltering(true); } protected virtual void Constraint_ActiveChanged(object sender, EventArgs e) { IRunCollectionConstraint constraint = (IRunCollectionConstraint)sender; this.UpdateFiltering(!constraint.Active); } protected virtual void Constraint_ConstrainedValueChanged(object sender, EventArgs e) { //mkommend: this method is intentionally left empty, because the constrainedValue is set in the ItemsAdded method } protected virtual void Constraint_ConstraintOperationChanged(object sender, EventArgs e) { IRunCollectionConstraint constraint = (IRunCollectionConstraint)sender; if (constraint.Active) this.UpdateFiltering(true); } protected virtual void Constraint_ConstraintDataChanged(object sender, EventArgs e) { IRunCollectionConstraint constraint = (IRunCollectionConstraint)sender; if (constraint.Active) this.UpdateFiltering(true); } #endregion } }