// 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.Collections.ObjectModel; using System.Linq; using Core.Common.Base; using Core.Common.Base.IO; using Core.Common.IO.Readers; using Ringtoets.Common.Data; using Ringtoets.Common.Data.Exceptions; using Ringtoets.Common.IO.Exceptions; using Ringtoets.Common.IO.FileImporters.MessageProviders; using Ringtoets.Common.IO.Properties; using RingtoetsCommonDataResources = Ringtoets.Common.Data.Properties.Resources; namespace Ringtoets.Common.IO.SoilProfile { /// /// Imports .soil files (SqlLite database files) created with the D-Soil Model application. /// /// The type of stochastic soil models to import. public class StochasticSoilModelImporter : FileImporterBase> where T : class, IMechanismStochasticSoilModel { private readonly IImporterMessageProvider messageProvider; private readonly IStochasticSoilModelUpdateModelStrategy updateStrategy; private readonly IStochasticSoilModelTransformer transformer; private readonly IStochasticSoilModelMechanismFilter filter; private IEnumerable updatedInstances; /// /// Creates a new instance of . /// /// The import target. /// The path to the file to import from. /// The message provider to provide messages during importer /// actions. /// The mechanism specific configuration containing all /// necessary stochastic soil model components. /// Thrown when any of the input parameters is null. public StochasticSoilModelImporter( ObservableUniqueItemCollectionWithSourcePath importTarget, string filePath, IImporterMessageProvider messageProvider, StochasticSoilModelImporterConfiguration configuration) : base(filePath, importTarget) { if (messageProvider == null) { throw new ArgumentNullException(nameof(messageProvider)); } if (configuration == null) { throw new ArgumentNullException(nameof(configuration)); } this.messageProvider = messageProvider; updateStrategy = configuration.UpdateStrategy; transformer = configuration.Transformer; filter = configuration.MechanismFilter; updatedInstances = Enumerable.Empty(); } protected override void LogImportCanceledMessage() { string message = messageProvider.GetCancelledLogMessageText(RingtoetsCommonDataResources.StochasticSoilModelCollection_TypeDescriptor); Log.Info(message); } protected override void DoPostImportUpdates() { foreach (IObservable observable in updatedInstances) { observable.NotifyObservers(); } } protected override bool OnImport() { ReadResult importStochasticSoilModelResult = ReadStochasticSoilModels(); if (importStochasticSoilModelResult.CriticalErrorOccurred || Canceled) { return false; } ReadResult transformedStochasticSoilModels; try { transformedStochasticSoilModels = GetTransformedStochasticSoilModels(importStochasticSoilModelResult.Items); } catch (ImportedDataTransformException e) { Log.ErrorFormat(Resources.StochasticSoilModelImporter_CriticalErrorMessage_0_File_Skipped, e.Message); return false; } if (transformedStochasticSoilModels.CriticalErrorOccurred || Canceled) { return false; } if (!transformedStochasticSoilModels.Items.Any()) { Log.WarnFormat(Resources.StochasticSoilModelImporter_No_stochastic_soil_models_found_for_failure_mechanism); return true; } NotifyProgress(messageProvider.GetAddDataToModelProgressText(), 1, 1); try { updatedInstances = updateStrategy.UpdateModelWithImportedData(transformedStochasticSoilModels.Items, FilePath); } catch (UpdateDataException e) { string message = string.Format(messageProvider.GetUpdateDataFailedLogMessageText( RingtoetsCommonDataResources.StochasticSoilModelCollection_TypeDescriptor), e.Message); Log.Error(message, e); return false; } return true; } private void HandleException(Exception e) { string message = string.Format(Resources.StochasticSoilModelImporter_CriticalErrorMessage_0_File_Skipped, e.Message); Log.Error(message, e); } #region Read stochastic soil models private ReadResult ReadStochasticSoilModels() { NotifyProgress(Resources.StochasticSoilModelImporter_Reading_database, 1, 1); try { using (var stochasticSoilModelReader = new StochasticSoilModelReader(FilePath)) { stochasticSoilModelReader.Validate(); return GetStochasticSoilModelReadResult(stochasticSoilModelReader); } } catch (Exception e) when (e is StochasticSoilModelException || e is CriticalFileReadException) { HandleException(e); } return new ReadResult(true); } /// /// Reads all stochastic soil models from the . /// /// The . /// Returns a collection of read stochastic soil models. /// Thrown when the database returned incorrect /// values for required properties. /// Thrown when: /// /// no stochastic soil profiles could be read; /// the read failure mechanism type is not supported. /// /// private ReadResult GetStochasticSoilModelReadResult(StochasticSoilModelReader stochasticSoilModelReader) { int totalNumberOfSteps = stochasticSoilModelReader.StochasticSoilModelCount; var currentStep = 1; var soilModels = new Collection(); while (stochasticSoilModelReader.HasNext) { if (Canceled) { return new ReadResult(false); } NotifyProgress(Resources.StochasticSoilModelImporter_GetStochasticSoilModelReadResult_Reading_stochastic_soil_models_from_database, currentStep++, totalNumberOfSteps); soilModels.Add(stochasticSoilModelReader.ReadStochasticSoilModel()); } return new ReadResult(false) { Items = soilModels }; } #endregion #region Validate stochastic soil models /// /// Transforms the stochastic soil models into mechanism specific stochastic soil models. /// /// The stochastic soil models to transform. /// Returns a collection of mechanism specific stochastic /// soil models, or an empty when any of the /// is not valid to be transformed. /// Thrown when transforming a stochastic /// soil model failed. private ReadResult GetTransformedStochasticSoilModels(IEnumerable stochasticSoilModels) { var transformedStochasticSoilModels = new List(); var stochasticSoilModelNumber = 1; StochasticSoilModel[] importedModels = stochasticSoilModels.Where(ssm => filter.IsValidForFailureMechanism(ssm)) .ToArray(); foreach (StochasticSoilModel stochasticSoilModel in importedModels) { NotifyProgress(Resources.Importer_ProgressText_Validating_imported_data, stochasticSoilModelNumber++, importedModels.Length); if (Canceled) { return new ReadResult(false); } ValidateStochasticSoilModel(stochasticSoilModel); transformedStochasticSoilModels.Add(transformer.Transform(stochasticSoilModel)); } return new ReadResult(false) { Items = transformedStochasticSoilModels }; } private void ValidateStochasticSoilModel(StochasticSoilModel stochasticSoilModel) { if (!IsSumOfAllProbabilitiesEqualToOne(stochasticSoilModel)) { Log.WarnFormat(Resources.StochasticSoilModelImporter_ValidateStochasticSoilModel_Sum_of_probabilities_of_stochastic_soil_model_0_is_not_correct, stochasticSoilModel.Name); } } private static bool IsSumOfAllProbabilitiesEqualToOne(StochasticSoilModel stochasticSoilModel) { double sumOfAllScenarioProbabilities = stochasticSoilModel.StochasticSoilProfiles .Sum(s => s.Probability); return Math.Abs(sumOfAllScenarioProbabilities - 1.0) < 1e-6; } #endregion } }