// Copyright (C) Stichting Deltares 2017. 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 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.Linq;
using Core.Common.Base.Data;
using Ringtoets.Common.Data.Calculation;
using Ringtoets.Common.Data.DikeProfiles;
using Ringtoets.Common.Data.Hydraulics;
using Ringtoets.Common.IO.Configurations;
using Ringtoets.Common.IO.Configurations.Helpers;
using Ringtoets.Common.IO.Configurations.Import;
using Ringtoets.GrassCoverErosionInwards.Data;
using Ringtoets.GrassCoverErosionInwards.IO.Properties;
using Ringtoets.GrassCoverErosionInwards.Utils;
namespace Ringtoets.GrassCoverErosionInwards.IO.Configurations
{
public class GrassCoverErosionInwardsCalculationConfigurationImporter
: CalculationConfigurationImporter
{
private readonly IEnumerable availableHydraulicBoundaryLocations;
private readonly IEnumerable availableDikeProfiles;
private readonly GrassCoverErosionInwardsFailureMechanism failureMechanism;
///
/// Creates a new instance of .
///
/// The path to the XML file to import from.
/// The calculation group to update.
/// The hydraulic boundary locations
/// used to check if the imported objects contain the right location.
/// The dike profiles used to check if
/// the imported objects contain the right profile.
/// The failure mechanism used to propagate changes.
/// Thrown when any parameter is
/// null.
public GrassCoverErosionInwardsCalculationConfigurationImporter(
string xmlFilePath,
CalculationGroup importTarget,
IEnumerable hydraulicBoundaryLocations,
IEnumerable dikeProfiles,
GrassCoverErosionInwardsFailureMechanism failureMechanism)
: base(xmlFilePath, importTarget)
{
if (hydraulicBoundaryLocations == null)
{
throw new ArgumentNullException(nameof(hydraulicBoundaryLocations));
}
if (dikeProfiles == null)
{
throw new ArgumentNullException(nameof(dikeProfiles));
}
if (failureMechanism == null)
{
throw new ArgumentNullException(nameof(failureMechanism));
}
availableHydraulicBoundaryLocations = hydraulicBoundaryLocations;
availableDikeProfiles = dikeProfiles;
this.failureMechanism = failureMechanism;
}
protected override void DoPostImportUpdates()
{
GrassCoverErosionInwardsHelper.UpdateCalculationToSectionResultAssignments(
failureMechanism.SectionResults,
failureMechanism.Calculations.Cast());
base.DoPostImportUpdates();
}
protected override GrassCoverErosionInwardsCalculationConfigurationReader CreateCalculationConfigurationReader(string xmlFilePath)
{
return new GrassCoverErosionInwardsCalculationConfigurationReader(xmlFilePath);
}
protected override ICalculation ParseReadCalculation(GrassCoverErosionInwardsCalculationConfiguration calculationConfiguration)
{
var calculation = new GrassCoverErosionInwardsCalculation
{
Name = calculationConfiguration.Name
};
if (TrySetCriticalFlowRate(calculationConfiguration, calculation)
&& TrySetHydraulicBoundaryLocation(calculationConfiguration.HydraulicBoundaryLocationName, calculation)
&& TrySetDikeProfile(calculationConfiguration.DikeProfileId, calculation)
&& TrySetOrientation(calculationConfiguration, calculation)
&& TrySetDikeHeight(calculationConfiguration, calculation)
&& ValidateWaveReduction(calculationConfiguration, calculation))
{
SetWaveReductionParameters(calculationConfiguration.WaveReduction, calculation.InputParameters);
SetDikeHeightCalculationType(calculationConfiguration, calculation);
SetOvertoppingRateCalculationType(calculationConfiguration, calculation);
SetShouldIllustrationPointsBeCalculated(calculationConfiguration, calculation);
return calculation;
}
return null;
}
private bool TrySetHydraulicBoundaryLocation(string locationName, GrassCoverErosionInwardsCalculation calculation)
{
HydraulicBoundaryLocation location;
if (TryReadHydraulicBoundaryLocation(locationName, calculation.Name, availableHydraulicBoundaryLocations, out location))
{
calculation.InputParameters.HydraulicBoundaryLocation = location;
return true;
}
return false;
}
private bool TrySetDikeProfile(string dikeProfileId, GrassCoverErosionInwardsCalculation calculation)
{
if (dikeProfileId != null)
{
DikeProfile dikeProfile = availableDikeProfiles.FirstOrDefault(fp => fp.Id == dikeProfileId);
if (dikeProfile == null)
{
Log.LogCalculationConversionError(string.Format(
Resources.GrassCoverErosionInwardsCalculationConfigurationImporter_ReadDikeProfile_DikeProfile_0_does_not_exist,
dikeProfileId),
calculation.Name);
return false;
}
calculation.InputParameters.DikeProfile = dikeProfile;
}
return true;
}
///
/// Assigns the orientation.
///
/// The calculation read from the imported file.
/// The calculation to configure.
/// false when the orientation is invalid or when there is an orientation but
/// no dike profile defined, true otherwise.
private bool TrySetOrientation(GrassCoverErosionInwardsCalculationConfiguration calculationConfiguration,
GrassCoverErosionInwardsCalculation calculation)
{
if (calculationConfiguration.Orientation.HasValue)
{
if (calculation.InputParameters.DikeProfile == null)
{
Log.LogCalculationConversionError(Resources.GrassCoverErosionInwardsCalculationConfigurationImporter_ValidateWaveReduction_No_DikeProfile_provided_for_Orientation,
calculation.Name);
return false;
}
double orientation = calculationConfiguration.Orientation.Value;
try
{
calculation.InputParameters.Orientation = (RoundedDouble) orientation;
}
catch (ArgumentOutOfRangeException e)
{
Log.LogOutOfRangeException(string.Format(Resources.GrassCoverErosionInwardsCalculationConfigurationImporter_ReadOrientation_Orientation_0_invalid, orientation),
calculation.Name,
e);
return false;
}
}
return true;
}
///
/// Assigns the dike height.
///
/// The calculation read from the imported file.
/// The calculation to configure.
/// false when there is a dike height but no dike profile defined, true otherwise.
private bool TrySetDikeHeight(GrassCoverErosionInwardsCalculationConfiguration calculationConfiguration,
GrassCoverErosionInwardsCalculation calculation)
{
if (calculationConfiguration.DikeHeight.HasValue)
{
if (calculation.InputParameters.DikeProfile == null)
{
Log.LogCalculationConversionError(Resources.GrassCoverErosionInwardsCalculationConfigurationImporter_ValidateWaveReduction_No_DikeProfile_provided_for_DikeHeight,
calculation.Name);
return false;
}
calculation.InputParameters.DikeHeight = (RoundedDouble) calculationConfiguration.DikeHeight.Value;
}
return true;
}
///
/// Assigns the dike height calculation type.
///
/// The calculation read from the imported file.
/// The calculation to configure.
private static void SetDikeHeightCalculationType(GrassCoverErosionInwardsCalculationConfiguration calculationConfiguration,
GrassCoverErosionInwardsCalculation calculation)
{
if (calculationConfiguration.DikeHeightCalculationType.HasValue)
{
calculation.InputParameters.DikeHeightCalculationType = (DikeHeightCalculationType) calculationConfiguration.DikeHeightCalculationType.Value;
}
}
///
/// Assigns the overtopping rate calculation type.
///
/// The calculation read from the imported file.
/// The calculation to configure.
private static void SetOvertoppingRateCalculationType(GrassCoverErosionInwardsCalculationConfiguration calculationConfiguration,
GrassCoverErosionInwardsCalculation calculation)
{
if (calculationConfiguration.OvertoppingRateCalculationType.HasValue)
{
calculation.InputParameters.OvertoppingRateCalculationType = (OvertoppingRateCalculationType) calculationConfiguration.OvertoppingRateCalculationType.Value;
}
}
///
/// Assigns the properties defining whether the illustration points need to be read for various calculations.
///
/// The calculation read from the imported file.
/// The calculation to configure.
private static void SetShouldIllustrationPointsBeCalculated(GrassCoverErosionInwardsCalculationConfiguration calculationConfiguration,
GrassCoverErosionInwardsCalculation calculation)
{
if (calculationConfiguration.ShouldOvertoppingOutputIllustrationPointsBeCalculated.HasValue)
{
calculation.InputParameters.ShouldOvertoppingOutputIllustrationPointsBeCalculated = calculationConfiguration.ShouldOvertoppingOutputIllustrationPointsBeCalculated.Value;
}
if (calculationConfiguration.ShouldDikeHeightIllustrationPointsBeCalculated.HasValue)
{
calculation.InputParameters.ShouldDikeHeightIllustrationPointsBeCalculated = calculationConfiguration.ShouldDikeHeightIllustrationPointsBeCalculated.Value;
}
if (calculationConfiguration.ShouldOvertoppingRateIllustrationPointsBeCalculated.HasValue)
{
calculation.InputParameters.ShouldOvertoppingRateIllustrationPointsBeCalculated = calculationConfiguration.ShouldOvertoppingRateIllustrationPointsBeCalculated.Value;
}
}
///
/// Assigns the critical flow rate.
///
/// The calculation read from the imported file.
/// The calculation to configure.
/// true if reading all required critical flow rate parameters was successful,
/// false otherwise.
private bool TrySetCriticalFlowRate(GrassCoverErosionInwardsCalculationConfiguration calculationConfiguration,
GrassCoverErosionInwardsCalculation calculation)
{
return ConfigurationImportHelper.TrySetStandardDeviationStochast(
GrassCoverErosionInwardsCalculationConfigurationSchemaIdentifiers.CriticalFlowRateStochastName,
calculation.Name,
calculation.InputParameters,
calculationConfiguration.CriticalFlowRate,
i => i.CriticalFlowRate,
(i, s) => i.CriticalFlowRate = s,
Log);
}
///
/// Validation to check if the defined wave reduction parameters are valid.
///
/// The calculation read from the imported file.
/// The calculation to configure.
/// false when there is an invalid wave reduction parameter defined, true otherwise.
private bool ValidateWaveReduction(GrassCoverErosionInwardsCalculationConfiguration calculationConfiguration,
GrassCoverErosionInwardsCalculation calculation)
{
WaveReductionConfiguration waveReductionConfiguration = calculationConfiguration.WaveReduction;
if (calculation.InputParameters.DikeProfile == null)
{
if (waveReductionConfiguration != null &&
(waveReductionConfiguration.UseBreakWater.HasValue
|| waveReductionConfiguration.UseForeshoreProfile.HasValue
|| waveReductionConfiguration.BreakWaterHeight != null
|| waveReductionConfiguration.BreakWaterType != null))
{
Log.LogCalculationConversionError(Resources.GrassCoverErosionInwardsCalculationConfigurationImporter_ValidateWaveReduction_No_DikeProfile_provided_for_BreakWater_parameters,
calculation.Name);
return false;
}
}
else if (!calculation.InputParameters.ForeshoreGeometry.Any())
{
if (waveReductionConfiguration?.UseForeshoreProfile != null && waveReductionConfiguration.UseForeshoreProfile.Value)
{
Log.LogCalculationConversionError(string.Format(
Resources.GrassCoverErosionInwardsCalculationConfigurationImporter_ValidateWaveReduction_DikeProfile_0_has_no_geometry_and_cannot_be_used,
calculationConfiguration.DikeProfileId),
calculation.Name);
return false;
}
}
return true;
}
}
}