// Copyright (C) Stichting Deltares 2023. All rights reserved.
//
// This file is part of the application DAM - UI.
//
// 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.
//#define INCLUDE_ALL_LINE_TYPES
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using Deltares.Dam.Data.CsvImporters;
using Deltares.Maps;
namespace Deltares.Dam.Data.Importers;
///
/// Exception for the class LineAttributeImporter
///
public class LineAttributeImporterException : Exception
{
public LineAttributeImporterException() {}
public LineAttributeImporterException(string message)
: base(message) {}
public LineAttributeImporterException(string message, Exception inner)
: base(message, inner) {}
}
public class LineAttributeImporter : IAttributeImporter where T : CsvImporterLocations.LocationRecord
{
private readonly IList errors;
private IDictionary targetLookup;
private IFeatureRepository crossSectionRepository;
public LineAttributeImporter()
{
errors = new List();
targetLookup = new Dictionary();
}
///
///
///
public string LocationIDAttributeName { private get; set; }
///
/// Gets or sets the cross section repository
///
public IFeatureRepository CrossSectionRepository
{
get
{
return crossSectionRepository;
}
set
{
crossSectionRepository = value;
if (targetLookup != null &&
targetLookup.Count > 0 &&
value != null &&
IsValidString(LocationIDAttributeName))
{
// Filter out all locations which are not subject for the intersection query..
CrossSectionRepository.Remove(f => !targetLookup.ContainsKey(GetID(f)));
}
}
}
///
/// Gets or sets the target objects
///
public IEnumerable Targets
{
private get
{
return targetLookup.Values;
}
set
{
if (value != null)
{
targetLookup = value.ToDictionary(k => k.LocationId.ToLowerInvariant(), v => v);
if (CrossSectionRepository != null)
{
// Filter out all locations which are not subject for the intersection query..
CrossSectionRepository.Remove(f => !targetLookup.ContainsKey(GetID(f)));
}
}
}
}
///
///
public IFeatureRepository AttributeRepository { internal get; set; }
///
///
///
public IEnumerable Errors
{
get
{
return errors;
}
}
///
/// Gets or sets the name of the file.
///
///
/// The name of the file.
///
public string FileName { private get; set; }
///
/// Sets the attribute mappings
///
public IEnumerable> AttributeMappings { private get; set; }
public void AddError(Exception exception)
{
errors.Add(exception);
}
///
///
///
/// Preconditions:
/// - A valid data folder needs to given
/// - A set of "targets" with their characteristic points table and initialized id's available from the waterboard
/// - The required files need to be in the data folder (one for the characteristics points,
/// - A set of (characteristic) lines wich have to be retrieved from the files
///
/// Postconditions:
/// - Some targets (the result of a join from the Location shape file and the existing location list from the Waterboard) have new characteristic point values
///
///
///
///
///
///
public void Import()
{
if (AttributeRepository == null)
{
throw new InvalidOperationException("No repository set");
}
if (!AttributeRepository.SupportedAttributes.Any())
{
throw new InvalidOperationException("The repository doesn't contain attributes");
}
if (!IsValidString(LocationIDAttributeName))
{
throw new InvalidOperationException("The location ID attribute name is not valid");
}
if (CrossSectionRepository == null)
{
throw new InvalidOperationException("No cross section repository set");
}
if (AttributeMappings == null)
{
throw new InvalidOperationException("No attribute mappings set");
}
// Find the intersection points between the geometries
IEnumerable> results = CrossSectionRepository.GetIntersectionPoints(AttributeRepository);
var count = 0; // <- using count to omit the Linq.Count() for perfomance reasons
IEnumerable work = results.GetResultsHavingCount(1);
foreach (IntersectionResult intersectionResult in work)
{
foreach (AttributeMapping mapping in AttributeMappings)
{
IFeature crossSection, attributeLine;
if (intersectionResult.Source.Attributes.Exists(mapping.Name))
{
crossSection = intersectionResult.Target;
attributeLine = intersectionResult.Source;
}
else
{
if (intersectionResult.Target.Attributes.Exists(mapping.Name))
{
crossSection = intersectionResult.Source;
attributeLine = intersectionResult.Target;
}
else
{
AddError(new AttributeMissingException(mapping.Name));
continue;
}
}
// Get the surface line for the location having the location ID
string locationId = GetID(crossSection);
if (!targetLookup.ContainsKey(locationId))
{
errors.Add(new ImportException($"Location {LocationIDAttributeName} not found"));
continue;
}
T target = targetLookup[locationId];
object value = attributeLine.Attributes[mapping.Name];
try
{
// set the value on target property
mapping.Action(target, value);
if (mapping.Name.ToUpper() == "DAMPINGPL3")
{
if (target.DampingFactorPl3 < 0 || target.DampingFactorPl3 > 1)
{
AddError(new AttributeWrongValueException(mapping.Name, target.DampingFactorPl3.Value, 0.0, 1.0));
target.DampingFactorPl3 = 0;
}
}
if (String.Compare(mapping.Name, "DampingPL4", true) == 0)
{
if (target.DampingFactorPl4 < 0 || target.DampingFactorPl4 > 1)
{
AddError(new AttributeWrongValueException(mapping.Name, target.DampingFactorPl4.Value, 0.0, 1.0));
target.DampingFactorPl4 = 0;
}
}
count++;
}
catch (Exception e)
{
throw new AttributeParseException(
$"Error parsing the value '{value.ToString().Replace("\0", "")}' of '{mapping.Name}' for target '{target.LocationId}' ", e);
}
}
}
if (count == 0)
{
errors.Add(new NotSupportedException("There are none or multiple intersections found. There should be exactly one intersection for each location in the target repository"));
}
}
private string GetID(IFeature feature)
{
bool attributeExists = feature.Attributes.Exists(LocationIDAttributeName);
if (!attributeExists)
{
throw new LineAttributeImporterException($"Cannot find attribute '{LocationIDAttributeName}'");
}
return feature.Attributes[LocationIDAttributeName].ToString().ToLowerInvariant();
}
private static bool IsValidString(string value)
{
return !(string.IsNullOrEmpty(value) || value.Trim() == string.Empty);
}
}
[Serializable]
public class AttributeParseException : Exception
{
//
// For guidelines regarding the creation of new exception types, see
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/cpconerrorraisinghandlingguidelines.asp
// and
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp07192001.asp
//
public AttributeParseException() {}
public AttributeParseException(string message) : base(message) {}
public AttributeParseException(string message, Exception inner) : base(message, inner) {}
protected AttributeParseException(
SerializationInfo info,
StreamingContext context) : base(info, context) {}
}