// 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.IO; using Core.Common.IO.Readers; using log4net; using Ringtoets.Common.Data.Calculation; using Ringtoets.Common.IO.Properties; using Ringtoets.Common.IO.Readers; namespace Ringtoets.Common.IO.FileImporters { /// /// Base class for importing a calculation configuration from an XML file and storing it on a . /// /// The type of the reader to use for reading the XML file. /// The type of the data read from the XML file by the reader. public abstract class CalculationConfigurationImporter : FileImporterBase where TCalculationConfigurationReader : CalculationConfigurationReader where TReadCalculation : class, IReadConfigurationItem { private static readonly ILog log = LogManager.GetLogger(typeof(CalculationConfigurationImporter)); /// /// Creates a new instance of . /// /// The path to the XML file to import from. /// The calculation group to update. /// Thrown when any parameter is null. protected CalculationConfigurationImporter(string xmlFilePath, CalculationGroup importTarget) : base(xmlFilePath, importTarget) {} protected override void LogImportCanceledMessage() { log.Info(Resources.CalculationConfigurationImporter_LogImportCanceledMessage_Import_canceled_no_data_read); } protected override bool OnImport() { NotifyProgress(Resources.CalculationConfigurationImporter_ProgressText_Reading_configuration, 1, 3); ReadResult readResult = ReadConfiguration(); if (readResult.CriticalErrorOccurred || Canceled) { return false; } NotifyProgress(Resources.CalculationConfigurationImporter_ProgressText_Validating_imported_data, 2, 3); var parsedCalculationItems = new List(); foreach (IReadConfigurationItem readItem in readResult.Items) { if (Canceled) { return false; } ICalculationBase parsedItem = ParseReadConfigurationItem(readItem); if (parsedItem != null) { parsedCalculationItems.Add(parsedItem); } } NotifyProgress(Resources.Importer_ProgressText_Adding_imported_data_to_data_model, 3, 3); AddItemsToModel(parsedCalculationItems); return true; } /// /// Creates the reader used for reading the calculation configuration from the provided . /// /// The path to the XML file to import from. /// A reader for reading the calculation configuration. /// Thrown when is invalid. /// Thrown when: /// /// points to a file that does not exist. /// points to a file that does not contain valid XML. /// points to a file that does not pass the schema validation. /// points to a file that does not contain configuration elements. /// /// protected abstract TCalculationConfigurationReader CreateCalculationConfigurationReader(string xmlFilePath); /// /// Parses a calculation from the provided . /// /// The calculation read from XML. /// A parsed calculation instance, or null when something goes wrong while parsing. protected abstract ICalculation ParseReadCalculation(TReadCalculation readCalculation); protected void LogOutOfRangeException(string errorMessage, string calculationName, ArgumentOutOfRangeException e) { LogReadCalculationConversionError($"{errorMessage} {e.Message}", calculationName); } protected void LogReadCalculationConversionError(string message, string calculationName) { log.ErrorFormat(Resources.CalculationConfigurationImporter_ValidateCalculation_Error_message_0_calculation_1_skipped, message, calculationName); } private ReadResult ReadConfiguration() { try { return new ReadResult(false) { Items = CreateCalculationConfigurationReader(FilePath).Read().ToList() }; } catch (Exception exception) when (exception is ArgumentException || exception is CriticalFileReadException) { string errorMessage = string.Format(Resources.CalculationConfigurationImporter_HandleCriticalFileReadError_Error_0_no_configuration_imported, exception.Message); log.Error(errorMessage, exception); return new ReadResult(true); } } /// /// Parses the read configuration item. /// /// The read item to parse. /// A parsed calculation item. /// Thrown when the item to parse is not valid. private ICalculationBase ParseReadConfigurationItem(IReadConfigurationItem readConfigurationItem) { var readCalculationGroup = readConfigurationItem as ReadCalculationGroup; if (readCalculationGroup != null) { return ParseReadCalculationGroup(readCalculationGroup); } var readCalculation = readConfigurationItem as TReadCalculation; if (readCalculation != null) { return ParseReadCalculation(readCalculation); } throw new InvalidOperationException("Can't parse item that is not a calculation or calculation group."); } /// /// Parses the read calculation group and it's children. /// /// The calculation group to parse. /// A parsed calculation group. /// Thrown when the one of the children /// to parse is not valid. private CalculationGroup ParseReadCalculationGroup(ReadCalculationGroup readCalculationGroup) { var calculationGroup = new CalculationGroup(readCalculationGroup.Name, true); foreach (IReadConfigurationItem item in readCalculationGroup.Items) { ICalculationBase parsedItem = ParseReadConfigurationItem(item); if (parsedItem != null) { calculationGroup.Children.Add(parsedItem); } } return calculationGroup; } private void AddItemsToModel(IEnumerable parsedCalculationItems) { foreach (ICalculationBase parsedCalculationItem in parsedCalculationItems) { ImportTarget.Children.Add(parsedCalculationItem); } } } }