// 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, CreateConversionCollector collector, IRingtoetsEntities context) { if (collector == null) { throw new ArgumentNullException("collector"); } 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, context, collector); UpdateCharacteristicPoints(surfaceLine, entity, collector); collector.Create(entity, surfaceLine); } private static void UpdateGeometry(RingtoetsPipingSurfaceLine surfaceLine, SurfaceLineEntity entity, IRingtoetsEntities context, CreateConversionCollector collector) { if (HasGeometryChanges(surfaceLine, entity)) { context.SurfaceLinePointEntities.RemoveRange(entity.SurfaceLinePointEntities); UpdateGeometryPoints(surfaceLine, entity, collector); } else { var orderedPointEntities = context.SurfaceLinePointEntities.OrderBy(pe => pe.Order).ToArray(); for (int i = 0; i < surfaceLine.Points.Length; i++) { collector.Create(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, CreateConversionCollector collector) { int order = 0; foreach (Point3D geometryPoint in surfaceLine.Points) { entity.SurfaceLinePointEntities.Add(geometryPoint.CreateSurfaceLinePoint(collector, order++)); } } private static void UpdateCharacteristicPoints(RingtoetsPipingSurfaceLine surfaceLine, SurfaceLineEntity entity, CreateConversionCollector collector) { CharacteristicPointEntity[] currentCharacteristicPointEntities = entity.SurfaceLinePointEntities .SelectMany(pe => pe.CharacteristicPointEntities) .ToArray(); UpdateCharacteristicPoint(surfaceLine.DikeToeAtRiver, CharacteristicPointType.DikeToeAtRiver, currentCharacteristicPointEntities, collector); UpdateCharacteristicPoint(surfaceLine.DikeToeAtPolder, CharacteristicPointType.DikeToeAtPolder, currentCharacteristicPointEntities, collector); UpdateCharacteristicPoint(surfaceLine.DitchDikeSide, CharacteristicPointType.DitchDikeSide, currentCharacteristicPointEntities, collector); UpdateCharacteristicPoint(surfaceLine.BottomDitchDikeSide, CharacteristicPointType.BottomDitchDikeSide, currentCharacteristicPointEntities, collector); UpdateCharacteristicPoint(surfaceLine.BottomDitchPolderSide, CharacteristicPointType.BottomDitchPolderSide, currentCharacteristicPointEntities, collector); UpdateCharacteristicPoint(surfaceLine.DitchPolderSide, CharacteristicPointType.DitchPolderSide, currentCharacteristicPointEntities, collector); } private static void UpdateCharacteristicPoint(Point3D currentCharacteristicPoint, CharacteristicPointType type, CharacteristicPointEntity[] currentCharacteristicPointEntities, CreateConversionCollector collector) { 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 = collector.GetSurfaceLinePoint(currentCharacteristicPoint); if (characteristicPointEntity == null) { geometryPointEntity.CharacteristicPointEntities.Add(new CharacteristicPointEntity { CharacteristicPointType = typeValue }); } else if (characteristicPointEntity.SurfaceLinePointEntity != geometryPointEntity) { characteristicPointEntity.SurfaceLinePointEntity = geometryPointEntity; collector.Create(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); } } } }