//#define INCLUDE_ALL_LINE_TYPES using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.Serialization; using Deltares.Maps; using Deltares.Standard; 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 : Location { private readonly IList errors; private IDictionary targetLookup; public LineAttributeImporter() { this.errors = new List(); this.targetLookup = new Dictionary(); } /// /// Gets or sets the target objects /// public IEnumerable Targets { private get { return this.targetLookup.Values; } set { if (value != null) { this.targetLookup = value.ToDictionary(k => k.Name.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 string LocationIDAttributeName { private get; set; } private IFeatureRepository crossSectionRepository; /// /// Gets or sets the cross section repository /// public IFeatureRepository CrossSectionRepository { get { return this.crossSectionRepository; } set { this.crossSectionRepository = value; if (this.targetLookup != null && this.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))); } } } /// /// /// public IEnumerable Errors { get { return this.errors; } } /// /// Gets or sets the name of the file. /// /// /// The name of the file. /// public string FileName { private get; set; } public void AddError(Exception exception) { this.errors.Add(exception); } /// /// Sets the attribute mappings /// public IEnumerable> AttributeMappings { private get; set; } private string GetID(IFeature feature) { bool attributeExists = feature.Attributes.Exists(LocationIDAttributeName); if (!attributeExists) { throw new LineAttributeImporterException(String.Format("Cannot find attribute '{0}'", LocationIDAttributeName)); } return feature.Attributes[LocationIDAttributeName].ToString().ToLowerInvariant(); } /// /// /// /// 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 (this.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 = this.CrossSectionRepository.GetIntersectionPoints(AttributeRepository); int 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)) { this.errors.Add(new ImportException(string.Format("Location {0} not found", LocationIDAttributeName))); 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, 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, 0.0, 1.0)); target.DampingFactorPL4 = 0; } } count++; } catch (Exception e) { throw new AttributeParseException( string.Format("Error parsing the value '{0}' of '{1}' for target '{2}' ", value.ToString().Replace("\0", ""), mapping.Name, target.Name), e); } } } if (count == 0) { this.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 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) { } } }