// Copyright (C) Stichting Deltares 2016. All rights reserved. // // This file is part of Ringtoets. // // Ringtoets is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program 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 Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with this program. If not, see . // // All names, logos, and references to "Deltares" are registered trademarks of // Stichting Deltares and remain full property of Stichting Deltares at all times. // All rights reserved. using System; using System.Collections.Generic; using System.Collections.ObjectModel; using Core.Common.Base.Properties; using log4net; namespace Core.Common.Base.Service { /// /// Abstract class that can be derived for performing activities (like calculations, data imports, data exports, etc.). /// The regular workflow for completely performing an is: -> . /// can be called for cancelling a running . /// /// /// By convention, only should contain UI thread related logic. /// public abstract class Activity { /// /// Event for notifying progress changes. /// public event EventHandler ProgressChanged; private readonly ILog log = LogManager.GetLogger(typeof(Activity)); private string progressText; /// /// Constructs a new . /// protected Activity() { Name = ""; State = ActivityState.None; LogMessages = new Collection(); } /// /// Gets or sets the name of the . /// public virtual string Name { get; set; } /// /// Gets or sets the of the . /// public ActivityState State { get; protected set; } /// /// Gets or sets the progress text of the . /// listeners are notified when the progress text is set. /// public string ProgressText { get { return progressText; } protected set { progressText = value; OnProgressChanged(); } } /// /// Gets or sets the collection of log messages of the (which are appended while performing the ). /// /// /// Derived classes themselves are responsible for clearing the collection of log messages. /// public ICollection LogMessages { get; private set; } /// /// This method resets to and then runs the . /// The of a successfully run will become . /// When the run fails, the will become . /// public void Run() { State = ActivityState.None; ChangeState(OnRun, ActivityState.Executed); } /// /// This method cancels a running . /// The of a successfully cancelled will become . /// When the cancel action fails, the will become . /// public void Cancel() { ChangeState(OnCancel, ActivityState.Cancelled); } /// /// This method finishes an that successfully ran. /// Successfully ran activities can be identified by a equal to . /// The of a successfully finished will become . /// When the finish action fails, the will become . /// public void Finish() { ChangeState(OnFinish, State == ActivityState.Executed ? ActivityState.Finished : State); // If relevant, preserve the previous state if (State == ActivityState.Finished) { log.InfoFormat(Resources.Activity_Finish_Execution_of_ActivityName_0_has_succeeded, Name); } if (State == ActivityState.Cancelled) { log.WarnFormat(Resources.Activity_Finish_Execution_of_ActivityName_0_has_been_cancelled, Name); } if (State == ActivityState.Failed) { log.ErrorFormat(Resources.Activity_Finish_Execution_of_ActivityName_0_has_failed, Name); } if (State == ActivityState.Skipped) { log.InfoFormat(Resources.Activity_Finish_Execution_of_ActivityName_0_has_been_skipped, Name); } } /// /// This template method provides the actual run logic (it is called within ). /// /// /// The should be set to when one or more errors occur. /// By convention, the implementation of this method should not contain UI thread related logic. /// Implementations of this method are allowed to throw exceptions of any kind. /// protected abstract void OnRun(); /// /// This template method provides the actual cancel logic (it is called within ). /// /// /// By convention, the implementation of this method should not contain UI thread related logic. /// Implementations of this method are allowed to throw exceptions of any kind. /// protected abstract void OnCancel(); /// /// This template method provides the actual finish logic (it is called within ). /// /// /// By convention, only the implementation of this method might contain UI thread related logic. /// Implementations of this method are allowed to throw exceptions of any kind. /// protected abstract void OnFinish(); private void OnProgressChanged() { if (ProgressChanged != null) { ProgressChanged(this, EventArgs.Empty); } } private void ChangeState(Action transitionAction, ActivityState stateAfter) { try { transitionAction(); if (State == ActivityState.Failed || State == ActivityState.Cancelled || State == ActivityState.Skipped) { return; } } catch (Exception e) { State = ActivityState.Failed; log.Error(e.Message); return; } State = stateAfter; } } }