#region License Information /* HeuristicLab * Copyright (C) 2002-2016 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.Threading; using System.Threading.Tasks; using HeuristicLab.Clients.Access; using HeuristicLab.Collections; using HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.Optimization; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; using HeuristicLab.Persistence.Default.Xml; using System; using System.Collections.Generic; using System.Drawing; using System.IO; using System.Linq; namespace HeuristicLab.Clients.OKB.RunCreation { [Item("OKB Algorithm", "An algorithm which is stored in the OKB.")] [Creatable(CreatableAttribute.Categories.TestingAndAnalysisOKB, Priority = 100)] [StorableClass] public sealed class OKBAlgorithm : Item, IAlgorithm, IStorableContent { public string Filename { get; set; } private long algorithmId; public long AlgorithmId { get { return algorithmId; } } private IAlgorithm algorithm; private IAlgorithm Algorithm { get { return algorithm; } set { if (value == null) throw new ArgumentNullException("Algorithm", "Algorithm cannot be null."); if (value != algorithm) { CancelEventArgs e = new CancelEventArgs(value.Name); OnNameChanging(e); if (!e.Cancel) { IProblem problem = algorithm.Problem; DeregisterAlgorithmEvents(); algorithm = value; RegisterAlgorithmEvents(); OnToStringChanged(); OnItemImageChanged(); OnNameChanged(); OnDescriptionChanged(); OnAlgorithmChanged(); OnStoreAlgorithmInEachRunChanged(); try { algorithm.Problem = problem; } catch (ArgumentException) { algorithm.Problem = null; } algorithm.Prepare(true); } } } } public IEnumerable NestedOptimizers { get { // inner algorithm cannot be accessed directly return Enumerable.Empty(); } } public override Image ItemImage { get { return Algorithm.ItemImage; } } public static new Image StaticItemImage { get { return HeuristicLab.Common.Resources.VSImageLibrary.Event; } } public string Name { get { return Algorithm.Name; } set { throw new NotSupportedException("Name cannot be changed."); } } public string Description { get { return Algorithm.Description; } set { throw new NotSupportedException("Description cannot be changed."); } } public bool CanChangeName { get { return false; } } public bool CanChangeDescription { get { return false; } } public IKeyedItemCollection Parameters { get { return Algorithm.Parameters; } } public ExecutionState ExecutionState { get { return Algorithm.ExecutionState; } } public TimeSpan ExecutionTime { get { return Algorithm.ExecutionTime; } } public Type ProblemType { get { return Algorithm.ProblemType; } } public IProblem Problem { get { return Algorithm.Problem; } set { Algorithm.Problem = value; } } public ResultCollection Results { get { return Algorithm.Results; } } private RunCollection runs; public RunCollection Runs { get { return runs; } } private bool storeRunsAutomatically; public bool StoreRunsAutomatically { get { return storeRunsAutomatically; } set { if (value != storeRunsAutomatically) { storeRunsAutomatically = value; OnStoreRunsAutomaticallyChanged(); } } } public bool StoreAlgorithmInEachRun { get { return Algorithm.StoreAlgorithmInEachRun; } set { Algorithm.StoreAlgorithmInEachRun = value; } } #region Persistence Properties [Storable] private Guid UserId; [Storable(Name = "AlgorithmId")] private long StorableAlgorithmId { get { return algorithmId; } set { algorithmId = value; } } [Storable(Name = "Algorithm")] private IAlgorithm StorableAlgorithm { get { return algorithm; } set { algorithm = value; RegisterAlgorithmEvents(); } } [Storable(Name = "Runs")] private RunCollection StorableRuns { get { return runs; } set { runs = value; RegisterRunsEvents(); } } [Storable(Name = "StoreRunsAutomatically")] private bool StorableStoreRunsAutomatically { get { return storeRunsAutomatically; } set { storeRunsAutomatically = value; } } #endregion [StorableConstructor] private OKBAlgorithm(bool deserializing) : base(deserializing) { } private OKBAlgorithm(OKBAlgorithm original, Cloner cloner) : base(original, cloner) { algorithmId = original.algorithmId; algorithm = cloner.Clone(original.algorithm); RegisterAlgorithmEvents(); runs = cloner.Clone(original.runs); storeRunsAutomatically = original.storeRunsAutomatically; UserId = original.UserId; RegisterRunsEvents(); } public OKBAlgorithm() : base() { algorithmId = -1; algorithm = new EmptyAlgorithm("No algorithm selected. Please choose an algorithm from the OKB."); RegisterAlgorithmEvents(); runs = new RunCollection(); storeRunsAutomatically = true; RegisterRunsEvents(); } private void CheckUserPermissions() { if (UserInformation.Instance.UserExists) { if (UserInformation.Instance.User.Roles.Count(x => x.Name == OKBRoles.OKBUser || x.Name == OKBRoles.OKBAdministrator) > 0) { UserId = UserInformation.Instance.User.Id; } else { throw new Exception("You don't have the appropriate roles for executing OKB Algorithms."); } } else { throw new Exception("You need an user account for executing OKB Algorithms."); } } public override IDeepCloneable Clone(Cloner cloner) { return new OKBAlgorithm(this, cloner); } public void Load(long algorithmId) { if (this.algorithmId != algorithmId) { IAlgorithm algorithm; byte[] algorithmData = RunCreationClient.Instance.GetAlgorithmData(algorithmId); using (MemoryStream stream = new MemoryStream(algorithmData)) { algorithm = XmlParser.Deserialize(stream); } this.algorithmId = algorithmId; Algorithm = algorithm; } } public IAlgorithm CloneAlgorithm() { return (IAlgorithm)Algorithm.Clone(); } public void CollectParameterValues(IDictionary values) { Algorithm.CollectParameterValues(values); } public void CollectResultValues(IDictionary values) { Algorithm.CollectResultValues(values); } public void Prepare() { Algorithm.Prepare(); } public void Prepare(bool clearRuns) { if (clearRuns) runs.Clear(); Algorithm.Prepare(clearRuns); } public void Start() { Start(CancellationToken.None); } public void Start(CancellationToken cancellationToken) { CheckUserPermissions(); if (!ClientInformation.Instance.ClientExists && storeRunsAutomatically) { throw new MissingClientRegistrationException(); } Algorithm.Start(cancellationToken); } public async Task StartAsync() { await StartAsync(CancellationToken.None); } public async Task StartAsync(CancellationToken cancellationToken) { await AsyncHelper.DoAsync(Start, cancellationToken); } public void Pause() { Algorithm.Pause(); } public void Stop() { Algorithm.Stop(); } #region Events public event EventHandler AlgorithmChanged; private void OnAlgorithmChanged() { EventHandler handler = AlgorithmChanged; if (handler != null) handler(this, EventArgs.Empty); } public event EventHandler> NameChanging; private void OnNameChanging(CancelEventArgs e) { var handler = NameChanging; if (handler != null) handler(this, e); } public event EventHandler NameChanged; private void OnNameChanged() { var handler = NameChanged; if (handler != null) handler(this, EventArgs.Empty); } public event EventHandler DescriptionChanged; private void OnDescriptionChanged() { var handler = DescriptionChanged; if (handler != null) handler(this, EventArgs.Empty); } public event EventHandler ExecutionStateChanged; private void OnExecutionStateChanged() { var handler = ExecutionStateChanged; if (handler != null) handler(this, EventArgs.Empty); } public event EventHandler ExecutionTimeChanged; private void OnExecutionTimeChanged() { var handler = ExecutionTimeChanged; if (handler != null) handler(this, EventArgs.Empty); } public event EventHandler ProblemChanged; private void OnProblemChanged() { var handler = ProblemChanged; if (handler != null) handler(this, EventArgs.Empty); } public event EventHandler StoreRunsAutomaticallyChanged; private void OnStoreRunsAutomaticallyChanged() { var handler = StoreRunsAutomaticallyChanged; if (handler != null) handler(this, EventArgs.Empty); } public event EventHandler StoreAlgorithmInEachRunChanged; private void OnStoreAlgorithmInEachRunChanged() { var handler = StoreAlgorithmInEachRunChanged; if (handler != null) handler(this, EventArgs.Empty); } public event EventHandler Prepared; private void OnPrepared() { var handler = Prepared; if (handler != null) handler(this, EventArgs.Empty); } public event EventHandler Started; private void OnStarted() { var handler = Started; if (handler != null) handler(this, EventArgs.Empty); } public event EventHandler Paused; private void OnPaused() { var handler = Paused; if (handler != null) handler(this, EventArgs.Empty); } public event EventHandler Stopped; private void OnStopped() { var handler = Stopped; if (handler != null) handler(this, EventArgs.Empty); } public event EventHandler> ExceptionOccurred; private void OnExceptionOccurred(Exception exception) { var handler = ExceptionOccurred; if (handler != null) handler(this, new EventArgs(exception)); } private void RegisterAlgorithmEvents() { if (Algorithm != null) { Algorithm.ToStringChanged += new EventHandler(Algorithm_ToStringChanged); Algorithm.ItemImageChanged += new EventHandler(Algorithm_ItemImageChanged); Algorithm.NameChanging += new EventHandler>(Algorithm_NameChanging); Algorithm.NameChanged += new EventHandler(Algorithm_NameChanged); Algorithm.DescriptionChanged += new EventHandler(Algorithm_DescriptionChanged); Algorithm.ExecutionStateChanged += new EventHandler(Algorithm_ExecutionStateChanged); Algorithm.ExecutionTimeChanged += new EventHandler(Algorithm_ExecutionTimeChanged); Algorithm.ProblemChanged += new EventHandler(Algorithm_ProblemChanged); Algorithm.Runs.ItemsAdded += new CollectionItemsChangedEventHandler(Algorithm_Runs_ItemsAdded); Algorithm.StoreAlgorithmInEachRunChanged += new EventHandler(Algorithm_StoreAlgorithmInEachRunChanged); Algorithm.Prepared += new EventHandler(Algorithm_Prepared); Algorithm.Started += new EventHandler(Algorithm_Started); Algorithm.Paused += new EventHandler(Algorithm_Paused); Algorithm.Stopped += new EventHandler(Algorithm_Stopped); Algorithm.ExceptionOccurred += new EventHandler>(Algorithm_ExceptionOccurred); } } private void DeregisterAlgorithmEvents() { if (Algorithm != null) { Algorithm.ToStringChanged -= new EventHandler(Algorithm_ToStringChanged); Algorithm.ItemImageChanged -= new EventHandler(Algorithm_ItemImageChanged); Algorithm.NameChanging -= new EventHandler>(Algorithm_NameChanging); Algorithm.NameChanged -= new EventHandler(Algorithm_NameChanged); Algorithm.DescriptionChanged -= new EventHandler(Algorithm_DescriptionChanged); Algorithm.ExecutionStateChanged -= new EventHandler(Algorithm_ExecutionStateChanged); Algorithm.ExecutionTimeChanged -= new EventHandler(Algorithm_ExecutionTimeChanged); Algorithm.ProblemChanged -= new EventHandler(Algorithm_ProblemChanged); Algorithm.Runs.ItemsAdded -= new CollectionItemsChangedEventHandler(Algorithm_Runs_ItemsAdded); Algorithm.StoreAlgorithmInEachRunChanged -= new EventHandler(Algorithm_StoreAlgorithmInEachRunChanged); Algorithm.Prepared -= new EventHandler(Algorithm_Prepared); Algorithm.Started -= new EventHandler(Algorithm_Started); Algorithm.Paused -= new EventHandler(Algorithm_Paused); Algorithm.Stopped -= new EventHandler(Algorithm_Stopped); Algorithm.ExceptionOccurred -= new EventHandler>(Algorithm_ExceptionOccurred); } } private void Algorithm_ToStringChanged(object sender, EventArgs e) { OnToStringChanged(); } private void Algorithm_ItemImageChanged(object sender, EventArgs e) { OnItemImageChanged(); } private void Algorithm_NameChanging(object sender, CancelEventArgs e) { OnNameChanging(e); } private void Algorithm_NameChanged(object sender, EventArgs e) { OnNameChanged(); } private void Algorithm_DescriptionChanged(object sender, EventArgs e) { OnDescriptionChanged(); } private void Algorithm_ExecutionStateChanged(object sender, EventArgs e) { OnExecutionStateChanged(); } private void Algorithm_ExecutionTimeChanged(object sender, EventArgs e) { OnExecutionTimeChanged(); } private void Algorithm_ProblemChanged(object sender, EventArgs e) { OnProblemChanged(); } private void Algorithm_Runs_ItemsAdded(object sender, CollectionItemsChangedEventArgs e) { OKBProblem problem = Problem as OKBProblem; foreach (IRun run in e.Items) { if (problem != null) { OKBRun okbRun = new OKBRun(AlgorithmId, problem.ProblemId, run, UserId); runs.Add(okbRun); if (StoreRunsAutomatically) { okbRun.Store(); } } else { runs.Add(run); } } } private void Algorithm_StoreAlgorithmInEachRunChanged(object sender, EventArgs e) { OnStoreAlgorithmInEachRunChanged(); } private void Algorithm_Prepared(object sender, EventArgs e) { OnPrepared(); } private void Algorithm_Started(object sender, EventArgs e) { OnStarted(); } private void Algorithm_Paused(object sender, EventArgs e) { OnPaused(); } private void Algorithm_Stopped(object sender, EventArgs e) { OnStopped(); } private void Algorithm_ExceptionOccurred(object sender, EventArgs e) { OnExceptionOccurred(e.Value); } private void RegisterRunsEvents() { runs.ItemsRemoved += new CollectionItemsChangedEventHandler(runs_ItemsRemoved); runs.CollectionReset += new CollectionItemsChangedEventHandler(Runs_CollectionReset); } private void runs_ItemsRemoved(object sender, CollectionItemsChangedEventArgs e) { foreach (IRun run in e.Items) { OKBRun okbRun = run as OKBRun; if (okbRun != null) Algorithm.Runs.Remove(okbRun.WrappedRun); else Algorithm.Runs.Remove(run); } } private void Runs_CollectionReset(object sender, CollectionItemsChangedEventArgs e) { foreach (IRun run in e.OldItems) { OKBRun okbRun = run as OKBRun; if (okbRun != null) Algorithm.Runs.Remove(okbRun.WrappedRun); else Algorithm.Runs.Remove(run); } } #endregion } }