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