//#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)
{
}
}
}