// Copyright (C) Stichting Deltares 2016. 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.FileImporters;
using Ringtoets.Revetment.Data;
using Ringtoets.Revetment.IO.Properties;
using Ringtoets.Revetment.IO.Readers;
using RingtoetsCommonIOResources = Ringtoets.Common.IO.Properties.Resources;
namespace Ringtoets.Revetment.IO.Importers
{
///
/// Imports a wave conditions calculation configuration from an XML file and stores it on a
/// .
///
/// The type of the calculation to import.
public class WaveConditionsCalculationConfigurationImporter
: CalculationConfigurationImporter
where T : IWaveConditionsCalculation, new()
{
private readonly IEnumerable availableHydraulicBoundaryLocations;
private readonly IEnumerable foreshoreProfiles;
///
/// 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 foreshore profiles used to check if
/// the imported objects contain the right profile.
/// Thrown when any parameter is
/// null.
public WaveConditionsCalculationConfigurationImporter(string xmlFilePath,
CalculationGroup importTarget,
IEnumerable availableHydraulicBoundaryLocations,
IEnumerable foreshoreProfiles)
: base(xmlFilePath, importTarget)
{
if (availableHydraulicBoundaryLocations == null)
{
throw new ArgumentNullException(nameof(availableHydraulicBoundaryLocations));
}
if (foreshoreProfiles == null)
{
throw new ArgumentNullException(nameof(foreshoreProfiles));
}
this.availableHydraulicBoundaryLocations = availableHydraulicBoundaryLocations;
this.foreshoreProfiles = foreshoreProfiles;
}
protected override WaveConditionsCalculationConfigurationReader CreateCalculationConfigurationReader(string xmlFilePath)
{
return new WaveConditionsCalculationConfigurationReader(xmlFilePath);
}
protected override ICalculation ParseReadCalculation(ReadWaveConditionsCalculation readCalculation)
{
var waveConditionsCalculation = new T
{
Name = readCalculation.Name
};
if (!ReadHydraulicBoundaryLocation(readCalculation, waveConditionsCalculation))
{
return null;
}
if (!ReadBoundaries(readCalculation, waveConditionsCalculation))
{
return null;
}
ReadStepSize(readCalculation, waveConditionsCalculation);
if (!ReadForeshoreProfile(readCalculation, waveConditionsCalculation))
{
return null;
}
if (!ReadOrientation(readCalculation, waveConditionsCalculation))
{
return null;
}
if (!ReadWaveReduction(readCalculation, waveConditionsCalculation))
{
return null;
}
return waveConditionsCalculation;
}
///
/// Reads the hydraulic boundary location.
///
/// The calculation read from the imported file.
/// The calculation to configure.
/// false when the has a
/// set which is not available in
/// , true otherwise.
private bool ReadHydraulicBoundaryLocation(ReadWaveConditionsCalculation readCalculation, IWaveConditionsCalculation calculation)
{
if (readCalculation.HydraulicBoundaryLocation != null)
{
HydraulicBoundaryLocation location = availableHydraulicBoundaryLocations
.FirstOrDefault(l => l.Name == readCalculation.HydraulicBoundaryLocation);
if (location == null)
{
LogReadCalculationConversionError(string.Format(
RingtoetsCommonIOResources.CalculationConfigurationImporter_ReadHydraulicBoundaryLocation_Hydraulic_boundary_location_0_does_not_exist,
readCalculation.HydraulicBoundaryLocation),
calculation.Name);
return false;
}
calculation.InputParameters.HydraulicBoundaryLocation = location;
}
return true;
}
///
/// Reads the boundaries of the calculation.
///
/// The calculation read from the imported file.
/// The calculation to configure.
/// false when one of the boundaries is invalid, true otherwise.
private bool ReadBoundaries(ReadWaveConditionsCalculation readCalculation, IWaveConditionsCalculation calculation)
{
if (readCalculation.UpperBoundaryRevetment.HasValue)
{
double upperBoundaryRevetment = readCalculation.UpperBoundaryRevetment.Value;
try
{
calculation.InputParameters.UpperBoundaryRevetment = (RoundedDouble) upperBoundaryRevetment;
}
catch (ArgumentOutOfRangeException e)
{
LogOutOfRangeException(string.Format(
Resources.WaveConditionsCalculationConfigurationImporter_ReadBoundaries_Upper_boundary_revetment_0_invalid,
upperBoundaryRevetment),
calculation.Name, e);
return false;
}
}
if (readCalculation.LowerBoundaryRevetment.HasValue)
{
double lowerBoundaryRevetment = readCalculation.LowerBoundaryRevetment.Value;
try
{
calculation.InputParameters.LowerBoundaryRevetment = (RoundedDouble) lowerBoundaryRevetment;
}
catch (ArgumentOutOfRangeException e)
{
LogOutOfRangeException(string.Format(
Resources.WaveConditionsCalculationConfigurationImporter_ReadBoundaries_Lower_boundary_revetment_0_invalid,
lowerBoundaryRevetment),
calculation.Name, e);
return false;
}
}
if (readCalculation.UpperBoundaryWaterLevels.HasValue)
{
double upperBoundaryWaterLevels = readCalculation.UpperBoundaryWaterLevels.Value;
try
{
calculation.InputParameters.UpperBoundaryWaterLevels = (RoundedDouble)upperBoundaryWaterLevels;
}
catch (ArgumentOutOfRangeException e)
{
LogOutOfRangeException(string.Format(
Resources.WaveConditionsCalculationConfigurationImporter_ReadBoundaries_Upper_boundary_waterlevels_0_invalid,
upperBoundaryWaterLevels),
calculation.Name, e);
return false;
}
}
if (readCalculation.LowerBoundaryWaterLevels.HasValue)
{
double lowerBoundaryWaterLevels = readCalculation.LowerBoundaryWaterLevels.Value;
try
{
calculation.InputParameters.LowerBoundaryWaterLevels = (RoundedDouble)lowerBoundaryWaterLevels;
}
catch (ArgumentOutOfRangeException e)
{
LogOutOfRangeException(string.Format(
Resources.WaveConditionsCalculationConfigurationImporter_ReadBoundaries_Lower_boundary_waterlevels_0_invalid,
lowerBoundaryWaterLevels),
calculation.Name, e);
return false;
}
}
return true;
}
private void ReadStepSize(ReadWaveConditionsCalculation readCalculation, IWaveConditionsCalculation calculation)
{
if (readCalculation.StepSize.HasValue)
{
calculation.InputParameters.StepSize = readCalculation.StepSize.Value;
}
}
///
/// Reads the foreshore profile.
///
/// The calculation read from the imported file.
/// The calculation to configure.
/// false when the has a
/// set which is not available in ,
/// true otherwise.
private bool ReadForeshoreProfile(ReadWaveConditionsCalculation readCalculation, IWaveConditionsCalculation calculation)
{
if (readCalculation.ForeshoreProfile != null)
{
ForeshoreProfile foreshoreProfile = foreshoreProfiles.FirstOrDefault(fp => fp.Name == readCalculation.ForeshoreProfile);
if (foreshoreProfile == null)
{
LogReadCalculationConversionError(string.Format(
Resources.WaveConditionsCalculationConfigurationImporter_ReadForeshoreProfile_Foreshore_profile_0_does_not_exist,
readCalculation.ForeshoreProfile),
calculation.Name);
return false;
}
calculation.InputParameters.ForeshoreProfile = foreshoreProfile;
}
return true;
}
///
/// Reads the orientation.
///
/// The calculation read from the imported file.
/// The calculation to configure.
/// falce when the orientation is invalid, true otherwise.
private bool ReadOrientation(ReadWaveConditionsCalculation readCalculation, IWaveConditionsCalculation calculation)
{
if (readCalculation.Orientation.HasValue)
{
double orientation = readCalculation.Orientation.Value;
try
{
calculation.InputParameters.Orientation = (RoundedDouble) orientation;
}
catch (ArgumentOutOfRangeException e)
{
LogOutOfRangeException(string.Format(
Resources.WaveConditionsCalculationConfigurationImporter_ReadOrientation_Orientation_0_invalid,
orientation),
calculation.Name, e);
return false;
}
}
return true;
}
///
/// Reads the wave reduction parameters.
///
/// 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 ReadWaveReduction(ReadWaveConditionsCalculation readCalculation, IWaveConditionsCalculation calculation)
{
if (!ValidateWaveReduction(readCalculation, calculation))
{
return false;
}
if (readCalculation.UseForeshore.HasValue)
{
calculation.InputParameters.UseForeshore = readCalculation.UseForeshore.Value;
}
if (readCalculation.UseBreakWater.HasValue)
{
calculation.InputParameters.UseBreakWater = readCalculation.UseBreakWater.Value;
}
if (readCalculation.BreakWaterType.HasValue)
{
calculation.InputParameters.BreakWater.Type = readCalculation.BreakWaterType.Value;
}
if (readCalculation.BreakWaterHeight.HasValue)
{
calculation.InputParameters.BreakWater.Height = (RoundedDouble) readCalculation.BreakWaterHeight.Value;
}
return true;
}
///
/// 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(ReadWaveConditionsCalculation readCalculation, IWaveConditionsCalculation calculation)
{
if (calculation.InputParameters.ForeshoreProfile == null)
{
if (readCalculation.UseBreakWater.HasValue
|| readCalculation.UseForeshore.HasValue
|| readCalculation.BreakWaterHeight != null
|| readCalculation.BreakWaterType != null)
{
LogReadCalculationConversionError(
Resources.WaveConditionsCalculationConfigurationImporter_ValidateWaveReduction_No_foreshore_profile_provided,
calculation.Name);
return false;
}
}
else if (!calculation.InputParameters.ForeshoreGeometry.Any())
{
if (readCalculation.UseForeshore.HasValue)
{
LogReadCalculationConversionError(string.Format(
Resources.WaveConditionsCalculationConfigurationImporter_ValidateWaveReduction_Foreshore_profile_0_has_no_geometry_and_cannot_be_used,
readCalculation.ForeshoreProfile),
calculation.Name);
return false;
}
}
return true;
}
}
}