// Copyright (C) Stichting Deltares 2017. 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.IO;
using System.Linq;
using Core.Common.Base.Geometry;
using Core.Common.Base.IO;
using Core.Common.Util;
using Core.Common.Util.Builders;
using Core.Common.Util.Properties;
using Core.Components.Gis.Data;
using Core.Components.Gis.Features;
using Core.Components.Gis.Geometries;
using Core.Components.Gis.IO.Readers;
using Ringtoets.Common.Data.AssessmentSection;
using RingtoetsCommonIOResources = Ringtoets.Common.IO.Properties.Resources;
namespace Ringtoets.Common.IO.ReferenceLines
{
///
/// Shape file reader that reads objects based on the line feature in the file.
///
public static class ReferenceLinesMetaReader
{
private const string assessmentsectionIdAttributeKey = "TRAJECT_ID";
private const string signalingValueAttributeKey = "NORM_SW";
private const string lowerLimitValueAttributeKey = "NORM_OG";
///
/// Reads the current features in the shape file into a collection of objects.
///
/// The file path to the shape file.
/// The created collection of objects.
/// Thrown when is invalid.
/// Thrown when current feature in the shape file:
///
/// - points to a file that does not exist.
/// - The shape file does not contain the mandatory attributes.
/// - Has an empty attribute.
/// - The shape file has non-line geometries in it.
///
public static IEnumerable ReadReferenceLinesMetas(string shapeFilePath)
{
ValidateFilePath(shapeFilePath);
using (PolylineShapeFileReader reader = OpenPolyLineShapeFile(shapeFilePath))
{
ValidateExistenceOfRequiredAttributes(reader, shapeFilePath);
return ReadReferenceLinesMetas(reader);
}
}
private static IEnumerable ReadReferenceLinesMetas(PolylineShapeFileReader reader)
{
var referenceLinesMetas = new List();
ReferenceLineMeta referenceLinesMeta;
do
{
referenceLinesMeta = ReadReferenceLinesMeta(reader);
if (referenceLinesMeta != null)
{
referenceLinesMetas.Add(referenceLinesMeta);
}
} while (referenceLinesMeta != null);
return referenceLinesMetas;
}
private static ReferenceLineMeta ReadReferenceLinesMeta(PolylineShapeFileReader reader)
{
MapLineData lineData = ReadMapLineData(reader);
return lineData == null ? null : CreateReferenceLineMeta(lineData);
}
///
/// Validates the .
///
/// The file path to the shape file.
/// Thrown when is invalid.
/// Thrown when does not exist.
private static void ValidateFilePath(string shapeFilePath)
{
IOUtils.ValidateFilePath(shapeFilePath);
if (!File.Exists(shapeFilePath))
{
string message = new FileReaderErrorMessageBuilder(shapeFilePath)
.Build(Resources.Error_File_does_not_exist);
throw new CriticalFileReadException(message);
}
}
///
/// Validates the file by checking if all mandatory attributes are present in the shape file.
///
/// The opened shape file reader.
/// The file path to the shape file.
/// Thrown when the shape file lacks one of the mandatory attributes.
private static void ValidateExistenceOfRequiredAttributes(PolylineShapeFileReader polylineShapeFileReader, string shapeFilePath)
{
IEnumerable missingAttributes = GetMissingAttributes(polylineShapeFileReader);
if (missingAttributes.Any())
{
string message = string.Format(RingtoetsCommonIOResources.ReferenceLinesMetaReader_File_0_lacks_required_Attribute_1_,
shapeFilePath, string.Join("', '", missingAttributes));
throw new CriticalFileReadException(message);
}
}
private static IEnumerable GetMissingAttributes(PolylineShapeFileReader polylineShapeFileReader)
{
if (!polylineShapeFileReader.HasAttribute(assessmentsectionIdAttributeKey))
{
yield return assessmentsectionIdAttributeKey;
}
if (!polylineShapeFileReader.HasAttribute(signalingValueAttributeKey))
{
yield return signalingValueAttributeKey;
}
if (!polylineShapeFileReader.HasAttribute(lowerLimitValueAttributeKey))
{
yield return lowerLimitValueAttributeKey;
}
}
///
/// Opens a new to .
///
/// Path to the shape file to read.
/// A new instance of the class.
/// Thrown when is invalid.
/// Thrown when:
///
/// - points to a file that does not exist.
/// - The shape file has non-line geometries in it.
///
///
private static PolylineShapeFileReader OpenPolyLineShapeFile(string shapeFilePath)
{
return new PolylineShapeFileReader(shapeFilePath);
}
private static MapLineData ReadMapLineData(PolylineShapeFileReader polylineShapeFileReader)
{
return (MapLineData) polylineShapeFileReader.ReadFeature();
}
///
/// Creates a new from the .
///
/// The to create a from.
/// The newly created .
private static ReferenceLineMeta CreateReferenceLineMeta(MapLineData lineData)
{
MapFeature feature = lineData.Features.First();
string assessmentSectionId = GetAssessmentSectionId(feature);
int? signalingValue = ParseNormValue(feature.MetaData[signalingValueAttributeKey]);
int? lowerLimitValue = ParseNormValue(feature.MetaData[lowerLimitValueAttributeKey]);
IEnumerable geometryPoints = GetSectionGeometry(feature);
var referenceLineMeta = new ReferenceLineMeta
{
AssessmentSectionId = assessmentSectionId
};
if (lowerLimitValue != null)
{
referenceLineMeta.LowerLimitValue = lowerLimitValue.Value;
}
if (signalingValue != null)
{
referenceLineMeta.SignalingValue = signalingValue.Value;
}
referenceLineMeta.ReferenceLine.SetGeometry(geometryPoints);
return referenceLineMeta;
}
///
/// Gets the geometry from the .
///
/// The to get the geometry from.
/// A collection that represents the 's geometry.
private static IEnumerable GetSectionGeometry(MapFeature lineFeature)
{
MapGeometry[] mapGeometries = lineFeature.MapGeometries.ToArray();
if (mapGeometries.Length != 1)
{
return Enumerable.Empty();
}
return mapGeometries[0].PointCollections.First().Select(p => new Point2D(p)).ToArray();
}
private static string GetAssessmentSectionId(MapFeature lineFeature)
{
return Convert.ToString(lineFeature.MetaData[assessmentsectionIdAttributeKey]);
}
private static int? ParseNormValue(object readObject)
{
try
{
return readObject == null ? (int?) null : Convert.ToInt32(readObject);
}
catch (Exception exception)
{
if (exception is InvalidCastException || exception is FormatException || exception is OverflowException)
{
return null;
}
throw;
}
}
}
}