// 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.Linq;
using Application.Ringtoets.Storage.Create;
using Application.Ringtoets.Storage.DbContext;
using Application.Ringtoets.Storage.Exceptions;
using Application.Ringtoets.Storage.Properties;
using Core.Common.Base.Geometry;
using Ringtoets.Piping.Primitives;
namespace Application.Ringtoets.Storage.Update
{
///
/// Extension methods for related to updating
/// an .
///
internal static class RingtoetsPipingSurfaceLineUpdateExtensions
{
///
/// Updates a in the database based on the information
/// of the .
///
/// The piping surfaceline to update the database entity for.
/// The object keeping track of update operations.
/// The context to obtain the existing entity from.
/// Thrown when either:
///
/// - is null
/// - is null
///
/// When no
/// can be found in that matches .
internal static void Update(this RingtoetsPipingSurfaceLine surfaceLine, PersistenceRegistry registry, IRingtoetsEntities context)
{
if (registry == null)
{
throw new ArgumentNullException("registry");
}
if (context == null)
{
throw new ArgumentNullException("context");
}
SurfaceLineEntity entity = GetCorrespondingSurfaceLineEntity(surfaceLine, context);
entity.Name = surfaceLine.Name;
entity.ReferenceLineIntersectionX = Convert.ToDecimal(surfaceLine.ReferenceLineIntersectionWorldPoint.X);
entity.ReferenceLineIntersectionY = Convert.ToDecimal(surfaceLine.ReferenceLineIntersectionWorldPoint.Y);
UpdateGeometry(surfaceLine, entity, registry);
UpdateCharacteristicPoints(surfaceLine, entity, registry);
registry.Register(entity, surfaceLine);
}
private static void UpdateGeometry(RingtoetsPipingSurfaceLine surfaceLine, SurfaceLineEntity entity, PersistenceRegistry registry)
{
if (HasGeometryChanges(surfaceLine, entity))
{
foreach (SurfaceLinePointEntity pointEntity in entity.SurfaceLinePointEntities.ToArray())
{
entity.SurfaceLinePointEntities.Remove(pointEntity);
}
UpdateGeometryPoints(surfaceLine, entity, registry);
}
else
{
var orderedPointEntities = entity.SurfaceLinePointEntities.OrderBy(pe => pe.Order).ToArray();
for (int i = 0; i < surfaceLine.Points.Length; i++)
{
registry.Register(orderedPointEntities[i], surfaceLine.Points[i]);
}
}
}
private static bool HasGeometryChanges(RingtoetsPipingSurfaceLine surfaceLine, SurfaceLineEntity entity)
{
if (surfaceLine.Points.Length != entity.SurfaceLinePointEntities.Count)
{
return true;
}
var existingSurfaceLinePointEntities = entity.SurfaceLinePointEntities.OrderBy(pe => pe.Order).ToArray();
for (int i = 0; i < surfaceLine.Points.Length; i++)
{
// Note: Point3D is immutable, therefore checking for identity is enough.
if (surfaceLine.Points[i].StorageId != existingSurfaceLinePointEntities[i].SurfaceLinePointEntityId)
{
return true;
}
}
return false;
}
private static void UpdateGeometryPoints(RingtoetsPipingSurfaceLine surfaceLine, SurfaceLineEntity entity, PersistenceRegistry registry)
{
int order = 0;
foreach (Point3D geometryPoint in surfaceLine.Points)
{
entity.SurfaceLinePointEntities.Add(geometryPoint.CreateSurfaceLinePointEntity(registry, order++));
}
}
private static void UpdateCharacteristicPoints(RingtoetsPipingSurfaceLine surfaceLine, SurfaceLineEntity entity, PersistenceRegistry registry)
{
CharacteristicPointEntity[] currentCharacteristicPointEntities = entity.SurfaceLinePointEntities
.SelectMany(pe => pe.CharacteristicPointEntities)
.ToArray();
UpdateCharacteristicPoint(surfaceLine.DikeToeAtRiver, CharacteristicPointType.DikeToeAtRiver,
currentCharacteristicPointEntities, registry);
UpdateCharacteristicPoint(surfaceLine.DikeToeAtPolder, CharacteristicPointType.DikeToeAtPolder,
currentCharacteristicPointEntities, registry);
UpdateCharacteristicPoint(surfaceLine.DitchDikeSide, CharacteristicPointType.DitchDikeSide,
currentCharacteristicPointEntities, registry);
UpdateCharacteristicPoint(surfaceLine.BottomDitchDikeSide, CharacteristicPointType.BottomDitchDikeSide,
currentCharacteristicPointEntities, registry);
UpdateCharacteristicPoint(surfaceLine.BottomDitchPolderSide, CharacteristicPointType.BottomDitchPolderSide,
currentCharacteristicPointEntities, registry);
UpdateCharacteristicPoint(surfaceLine.DitchPolderSide, CharacteristicPointType.DitchPolderSide,
currentCharacteristicPointEntities, registry);
}
private static void UpdateCharacteristicPoint(Point3D currentCharacteristicPoint, CharacteristicPointType type,
CharacteristicPointEntity[] currentCharacteristicPointEntities,
PersistenceRegistry registry)
{
short typeValue = (short)type;
CharacteristicPointEntity characteristicPointEntity = currentCharacteristicPointEntities
.FirstOrDefault(cpe => cpe.CharacteristicPointType == typeValue);
if (currentCharacteristicPoint == null && characteristicPointEntity != null)
{
characteristicPointEntity.SurfaceLinePointEntity = null;
}
else if (currentCharacteristicPoint != null)
{
SurfaceLinePointEntity geometryPointEntity = registry.GetSurfaceLinePoint(currentCharacteristicPoint);
if (characteristicPointEntity == null)
{
characteristicPointEntity = new CharacteristicPointEntity
{
CharacteristicPointType = typeValue
};
geometryPointEntity.CharacteristicPointEntities.Add(characteristicPointEntity);
}
else if (characteristicPointEntity.SurfaceLinePointEntity != geometryPointEntity)
{
characteristicPointEntity.SurfaceLinePointEntity = geometryPointEntity;
}
registry.Register(characteristicPointEntity, currentCharacteristicPoint);
}
}
///
/// Gets the from a
/// corresponding to an already saved instance.
///
/// The surface line.
/// The context.
/// The .
/// When no
/// can be found in that matches .
private static SurfaceLineEntity GetCorrespondingSurfaceLineEntity(RingtoetsPipingSurfaceLine surfaceLine, IRingtoetsEntities context)
{
try
{
return context.SurfaceLineEntities.Single(sle => sle.SurfaceLineEntityId == surfaceLine.StorageId);
}
catch (InvalidOperationException exception)
{
string message = string.Format(Resources.Error_Entity_Not_Found_0_1,
typeof(SurfaceLineEntity).Name,
surfaceLine.StorageId);
throw new EntityNotFoundException(message, exception);
}
}
}
}