// 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; }
}
}
}