#region License Information /* HeuristicLab * Copyright (C) 2002-2018 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.Drawing; using HeuristicLab.Common; using HeuristicLab.Common.Resources; using HeuristicLab.Core; using HeuristicLab.Parameters; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; namespace HeuristicLab.Optimization { [Item("ResultParameter", "A parameter whose value is written to a result collection.")] [StorableClass] public sealed class ResultParameter : LookupParameter, IResultParameter where T : class, IItem { public override Image ItemImage { get { return VSImageLibrary.Exception; } } public override bool CanChangeDescription { get { return true; } } [Storable] private string resultCollectionName; public string ResultCollectionName { get { return resultCollectionName; } set { if (value == null) throw new ArgumentNullException(); if (string.IsNullOrWhiteSpace(value)) throw new ArgumentNullException(); else if (!value.Equals(resultCollectionName)) { resultCollectionName = value; OnResultCollectionNameChanged(); } } } [Storable] private T defaultValue; public T DefaultValue { get { return defaultValue; } set { if (value != defaultValue) { defaultValue = value; OnDefaultValueChanged(); } } } [StorableConstructor] private ResultParameter(bool deserializing) : base(deserializing) { } private ResultParameter(ResultParameter original, Cloner cloner) : base(original, cloner) { resultCollectionName = original.resultCollectionName; defaultValue = cloner.Clone(original.defaultValue); } public override IDeepCloneable Clone(Cloner cloner) { return new ResultParameter(this, cloner); } public ResultParameter() : this("Anonymous", string.Empty, "Results") { } public ResultParameter(string name, string description) : this(name, description, "Results") { } public ResultParameter(string name, string description, string resultCollectionName) : base(name, description, string.Empty) { if (string.IsNullOrEmpty(resultCollectionName)) throw new ArgumentException("resultCollectionName"); this.resultCollectionName = resultCollectionName; Hidden = false; } public ResultParameter(string name, string description, string resultCollectionName, T defaultValue) : base(name, description, string.Empty) { if (string.IsNullOrEmpty(resultCollectionName)) throw new ArgumentException("resultCollectionName"); if (defaultValue == null) throw new ArgumentNullException("defaultValue"); this.resultCollectionName = resultCollectionName; this.defaultValue = defaultValue; Hidden = false; } protected override IItem GetActualValue() { ResultCollection results; if (CachedActualValue != null) { results = CachedActualValue as ResultCollection; if (results == null) throw new InvalidOperationException("ResultParameter (" + ActualName + "): ResultCollection not found."); } else { var tmp = ResultCollectionName; // verifyType has to be disabled, because the ResultCollection may not be identical to the generic type of the parameter results = GetValue(ExecutionContext, ref tmp) as ResultCollection; if (results == null) throw new InvalidOperationException("ResultParameter (" + ActualName + "): ResultCollection with name " + tmp + " not found."); CachedActualValue = results; } IResult result; if (!results.TryGetValue(ActualName, out result)) { if (DefaultValue == null) throw new InvalidOperationException("ResultParameter (" + ActualName + "): Result not found and no default value specified."); result = ItemDescription == Description ? new Result(ActualName, (T)DefaultValue.Clone()) : new Result(ActualName, Description, (T)DefaultValue.Clone()); results.Add(result); } var resultValue = result.Value as T; if (resultValue == null) throw new InvalidOperationException(string.Format("Type mismatch. Result \"{0}\" does not contain a \"{1}\".", ActualName, typeof(T).GetPrettyName())); return resultValue; } protected override void SetActualValue(IItem value) { ResultCollection results; if (CachedActualValue != null) { results = CachedActualValue as ResultCollection; if (results == null) throw new InvalidOperationException("ResultParameter (" + ActualName + "): ResultCollection not found."); } else { var tmp = ResultCollectionName; results = GetValue(ExecutionContext, ref tmp) as ResultCollection; if (results == null) throw new InvalidOperationException("ResultParameter (" + ActualName + "): ResultCollection with name " + tmp + " not found."); CachedActualValue = results; } IResult result; if (!results.TryGetValue(ActualName, out result)) { result = ItemDescription == Description ? new Result(ActualName, value) : new Result(ActualName, Description, value); results.Add(result); } else result.Value = value; } public event EventHandler ResultCollectionNameChanged; private void OnResultCollectionNameChanged() { var handler = ResultCollectionNameChanged; if (handler != null) handler(this, EventArgs.Empty); OnToStringChanged(); } public event EventHandler DefaultValueChanged; private void OnDefaultValueChanged() { EventHandler handler = DefaultValueChanged; if (handler != null) handler(this, EventArgs.Empty); OnItemImageChanged(); } } }