// Copyright (C) Stichting Deltares 2016. 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.IO.Exceptions;
using Core.Common.Utils;
using Core.Common.Utils.Builders;
using Core.Common.Utils.Properties;
using Core.Components.Gis.Data;
using Core.Components.Gis.Features;
using Core.Components.Gis.IO.Readers;
using Ringtoets.Common.Data.AssessmentSection;
using RingtoetsCommonIOResources = Ringtoets.Common.IO.Properties.Resources;
namespace Ringtoets.Common.IO
{
///
/// 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.
/// - Contains multiple poly lines.
///
public static List ReadReferenceLinesMetas(string shapeFilePath)
{
ValidateFilePath(shapeFilePath);
using (var reader = OpenPolyLineShapeFile(shapeFilePath))
{
ValidateExistenceOfRequiredAttributes(reader);
return ReadReferenceLinesMetas(reader);
}
}
private static List 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)
{
var 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)
{
FileUtils.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.
/// Thrown when the shape file lacks one of the mandatory attributes.
private static void ValidateExistenceOfRequiredAttributes(PolylineShapeFileReader polylineShapeFileReader)
{
IList missingAttributes = GetMissingAttributes(polylineShapeFileReader);
if (missingAttributes.Count == 1)
{
var message = string.Format(RingtoetsCommonIOResources.ReferenceLinesMetaReader_File_lacks_required_Attribute_0_,
missingAttributes[0]);
throw new CriticalFileReadException(message);
}
if (missingAttributes.Count > 1)
{
var message = string.Format(RingtoetsCommonIOResources.ReferenceLinesMetaReader_File_lacks_required_Attributes_0_,
string.Join("', '", missingAttributes));
throw new CriticalFileReadException(message);
}
}
private static IList GetMissingAttributes(PolylineShapeFileReader polylineShapeFileReader)
{
var list = new List(3);
if (!polylineShapeFileReader.HasAttribute(assessmentsectionIdAttributeKey))
{
list.Add(assessmentsectionIdAttributeKey);
}
if (!polylineShapeFileReader.HasAttribute(signalingValueAttributeKey))
{
list.Add(signalingValueAttributeKey);
}
if (!polylineShapeFileReader.HasAttribute(lowerLimitValueAttributeKey))
{
list.Add(lowerLimitValueAttributeKey);
}
return list;
}
///
/// 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.ReadLine();
}
///
/// Creates a new from the .
///
/// The to create a from.
/// The newly created .
/// Thrown when the shape file contains multiple poly lines.
private static ReferenceLineMeta CreateReferenceLineMeta(MapLineData lineData)
{
var features = lineData.Features.ToArray();
var feature = features[0];
string assessmentSectionId = GetAssessmentSectionId(feature);
int? signalingValue = GetSignalingValueAttributeKey(feature);
int? lowerLimitValue = GetLowerLimitValueAttribute(feature);
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.
/// Thrown when the shape file contains multiple poly lines.
private static IEnumerable GetSectionGeometry(MapFeature lineFeature)
{
var mapGeometries = lineFeature.MapGeometries.ToArray();
if (mapGeometries.Length > 1)
{
throw new CriticalFileReadException(RingtoetsCommonIOResources.ReferenceLineReader_File_contains_unsupported_multi_polyline);
}
return mapGeometries[0].PointCollections.First().Select(p => new Point2D(p.X, p.Y));
}
private static string GetAssessmentSectionId(MapFeature lineFeature)
{
return Convert.ToString(lineFeature.MetaData[assessmentsectionIdAttributeKey]);
}
private static int? GetSignalingValueAttributeKey(MapFeature lineFeature)
{
return lineFeature.MetaData[signalingValueAttributeKey] as int?;
}
private static int? GetLowerLimitValueAttribute(MapFeature lineFeature)
{
return lineFeature.MetaData[lowerLimitValueAttributeKey] as int?;
}
}
}