// Copyright (C) Stichting Deltares 2021. All rights reserved. // // This file is part of Riskeer. // // Riskeer 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.Globalization; using System.IO; using Core.Common.Base.Data; using Core.Common.Base.Service; using Core.Common.Base.Storage; using Core.Gui.Properties; using log4net; using CoreCommonBaseResources = Core.Common.Base.Properties.Resources; namespace Core.Gui { /// /// Activity that handles opening an . /// public class OpenProjectActivity : Activity { private readonly string filePath; private readonly IProjectOwner projectOwner; private readonly IStoreProject storage; private readonly ILog log = LogManager.GetLogger(typeof(OpenProjectActivity)); private readonly string migratedProjectFilePath; private readonly IMigrateProject migrator; private readonly int totalNumberOfSteps = 2; private IProject openedProject; private bool cancel; /// /// Creates a new instance of . /// /// All mandatory properties for being /// able to open a project. /// Optional: Properties for migrating /// the project to the current version. /// Thrown when /// is null. /// Thrown when any input argument has invalid values. public OpenProjectActivity(OpenProjectConstructionProperties requiredOpenProjectProperties, ProjectMigrationConstructionProperties optionalProjectMigrationProperties = null) { if (requiredOpenProjectProperties == null) { throw new ArgumentNullException(nameof(requiredOpenProjectProperties)); } ValidateOpenProjectProperties(requiredOpenProjectProperties); if (optionalProjectMigrationProperties != null) { ValidateProjectMigrationProperties(optionalProjectMigrationProperties); migratedProjectFilePath = optionalProjectMigrationProperties.MigrationFilePath; migrator = optionalProjectMigrationProperties.Migrator; totalNumberOfSteps = 3; } filePath = requiredOpenProjectProperties.FilePath; projectOwner = requiredOpenProjectProperties.ProjectOwner; storage = requiredOpenProjectProperties.ProjectStorage; Description = Resources.OpenProjectActivity_Open_project; } protected override void OnRun() { cancel = false; var currentStepNumber = 1; ClearOpenedProject(); if (migrator != null && !MigrateProject(currentStepNumber++)) { return; } LoadProject(currentStepNumber); } protected override void OnCancel() { cancel = true; } protected override void OnFinish() { switch (State) { case ActivityState.Executed: InitializeSuccessfulOpenedProject(); break; case ActivityState.Canceled: ClearOpenedProject(); break; } } private string FilePathTakingMigrationIntoAccount { get { return migratedProjectFilePath ?? filePath; } } /// /// Migrates the project. /// /// The current step number. /// true if migration was successful, false otherwise. private bool MigrateProject(int currentStepNumber) { UpdateProgressText(Resources.OpenProjectActivity_ProgressTextStepName_MigrateProject, currentStepNumber, totalNumberOfSteps); try { bool migrationSuccessful = migrator.Migrate(filePath, migratedProjectFilePath); if (cancel) { return false; } if (!migrationSuccessful) { State = ActivityState.Failed; return false; } } catch (ArgumentException e) { if (cancel) { return false; } log.Error(e.Message, e); State = ActivityState.Failed; return false; } return true; } private void LoadProject(int currentStepNumber) { UpdateProgressText(Resources.OpenProjectActivity_ProgressTextStepName_ReadProject, currentStepNumber, totalNumberOfSteps); try { openedProject = storage.LoadProject(FilePathTakingMigrationIntoAccount); } catch (StorageException e) { if (cancel) { return; } log.Error(e.Message, e.InnerException); } if (cancel) { return; } if (openedProject == null) { State = ActivityState.Failed; } } private void ClearOpenedProject() { openedProject = null; } private void InitializeSuccessfulOpenedProject() { UpdateProgressText(Resources.OpenProjectActivity_ProgressTextStepName_InitializeProject, totalNumberOfSteps, totalNumberOfSteps); projectOwner.SetProject(openedProject, FilePathTakingMigrationIntoAccount); openedProject.Name = Path.GetFileNameWithoutExtension(FilePathTakingMigrationIntoAccount); openedProject.NotifyObservers(); } /// /// Updates the progress text. /// /// A short description of the current step. /// The number of the current step. /// The total numbers of steps. private void UpdateProgressText(string currentStepName, int currentStep, int totalSteps) { ProgressText = string.Format(CultureInfo.CurrentCulture, CoreCommonBaseResources.Activity_UpdateProgressText_CurrentStepNumber_0_of_TotalStepsNumber_1_StepDescription_2_, currentStep, totalSteps, currentStepName); } /// /// Validates the construction arguments required for opening a project file. /// /// The construction arguments to be validated. /// Thrown when any construction property of /// is invalid. private static void ValidateOpenProjectProperties(OpenProjectConstructionProperties requiredOpenProjectProperties) { if (requiredOpenProjectProperties.FilePath == null) { throw new ArgumentException(@"Filepath should be set.", nameof(requiredOpenProjectProperties)); } if (requiredOpenProjectProperties.ProjectOwner == null) { throw new ArgumentException(@"Project owner should be set.", nameof(requiredOpenProjectProperties)); } if (requiredOpenProjectProperties.ProjectFactory == null) { throw new ArgumentException(@"Project factory should be set.", nameof(requiredOpenProjectProperties)); } if (requiredOpenProjectProperties.ProjectStorage == null) { throw new ArgumentException(@"Project storage should be set.", nameof(requiredOpenProjectProperties)); } } /// /// Validates the construction arguments required for migrating a project file. /// /// The construction arguments to be validated. /// Thrown when any construction property of /// is invalid. private static void ValidateProjectMigrationProperties(ProjectMigrationConstructionProperties optionalProjectMigrationProperties) { if (optionalProjectMigrationProperties.Migrator == null) { throw new ArgumentException(@"Project migrator should be set.", nameof(optionalProjectMigrationProperties)); } if (optionalProjectMigrationProperties.MigrationFilePath == null) { throw new ArgumentException(@"Migration target file path should be set.", nameof(optionalProjectMigrationProperties)); } } /// /// All construction properties related to opening a project file. /// public class OpenProjectConstructionProperties { /// /// Filepath to the project file that should be opened. /// public string FilePath { get; set; } /// /// The to be updated with the newly opened project. /// public IProjectOwner ProjectOwner { get; set; } /// /// The to create a default project in case of /// an error scenario. /// public IProjectFactory ProjectFactory { get; set; } /// /// The object used to open the file at . /// public IStoreProject ProjectStorage { get; set; } } /// /// All construction properties related to migrating a project file. /// public class ProjectMigrationConstructionProperties { /// /// The responsible for performing the migration. /// public IMigrateProject Migrator { get; set; } /// /// The file path to where the migrate project should be written to. This path /// will override with /// regards of opening the project. /// public string MigrationFilePath { get; set; } } } }