// Copyright (C) Stichting Deltares 2019. All rights reserved. // // This file is part of the application DAM - Clients Library. // // DAM - UI 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.Diagnostics; using System.IO; using System.Linq; using Deltares.Dam.Data.CsvImporters; using Deltares.Dam.Data.IO; using Deltares.Geometry; using Deltares.Geotechnics.IO; using Deltares.Geotechnics.Soils; using Deltares.Geotechnics.SurfaceLines; using Deltares.Maps; using Deltares.Standard; using Deltares.Standard.Logging; using GeoAPI.Geometries; namespace Deltares.Dam.Data.DataPlugins { using Data; using Importers; using Configuration; using Location = Location; // TODO: Import PL1-lines /// /// ImportMode /// internal enum ImportMode { DikeRingAndLocationData, All } /// /// Exception for DataPluginImporter /// public class DataPluginImporterException : ApplicationException { public DataPluginImporterException() { } public DataPluginImporterException(string message) : base(message) { } public DataPluginImporterException(string message, Exception inner) : base(message, inner) { } } /// /// DataPlugin implementation to import from files /// public class DataPluginImporter : IDataPlugin { private bool isAllDataImported = false; private bool isDikeRingAndLocationDataImported = false; private WaterBoard waterBoard; private readonly IFeatureRepository repository = new FeatureRepository(); private readonly List importLogMessages = new List(); private List attributes; private DamProjectType damProjectType; private bool csvDataAdded = false; private string damProjectFolder; /// /// Initializes a new instance of the class. /// public DataPluginImporter() { InitializeWaterBoard(); attributes = new List(); } private void InitializeWaterBoard() { if (waterBoard != null) { waterBoard.Dispose(); } waterBoard = new WaterBoard(); } /// /// Sets the type of the dam project. /// /// /// The type of the dam project. /// public DamProjectType DamProjectType { set { damProjectType = value; } } /// /// Gets the import log messages. /// /// /// The import log messages. /// public List ImportLogMessages { get { return importLogMessages; } } /// /// Gets or sets the dam project folder. /// /// /// The dam project folder. /// public string DamProjectFolder { get { return damProjectFolder; } set { if (damProjectFolder != value) { damProjectFolder = value; Clear(); } } } /// /// Gets the data folder. /// /// /// The data folder. /// public string DataFolder { get; private set; } /// /// Gets or sets the attributes. /// /// /// The attributes. /// /// value public IEnumerable Attributes { get { return attributes; } set { if (value == null) throw new ArgumentNullException("value"); isAllDataImported = false; attributes = value as List ?? value.ToList(); } } /// /// Define data sources /// /// /// public void SetDataSources(string dataFolder, IEnumerable dataSources) { isAllDataImported = false; DataFolder = dataFolder; DataSources = dataSources; } /// /// Get data source definitions /// /// public IEnumerable DataSources { get; private set; } /// /// Get info for WaterBoard /// /// public Info WaterBoardInfo { get { ThrowIfDataNotRead(); return new Info { Name = waterBoard.Name, Description = waterBoard.Description, Source = DataSourceManager.GetSource(waterBoard, "Name") }; } } /// /// Gets the map geometry identifier list. /// /// /// The map geometry identifier list. /// public IEnumerable MapGeometryIdList { get { ThrowIfDataNotRead(); return repository.FeatureIds.Select(id => id.ToString()); } } /// /// Clears this instance. /// private void Clear() { InitializeWaterBoard(); isAllDataImported = false; isDikeRingAndLocationDataImported = false; } /// /// Gets the dike. /// /// The dike ring identifier. /// private Dike GetDike(string dikeRingId) { ThrowIfDataNotRead(); return waterBoard.Dikes.First(d => d.Name.Equals(dikeRingId)); } /// /// Gets the or create dike. /// /// The dike ring identifier. /// private Dike GetOrCreateDike(string dikeRingId) { // first check to see if this dike is already known, if not create it Dike dike = null; // try to get it if (waterBoard.Dikes.Any()) { var id = dikeRingId; dike = waterBoard.Dikes.FirstOrDefault(x => x.Name.Equals(id)); } // not found, create it if (dike == null) { dike = new Dike { Name = dikeRingId }; waterBoard.Dikes.Add(dike); } return dike; } /// /// Gets the segment. /// /// The segment identifier. /// private Segment GetSegment(string segmentID) { ThrowIfDataNotRead(); return waterBoard.Segments.First(s => s.Name.Equals(segmentID)); } /// /// Gets the location. /// /// The dike ring identifier. /// The location identifier. /// private Location GetLocation(string dikeRingId, string locationId) { var dike = GetDike(dikeRingId); return dike.Locations.First(l => l.Name.Equals(locationId)); } /// /// Gets a soil. /// /// The dike ring identifier. /// The soil identifier. /// private Soil GetSoil(string dikeRingId, string soilId) { var dike = GetDike(dikeRingId); Soil soil = dike.SoilList.GetSoilByName(soilId); return soil; } /// /// Gets a soil profile. /// /// The dike ring identifier. /// The soil profile1 d identifier. /// private SoilProfile1D GetSoilProfile(string dikeRingId, string soilProfile1DId) { var dike = GetDike(dikeRingId); return dike.SoilProfiles.First(p => p.Name.Equals(soilProfile1DId)); } /// /// Gets a scenario. /// /// The dike ring identifier. /// The location identifier. /// The scenario identifier. /// private Scenario GetScenario(string dikeRingId, string locationId, string scenarioId) { var dike = GetDike(dikeRingId); var location = dike.Locations.FirstOrDefault(l => l.Name.Equals(locationId)); return (location == null ? null : location.Scenarios.FirstOrDefault(s => s.LocationScenarioID.Equals(scenarioId))); } /// /// Gets a surface line. /// /// The dike ring identifier. /// The surface line identifier. /// private SurfaceLine2 GetSurfaceLine(string dikeRingId, string surfaceLineId) { var dike = GetDike(dikeRingId); return dike.SurfaceLines2.First(x => x.Name.Equals(surfaceLineId)); } /// /// Gets the surface line identifier list. /// /// The dike ring identifier. /// public IEnumerable GetSurfaceLineIdList(string dikeRingId) { var dike = GetDike(dikeRingId); return dike.SurfaceLines2.Select(surfaceLine => surfaceLine.Name); } /// /// Gets the parameters from dictionary. /// /// The dictionary. /// The source. /// private IEnumerable GetParametersFromDictionary( Dictionary dictionary, object source) { var pairs = dictionary.Select(nameValuePair => new NameValueParameter { ParameterName = nameValuePair.Key, ParameterValue = nameValuePair.Value, Source = DataSourceManager.GetSource(source, nameValuePair.Key) }); return new List(pairs); } /// /// Gets the dike ring identifier list. /// /// Type of the dam. /// public IEnumerable GetDikeRingIdList(DamType damType) { ImportDikeRingAndLocationData(damType); return waterBoard.Dikes.Select(dike => dike.Name); } /// /// Imports the data for dike rings. /// /// The dike ring ids. /// Type of the dam. /// The progress. public void ImportDataForDikeRings(IEnumerable dikeRingIds, DamType damType, DamEngine.Data.Standard.Calculation.ProgressDelegate progress) { ImportAllData(dikeRingIds, damType, progress); } /// /// Gets the scenario list. /// /// The dike ring identifier. /// The location identifier. /// public IEnumerable GetScenarioList(string dikeRingId, string locationId) { var location = GetLocation(dikeRingId, locationId); return location.Scenarios.Select(scenario => scenario.LocationScenarioID); } /// /// Gets the dike ring information. /// /// The dike ring identifier. /// public Info GetDikeRingInfo(string dikeRingId) { var dike = GetDike(dikeRingId); return new Info { Name = dike.Name, Description = dike.Description, Source = DataSourceManager.GetSource(dike, "Name") }; } /// /// Gets the dike parameters. /// /// The dike ring identifier. /// public IEnumerable GetDikeParameters(string dikeRingId) { var dike = GetDike(dikeRingId); var nameValuePairs = dike.GetParametersAsNameValuePairs(); return GetParametersFromDictionary(nameValuePairs, dike); } /// /// Gets the location identifier list. /// /// The dike ring identifier. /// Type of the dam. /// public IEnumerable GetLocationIdList(string dikeRingId, DamType damType) { ImportDikeRingAndLocationData(damType); var dike = GetDike(dikeRingId); return dike.Locations.Select(location => location.Name); } /// /// Gets the location information. /// /// The dike ring identifier. /// The location identifier. /// public Info GetLocationInfo(string dikeRingId, string locationId) { var location = GetLocation(dikeRingId, locationId); return new Info { Name = location.Name, Description = "", Source = DataSourceManager.GetSource(location, "Name") }; } /// /// Gets the location details. /// /// The dike ring identifier. /// The location identifier. /// public IEnumerable GetLocationDetails(string dikeRingId, string locationId) { var location = GetLocation(dikeRingId, locationId); var nameValuePairs = location.GetParametersAsNameValuePairs(); return GetParametersFromDictionary(nameValuePairs, location); } /// /// Gets the scenario details. /// /// The dike ring identifier. /// The location identifier. /// The scenario identifier. /// public IEnumerable GetScenarioDetails(string dikeRingId, string locationId, string scenarioId) { var location = GetLocation(dikeRingId, locationId); var scenario = GetScenario(dikeRingId, locationId, scenarioId); if (scenario == null) yield break; var nameValuePairs = scenario.GetParametersAsNameValuePairs(); foreach (var nameValuePair in nameValuePairs) { yield return new NameValueParameter { ParameterName = nameValuePair.Key, ParameterValue = nameValuePair.Value, Source = DataSourceManager.GetSource(location, nameValuePair.Key) }; } } public void DisposeImportedItem(string dikeRingId) { GetDike(dikeRingId).Dispose(); } /// /// Gets the surface line points. /// /// The dike ring identifier. /// The surface line identifier. /// public IList GetSurfaceLinePoints(string dikeRingId, string surfaceLineId) { var surfaceLine = GetSurfaceLine(dikeRingId, surfaceLineId); var surfaceLinePoints = new List(); for (int pointIndex = 0; pointIndex < surfaceLine.Geometry.Points.Count(); pointIndex++) { surfaceLinePoints.Add(surfaceLine.Geometry.Points[pointIndex]); } return surfaceLinePoints; } /// /// Gets the surface line characteristic points. /// /// The dike ring identifier. /// The surface line identifier. /// public IEnumerable GetSurfaceLineCharacteristicPoints(string dikeRingId, string surfaceLineId) { var surfaceLine = GetSurfaceLine(dikeRingId, surfaceLineId); foreach (CharacteristicPointType type in Enum.GetValues(typeof(CharacteristicPointType))) { // get & check point var point = surfaceLine.CharacteristicPoints.GetGeometryPoint(type); if (point == null) continue; if ((point.X == -1.0) && (point.Y == -1.0) && (point.Z == -1.0)) continue; // create point yield return new DpCharacteristicPoint { Id = type.ToString(), X = point.X, Y = point.Y, Z = point.Z }; } } /// /// Gets the segment identifier list. /// /// The dike ring identifier. /// public IEnumerable GetSegmentIdList(string dikeRingId) { ThrowIfDataNotRead(); return waterBoard.Segments.Select(segment => segment.Name); } /// /// Gets the profile1 d identifier list for segment. /// /// The dike ring identifier. /// The segment identifier. /// Type of the segment failure mechanism. /// public IEnumerable GetProfile1DIdListForSegment(string dikeRingId, string segmentId, FailureMechanismSystemType segmentFailureMechanismType) { ThrowIfDataNotRead(); var segment = GetSegment(segmentId); foreach (SoilGeometryProbability soilGeometryProbability in segment.SoilProfileProbabilities) { if (soilGeometryProbability.SoilProfile != null) { if ((soilGeometryProbability.SegmentFailureMechanismType == null) || (soilGeometryProbability.SegmentFailureMechanismType.Value == segmentFailureMechanismType)) yield return soilGeometryProbability.SoilGeometryName; } } } /// /// Gets the profile2 d identifier list for segment. /// /// The dike ring identifier. /// The segment identifier. /// Type of the segment failure mechanism. /// public IEnumerable GetProfile2DIdListForSegment(string dikeRingId, string segmentId, FailureMechanismSystemType segmentFailureMechanismType) { ThrowIfDataNotRead(); var segment = GetSegment(segmentId); foreach (SoilGeometryProbability soilGeometryProbability in segment.SoilProfileProbabilities) { if (soilGeometryProbability.SoilProfile == null) { if ((soilGeometryProbability.SegmentFailureMechanismType == null) || (soilGeometryProbability.SegmentFailureMechanismType.Value == segmentFailureMechanismType)) yield return soilGeometryProbability.SoilGeometryName; } } } /// /// Gets the segment profile1 d details. /// /// The dike ring identifier. /// The segment identifier. /// The profile1 d identifier. /// public IEnumerable GetSegmentProfile1DDetails(string dikeRingId, string segmentId, string profile1DId, FailureMechanismSystemType segmentFailureMechanismType) { var segment = GetSegment(segmentId); var nameValuePairs = segment.GetParametersForSoilProfile1DAsNameValuePairs(profile1DId, segmentFailureMechanismType); return GetParametersFromDictionary(nameValuePairs, segment); } /// /// Gets the segment profile2 d details. /// /// The dike ring identifier. /// The segment identifier. /// The profile2 d identifier. /// public IEnumerable GetSegmentProfile2DDetails(string dikeRingId, string segmentId, string profile2DId, FailureMechanismSystemType failureMechanismSystemType) { var segment = GetSegment(segmentId); var nameValuePairs = segment.GetParametersForSoilProfile2DAsNameValuePairs(profile2DId, failureMechanismSystemType); return GetParametersFromDictionary(nameValuePairs, segment); } /// /// Gets the soil profile1 d identifier list. /// /// The dike ring identifier. /// public IEnumerable GetSoilProfile1DIdList(string dikeRingId) { var dike = GetDike(dikeRingId); return dike.SoilProfiles.Select(soilProfile => soilProfile.Name); } /// /// Gets the soil profile1 d details. /// /// The dike ring identifier. /// The soil profile1 d identifier. /// public DpSoilProfile GetSoilProfile1DDetails(string dikeRingId, string soilProfile1DId) { var soilProfile = GetSoilProfile(dikeRingId, soilProfile1DId); var dpSoilProfile = new DpSoilProfile { Layers = new List() }; for (int layerIndex = 0; layerIndex < soilProfile.Layers.Count; layerIndex++) { var dpLayer = new DpLayer { TopLevel = soilProfile.Layers[layerIndex].TopLevel, SoilName = soilProfile.Layers[layerIndex].Soil.Name }; dpSoilProfile.Layers.Add(dpLayer); } var bottomLevelLayer = new DpLayer { TopLevel = soilProfile.BottomLevel, SoilName = SoilProfile1D.SoilProfileBottomLevelId }; dpSoilProfile.Layers.Add(bottomLevelLayer); return dpSoilProfile; } /// /// Gets the soil profile2 d identifier list. /// /// The dike ring identifier. /// /// public IEnumerable GetSoilProfile2DIdList(string dikeRingId) { ThrowIfDataNotRead(); throw new NotImplementedException(); } /// /// Gets the soil profile2 d details. /// /// The dike ring identifier. /// The soil profile2 d identifier. /// /// public string GetSoilProfile2DDetails(string dikeRingId, string soilProfile2DId) { ThrowIfDataNotRead(); throw new NotImplementedException(); } /// /// Gets the soil identifier list. /// /// The dike ring identifier. /// public IEnumerable GetSoilIdList(string dikeRingId) { var dike = GetDike(dikeRingId); IEnumerable soilNames = dike.SoilList.Soils.Select(soil => soil.Name).ToList(); return soilNames; } /// /// Gets the soil aquifer values. /// /// The dike ring identifier. /// public IEnumerable GetSoilAquiferValues(string dikeRingId) { var dike = GetDike(dikeRingId); var res = new List(); foreach (var soil in dike.SoilList.Soils) { if (dike.SoilList.AquiferDictionary.ContainsKey(soil)) { var nvp = new NameValueParameter(); nvp.ParameterName = soil.Name; nvp.ParameterValue = dike.SoilList.AquiferDictionary[soil].ToString(); nvp.Source = DataSourceSystemType.MSoilBase; res.Add(nvp); } } return res; } /// /// Gets the soil details. /// /// The dike ring identifier. /// The soil identifier. /// public IEnumerable GetSoilDetails(string dikeRingId, string soilId) { var soil = GetSoil(dikeRingId, soilId); var nameValuePairs = SoilUtils.GetParametersAsNameValuePairs(soil); return GetParametersFromDictionary(nameValuePairs, soil); } /// /// Gets the map geometry. /// /// The map geometry identifier. /// public string GetMapGeometry(string mapGeometryId) { ThrowIfDataNotRead(); var geom = GetGeometryById(mapGeometryId); return geom.AsText(); } /// /// Gets the map geometry attributes. /// /// The map geometry identifier. /// public IEnumerable GetMapGeometryAttributes(string mapGeometryId) { ThrowIfDataNotRead(); var geom = GetGeometryById(mapGeometryId); var geomAttributes = repository.GetAttributes(geom); return geomAttributes .Select(kvp => new NameValueParameter { ParameterName = kvp.Key, ParameterValue = kvp.Value.ToString() }).ToList(); } /// /// Import all csv files /// /// /// The DamType is not (yet) read from the csv file; we assign the specified DamType to all locations that are read /// /// /// private CsvImporter ImportCsvFiles(string importFolder, DamType damType, ImportMode importMode, DamEngine.Data.Standard.Calculation.ProgressDelegate progress) { DataSourceManager.CurrentSource = DataSourceSystemType.Csv; var csvImporter = new CsvImporter(); bool isImportOnlyLocations = (importMode == ImportMode.DikeRingAndLocationData); csvImporter.ImportCsvDataFromDirectory(importFolder, isImportOnlyLocations, progress, damType, damProjectType); // add messages var messages = csvImporter.ErrorMessages; ImportLogMessages.AddRange(messages); DataSourceManager.CurrentSource = DataSourceSystemType.User; // check for fatal messages bool importOk = messages.All(m => m.MessageType != LogMessageType.FatalError); return importOk ? csvImporter : null; } /// /// Import name of the specified soilbase to all dikerings with id as specified in dikeRingIds. /// Note that it does NOT import the soils in the database themselves. /// If dikeringId not found then a new dike is created for that dikeRingId. /// /// path where the data can be found /// private void ImportMSoilBaseName(string importFolder, IEnumerable dikeRingIds) { if (dikeRingIds == null) return; DataSourceManager.CurrentSource = DataSourceSystemType.MSoilBase; foreach (string dikeRingId in dikeRingIds) { var dike = GetOrCreateDike(dikeRingId); dike.SoilDatabaseName = importFolder; } DataSourceManager.CurrentSource = DataSourceSystemType.User; } /// /// Import the specified MGeobase to all dikerings with id as specified in dikeRingIds /// Note that this does import the 1D soil profiles together with the soils and their parameters. /// If dikeringId not found then a new dike is created for that dikeRingId /// /// path where the data can be found /// private void ImportMGeobase(string importFolder, IEnumerable dikeRingIds) { if (dikeRingIds == null) return; DataSourceManager.CurrentSource = DataSourceSystemType.MGeobase; foreach (string dikeRingId in dikeRingIds) { // first check to see if this dike is already known, if not create it var dike = GetOrCreateDike(dikeRingId); dike.SoilDatabaseName = importFolder; dike.AddSoilProfilesFromDB(); } DataSourceManager.CurrentSource = DataSourceSystemType.User; } /// /// Import data from Iris shapefiles /// /// path where the data can be found private void ImportIrisFiles(string importFolder) { DataSourceManager.CurrentSource = DataSourceSystemType.Iris; // get locations (locationid and beginpoint and endpoint in RD) from "locations.shp" (LocationsNew) // get line of buitenkruinlijn // voeg aan elke locatie snijpunt met buitenkruinlijn toe (geen snijpunt is exception) // nu heeft locatie een begin-, eind- en buitenrkuinpunt // get line of binnenkruinlijn // voeg aan elke locatie snijpunt met binnenkruinlijn toe (geen snijpunt is exception) // nu heeft locatie een begin-, eind-, binnen- en buitenrkuinpunt // er is al een lijst met locaties in Waterboard WaterBoard.Dike[0].Locations (LocationsOrg) // LocationOrg.GeometryPoint[DikeTopAtRiver] = LocationNew.buitenkuinpunt // LocationOrg.GeometryPoint[DikeTopAtPolder] = LocationNew.binnnenkuinpunt // Als LocationNew.id niet gevonden kan worden in LocationsOrg dan excpetion // Get all locations from waterboard var locations = GetAllLocations(); var importer = new LocationCharacteristicPointImporter(importFolder, locations); importer.Import(); DataSourceManager.CurrentSource = DataSourceSystemType.User; } /// /// Get background shapefile for this waterboard /// /// path where the data can be found private void ImportBackgroundShapeFiles(string importFolder) { DataSourceManager.CurrentSource = DataSourceSystemType.Gis; var reader = new ShapeFileReader(importFolder) { IgnoreAttributeData = true }; var importer = new FeatureImporter(repository, reader); importer.Import(); DataSourceManager.CurrentSource = DataSourceSystemType.User; } /// /// Get all locations for all dikes /// /// private IEnumerable GetAllLocations() { return waterBoard.Dikes.SelectMany(dike => dike.Locations); } /// /// Import locations from shapefile /// /// /// private void ImportLocationsFromShapeFile(string importFolder, IEnumerable dataAttributes) { if (importFolder == null) throw new ArgumentNullException("importFolder"); LocationShapeFileImporter locationImporter = LocationShapeFileImporter.Create(new List(), dataAttributes, importFolder); //FeatureSet fs = new FeatureSet(); // Not completed yet. Implement code from MapEditor.FileOpen } /// /// Pre conditions: /// - A list of waterboard locations with initialized x,y values /// - shape file ccontaining the attributes and data /// /// Post condition: /// - Location properties (in relation to the attributes) are set /// /// /// /// /// /// /// private void ImportDataShapeFiles(string importFolder, IEnumerable dataAttributes, ImportMode importMode, IEnumerable dikeRingIds, DamType damType, DamEngine.Data.Standard.Calculation.ProgressDelegate progress) { DataSourceManager.CurrentSource = DataSourceSystemType.Gis; if (importFolder == null) throw new ArgumentNullException("importFolder"); string importErrorLogFile = @"shapefiletrace.log"; if (!string.IsNullOrEmpty(DamProjectFolder)) { importErrorLogFile = Path.Combine(DamProjectFolder, importErrorLogFile); } var locations = GetAllLocations(); var locationList = locations as List ?? locations.ToList(); var dataAttributesList = dataAttributes as List ?? dataAttributes.ToList(); var exceptions = new List(); var csvImportedDike = waterBoard.Dikes[0]; var existingDikeRings = waterBoard.Dikes.Select(dike => dike.Name).ToList(); var locationImporter = LocationShapeFileImporter.Create( locationList, dataAttributesList, importFolder); if (locationImporter != null) { locationImporter.Import(); var newDikeRings = locationImporter.ImportedItems.Select(l => l.DikeRingId).Distinct(); locationList = locationImporter.ImportedItems.ToList(); foreach (var newDikeRingId in newDikeRings) { // // This is where all the locations are imported for a dikering // Only the location and damptype willbe read here // All other attributes are read later in this function // Dike dike; if (!existingDikeRings.Contains(newDikeRingId)) { dike = new Dike { Name = newDikeRingId, SoilBaseDB = csvImportedDike.SoilBaseDB }; waterBoard.Dikes.Insert(0, dike); } else { var ringId = newDikeRingId; dike = waterBoard.Dikes.First(existingDike => existingDike.Name == ringId); } string id = newDikeRingId; foreach (Location location in locationList.Where(location => location.DikeRingId == id)) { if (location.DamType == damType) { // Replace if location existsȚ else add Location existingLocation = dike.Locations.FirstOrDefault(l => l.Name == location.Name); if (existingLocation != null) { int indexExistingLocation = dike.Locations.IndexOf(existingLocation); dike.Locations[indexExistingLocation] = location; } else { dike.Locations.Add(location); } } } } } // Remove dikes that are not specified and rebuild the total locations list if (dikeRingIds != null) { var newLocations = new List(); var dikeRingIdList = dikeRingIds.ToList(); for (int dikeIndex = waterBoard.Dikes.Count - 1; dikeIndex >= 0; dikeIndex--) { int index = dikeIndex; string result = dikeRingIdList.FirstOrDefault(s => s == waterBoard.Dikes[index].Name); if (result == null) { waterBoard.Dikes.RemoveAt(index); } else { newLocations.AddRange(waterBoard.Dikes[index].Locations); } } locationList = newLocations; } // Skip reading properties when only dikering and locationdata is required if (importMode == ImportMode.All) { // // Location Property Importer // This is where all the attribute values are read form the shapefiles // var importer = new LocationPropertyImporter(importFolder, dataAttributesList) { Targets = locationList }; importer.Import(progress); exceptions.AddRange(importer.ImportErrors); } using (var sw = new StreamWriter(importErrorLogFile, false)) { if (!exceptions.Any()) return; foreach (var error in exceptions) { //defaultWriter.Write(error.Message); sw.WriteLine("Date: {0}, Error type: {1}, Message: {2}", DateTime.Now.ToShortDateString(), error.GetType().Name, error.Message); var lm = new LogMessage(LogMessageType.Error, this, error.Message); importLogMessages.Add(lm); } } } /// /// Gets the geometry by identifier. /// /// The map geometry identifier. /// /// mapGeometryId /// Can't find a geometry with this id private IGeometry GetGeometryById(string mapGeometryId) { if (mapGeometryId == null) throw new ArgumentNullException("mapGeometryId"); var id = new Guid(mapGeometryId); var geom = repository.GetGeometryById(id); if (geom == null) throw new ArgumentException("Can't find a geometry with this id"); return geom; } /// /// Import only Dikering and location id's /// private void ImportDikeRingAndLocationData(DamType damType) { if (isDikeRingAndLocationDataImported || isAllDataImported) return; foreach (var dataSource in DataSources) { ImportDikeRingAndLocationData(dataSource, damType); } isDikeRingAndLocationDataImported = true; } /// /// Gets the data location. /// /// The data source. /// private string GetDataLocation(DataSource dataSource) { var dataLocation = dataSource.DataLocation; if (!string.IsNullOrEmpty(DataFolder) && (!Directory.Exists(dataLocation) || !File.Exists(dataLocation))) { dataLocation = Path.Combine(DataFolder, dataLocation); } return dataLocation; } /// /// Imports the dike ring and location data. /// /// The data source. /// Type of the dam. /// private void ImportDikeRingAndLocationData(DataSource dataSource, DamType damType) { var dataLocation = GetDataLocation(dataSource); switch (dataSource.DataSourceType) { case DataSourceType.CsvFiles: // New importer var csvImporter = ImportCsvFiles(dataLocation, damType, ImportMode.DikeRingAndLocationData, null); var combineImportedData = new CombineImportedData { WaterBoard = waterBoard, LocationRecords = csvImporter.LocationRecords, }; combineImportedData.AddCsvDataToDikes(); break; case DataSourceType.DataShapeFiles: ImportShapeFile(dataLocation, damType); break; case DataSourceType.Iris: case DataSourceType.BackgroundShapeFiles: case DataSourceType.MSoilBase: case DataSourceType.MGeobase: break; default: throw new ArgumentOutOfRangeException(); } } /// /// Imports the data. /// /// The data source. /// Type of the dam. /// The dike ring identifier list. /// The import mode. /// The progress. /// The CSV importer. /// private void ImportData2(DataSource dataSource, DamType damType, IEnumerable dikeRingIdList, ImportMode importMode, DamEngine.Data.Standard.Calculation.ProgressDelegate progress, ref CsvImporter csvImporter) { var dataLocation = GetDataLocation(dataSource); switch (dataSource.DataSourceType) { case DataSourceType.CsvFiles: // New importer csvImporter = ImportCsvFiles(dataLocation, damType, importMode, progress); if (csvImporter != null && csvImporter.LocationRecords.Count > 0) { // This is to support projects which have defined locations in locations.csv // This is needed specifically for Koswat // If Koswat generates a project where the locations are defined in a shape this code // can be removed. AddCsvDataToDikes(csvImporter); } break; case DataSourceType.Iris: ImportIrisFiles(dataLocation); break; case DataSourceType.DataShapeFiles: ImportDataShapeFiles(dataLocation, attributes, importMode, dikeRingIdList, damType, progress); break; case DataSourceType.BackgroundShapeFiles: if (importMode == ImportMode.All) { ImportBackgroundShapeFiles(dataLocation); } break; case DataSourceType.MSoilBase: ImportMSoilBaseName(dataLocation, dikeRingIdList); break; case DataSourceType.MGeobase: ImportMGeobase(dataLocation, dikeRingIdList); break; default: throw new ArgumentOutOfRangeException(); } } /// /// Imports the shape file. /// /// The data location. /// Type of the dam. private void ImportShapeFile(string dataLocation, DamType damType) { // get locations var configuredAttribute = attributes.SingleOrDefault(a => a.AttributeId.Equals( LocationShapeFileAttributeMap.LocationAttributeId, StringComparison.InvariantCultureIgnoreCase)); if (configuredAttribute == null) { return; } var locations = LocationShapeFileImporterDotSpatial.ImportLocations( Path.Combine(dataLocation, configuredAttribute.DataSource), damType, attributes); // Split locations in several dikes based on DikeRingid var newDikeRings = locations.Select(l => l.DikeRingId).Distinct(); foreach (var newDikeRingId in newDikeRings) { var dike = GetOrCreateDike(newDikeRingId); // TODO var id = newDikeRingId; foreach (var location in locations.Where(location => location.DikeRingId == id)) { dike.Locations.Add(location); } } } /// /// Imports all data. /// /// The dike ring ids. /// Type of the dam. /// The progress. private void ImportAllData(IEnumerable dikeRingIds, DamType damType, DamEngine.Data.Standard.Calculation.ProgressDelegate progress) { // do nothing if all data is already imported if (isAllDataImported) return; ImportData(ImportMode.All, dikeRingIds, damType, progress); isAllDataImported = true; } /// /// Import all data /// private void ImportData(ImportMode importMode, IEnumerable dikeRingIds, DamType damType, DamEngine.Data.Standard.Calculation.ProgressDelegate progress) { ThrowIfNoDataDefinitions(); if (!isDikeRingAndLocationDataImported) { // If locations and dikeringIds were not read yet then we start with a new waterboard // Else continue with waterboard that was created when importing the locations InitializeWaterBoard(); } waterBoard.Description = "Waterschap"; CsvImporter csvImporter = null; var dikeRingIdList = dikeRingIds == null ? null : dikeRingIds as List ?? dikeRingIds.ToList(); csvDataAdded = false; foreach (var dataSource in DataSources) { ImportData2(dataSource, damType, dikeRingIdList, importMode, progress, ref csvImporter); } if (!csvDataAdded) { AddCsvDataToDikes(csvImporter); } if (importMode == ImportMode.All) { CorrectSegmentAssignments(); if (damProjectType == DamProjectType.Assessment) { RemoveInvalidLocations(); } } } /// /// Removes the invalid locations. /// private void RemoveInvalidLocations() { var removeLocations = new List(); Location.DamProjectType = DamProjectType.Assessment; foreach (var location in waterBoard.Locations) { var res = location.ValidateLocationHasSegment(); if (res.Any()) { removeLocations.Add(location); foreach (var validationResult in res) { var logmessage = new LogMessage(LogMessageType.Error, location, validationResult.Text); importLogMessages.Add(logmessage); } } var res2 = location.ValidateLocationHasValidEssentialAssessmentValues(); if (res2.Any()) { removeLocations.Add(location); foreach (var validationResult in res2) { var logmessage = new LogMessage(LogMessageType.Error, location, validationResult.Text); importLogMessages.Add(logmessage); } } } foreach (var removeLocation in removeLocations) { waterBoard.Locations.Remove(removeLocation); // Remove the locations from the dikes too as those are the ones that are used in (re-)filling the project (waterboard) foreach (var dike in waterBoard.Dikes) { dike.Locations.Remove(removeLocation); } } } /// /// Adds the CSV data to dikes. /// /// The CSV importer. private void AddCsvDataToDikes(CsvImporter csvImporter) { if (csvImporter != null) { DataSourceManager.CurrentSource = DataSourceSystemType.Csv; var combineImportedData = new CombineImportedData { WaterBoard = waterBoard, LocationRecords = csvImporter.LocationRecords, CharacteristicPointsRecords = csvImporter.CharacteristicPointsRecords, ScenarioRecords = csvImporter.ScenariosRecords, SegmentRecords = csvImporter.SegmentRecords, SoilProfilerecords = csvImporter.SoilProfilesRecords, SurfaceLineRecords = csvImporter.SurfaceLinesRecords }; combineImportedData.AddCsvDataToDikes(); importLogMessages.AddRange(combineImportedData.ErrorMessages); Debug.Assert(ReferenceEquals(waterBoard, combineImportedData.WaterBoard)); waterBoard = combineImportedData.WaterBoard; csvDataAdded = true; } } /// /// When segment shapefile has assigned new segmentIds the segment object has to be re-assigned /// private void CorrectSegmentAssignments() { foreach (var dike in waterBoard.Dikes) { foreach (var location in dike.Locations) { location.Segment = waterBoard.Segments.FirstOrDefault(s => s.Name.Equals(location.SegmentId)); } } } /// /// Check if data definitions already specified /// private void ThrowIfNoDataDefinitions() { if (DataSources == null || !DataSources.Any()) { throw new DataPluginImporterException("No data sources defined"); } } /// /// Check if data has been read /// private void ThrowIfDataNotRead() { if (!isAllDataImported) { throw new DataPluginImporterException("Data has not been imported yet"); } } /// /// Returns a that represents this instance. /// /// /// A that represents this instance. /// public override string ToString() { return "DataPluginImporter"; } } }