// 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 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 General Public License for more details. // // You should have received a copy of the GNU 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.IO; using System.Linq; using Components.Persistence.Stability; using Core.Common.Base.Data; using Core.Common.Base.IO; using Core.Common.IO.Exceptions; using Core.Common.Util; using log4net; using Riskeer.Common.Data.Calculation; using Riskeer.Common.IO.Helpers; using Riskeer.Common.Util.Helpers; using Riskeer.MacroStabilityInwards.Data; using Riskeer.MacroStabilityInwards.IO.Properties; using CoreCommonUtilResources = Core.Common.Util.Properties.Resources; using CoreGuiResources = Core.Gui.Properties.Resources; namespace Riskeer.MacroStabilityInwards.IO.Exporters { /// /// Exports macro stability inwards calculations from a calculation group and stores them as separate stix files. /// public class MacroStabilityInwardsCalculationGroupExporter : IFileExporter { private static readonly ILog log = LogManager.GetLogger(typeof(MacroStabilityInwardsCalculationGroupExporter)); private readonly CalculationGroup calculationGroup; private readonly GeneralMacroStabilityInwardsInput generalInput; private readonly IPersistenceFactory persistenceFactory; private readonly string filePath; private readonly string tempFolderPath; private readonly string fileExtension; private readonly Func getNormativeAssessmentLevelFunc; private bool itemExported; /// /// Creates a new instance of . /// /// The calculation group to export. /// General calculation parameters that are the same across all calculations. /// The persistence factory to use. /// The file path to export to. /// The extension of the files. /// /// for obtaining the normative assessment level. /// Thrown when , , /// , or is null. /// Thrown when is invalid. /// A valid path: /// is not empty or null, /// does not consist out of only whitespace characters, /// does not contain an invalid character, /// is not too long. /// public MacroStabilityInwardsCalculationGroupExporter(CalculationGroup calculationGroup, GeneralMacroStabilityInwardsInput generalInput, IPersistenceFactory persistenceFactory, string filePath, string fileExtension, Func getNormativeAssessmentLevelFunc) { if (calculationGroup == null) { throw new ArgumentNullException(nameof(calculationGroup)); } if (generalInput == null) { throw new ArgumentNullException(nameof(generalInput)); } if (persistenceFactory == null) { throw new ArgumentNullException(nameof(persistenceFactory)); } if (getNormativeAssessmentLevelFunc == null) { throw new ArgumentNullException(nameof(getNormativeAssessmentLevelFunc)); } IOUtils.ValidateFilePath(filePath); this.calculationGroup = calculationGroup; this.generalInput = generalInput; this.persistenceFactory = persistenceFactory; this.filePath = filePath; string folderPath = Path.GetDirectoryName(filePath); tempFolderPath = Path.Combine(folderPath, "~temp"); this.fileExtension = fileExtension; this.getNormativeAssessmentLevelFunc = getNormativeAssessmentLevelFunc; } public bool Export() { try { if (!ExportCalculationItemsRecursively(calculationGroup, tempFolderPath)) { return false; } if (itemExported) { ZipFileExportHelper.CreateZipFileFromExportedFiles(tempFolderPath, filePath); } return true; } catch (CriticalFileWriteException e) { log.ErrorFormat(Resources.MacroStabilityInwardsCalculationGroupExporter_Export_Exception_0_no_stability_projects_exported, e.Message); return false; } finally { if (Directory.Exists(tempFolderPath)) { var di = new DirectoryInfo(tempFolderPath); foreach (FileInfo file in di.GetFiles()) { file.Delete(); } foreach (DirectoryInfo dir in di.GetDirectories()) { dir.Delete(true); } } } } private bool ExportCalculationItemsRecursively(CalculationGroup groupToExport, string currentFolderPath) { CreateDirectoryWhenNeeded(groupToExport, currentFolderPath); var continueExport = true; var exportedGroups = new List(); var exportedCalculations = new List(); foreach (ICalculationBase calculationItem in groupToExport.Children) { switch (calculationItem) { case CalculationGroup nestedGroup when HasChildren(nestedGroup): continueExport = ExportCalculationGroup(nestedGroup, currentFolderPath, exportedGroups); break; case MacroStabilityInwardsCalculation calculation when !calculation.HasOutput: log.WarnFormat(Resources.MacroStabilityInwardsCalculationGroupExporter_Export_Calculation_0_has_no_output_and_is_skipped, calculation.Name); break; case MacroStabilityInwardsCalculation calculation: continueExport = ExportCalculation(calculation, currentFolderPath, exportedCalculations); break; } if (!continueExport) { return false; } } return true; } private static bool HasChildren(CalculationGroup nestedGroup) { return nestedGroup.GetCalculations() .Cast() .Any(); } private static void CreateDirectoryWhenNeeded(CalculationGroup nestedGroup, string currentFolderPath) { if (nestedGroup.HasOutput() && !Directory.Exists(currentFolderPath)) { Directory.CreateDirectory(currentFolderPath); } } private bool ExportCalculationGroup(CalculationGroup nestedGroup, string currentFolderPath, List exportedGroups) { string uniqueGroupName = NamingHelper.GetUniqueName(exportedGroups, nestedGroup.Name, group => group); bool exportSucceeded = ExportCalculationItemsRecursively(nestedGroup, Path.Combine(currentFolderPath, uniqueGroupName)); if (!exportSucceeded) { return false; } exportedGroups.Add(uniqueGroupName); return true; } private bool ExportCalculation(MacroStabilityInwardsCalculation calculation, string currentFolderPath, List exportedCalculations) { string uniqueName = NamingHelper.GetUniqueName(exportedCalculations, ((ICalculationBase) calculation).Name, c => c); string calculationFilePath = GetCalculationFilePath(currentFolderPath, uniqueName); var exporter = new MacroStabilityInwardsCalculationExporter(calculation, generalInput, persistenceFactory, calculationFilePath, () => getNormativeAssessmentLevelFunc(calculation)); bool exportSucceeded = exporter.Export(); if (!exportSucceeded) { log.ErrorFormat("{0} {1}", string.Format(Resources.MacroStabilityInwardsCalculationGroupExporter_ExportCalculation_Unexpected_error_during_export_CalculationName_0, calculation.Name), Resources.MacroStabilityInwardsCalculationExporter_Export_no_stability_project_exported); return false; } exportedCalculations.Add(uniqueName); itemExported = true; return true; } private string GetCalculationFilePath(string currentFolderPath, string fileName) { var fileNameWithExtension = $"{fileName}.{fileExtension}"; return Path.Combine(currentFolderPath, fileNameWithExtension); } } }