// 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.Linq; using Application.Ringtoets.Storage.DbContext; using Core.Common.Base.Data; using Core.Common.Base.Geometry; using Core.Common.Utils; using Ringtoets.Common.Data.FailureMechanism; using Ringtoets.HydraRing.Data; using Ringtoets.Integration.Data; using Ringtoets.Piping.Data; using Ringtoets.Piping.Primitives; namespace Application.Ringtoets.Storage.Create { /// /// This class can be used to keep track of create and update operations on a database. /// This information can be used to reuse objects. When all operations have been performed, /// then the collected information can be used to transfer the ids assigned to the created /// database instances back to the data model or to clean up orphans. /// internal class PersistenceRegistry { private readonly Dictionary projects = new Dictionary(new ReferenceEqualityComparer()); private readonly Dictionary assessmentSections = new Dictionary(new ReferenceEqualityComparer()); private readonly Dictionary failureMechanisms = new Dictionary(new ReferenceEqualityComparer()); private readonly Dictionary failureMechanismSections = new Dictionary(); private readonly Dictionary hydraulicLocations = new Dictionary(new ReferenceEqualityComparer()); private readonly Dictionary stochasticSoilModels = new Dictionary(new ReferenceEqualityComparer()); private readonly Dictionary stochasticSoilProfiles = new Dictionary(new ReferenceEqualityComparer()); private readonly Dictionary soilProfiles = new Dictionary(new ReferenceEqualityComparer()); private readonly Dictionary soilLayers = new Dictionary(new ReferenceEqualityComparer()); private readonly Dictionary surfaceLines = new Dictionary(new ReferenceEqualityComparer()); private readonly Dictionary surfaceLinePoints = new Dictionary(new ReferenceEqualityComparer()); private readonly Dictionary characteristicPoints = new Dictionary(new ReferenceEqualityComparer()); /// /// Registers a create or update operation for and the /// that was constructed with the information. /// /// The that was registered. /// The which needed to registered. /// Thrown when either: /// /// is null /// is null /// public void Register(FailureMechanismSectionEntity entity, FailureMechanismSection model) { Register(failureMechanismSections, entity, model); } /// /// Registers a create or update operation for and the /// that was constructed with the information. /// /// The that was registered. /// The which needed to be registered. /// Thrown when either: /// /// is null /// is null /// internal void Register(ProjectEntity entity, Project model) { Register(projects, entity, model); } /// /// Registers a create or update operation for and the /// that was constructed with the information. /// /// The that was registered. /// The which needed to be registered. /// Thrown when either: /// /// is null /// is null /// internal void Register(AssessmentSectionEntity entity, AssessmentSection model) { Register(assessmentSections, entity, model); } /// /// Registers a create or update operation for and the /// that was constructed with the information. /// /// The that was registered. /// The which needed to be registered. /// Thrown when either: /// /// is null /// is null /// internal void Register(HydraulicLocationEntity entity, HydraulicBoundaryLocation model) { Register(hydraulicLocations, entity, model); } /// /// Registers a create or update operation for and the /// that was constructed with the information. /// /// The that was registered. /// The which needed to be registered. /// Thrown when either: /// /// is null /// is null /// internal void Register(FailureMechanismEntity entity, IFailureMechanism model) { Register(failureMechanisms, entity, model); } /// /// Registers a create or update operation for and the /// that was constructed with the information. /// /// The that was registered. /// The which needed to be registered. /// Thrown when either: /// /// is null /// is null /// internal void Register(StochasticSoilModelEntity entity, StochasticSoilModel model) { Register(stochasticSoilModels, entity, model); } /// /// Registers a create or update operation for and the /// that was constructed with the information. /// /// The that was registered. /// The which needed to be registered. /// Thrown when either: /// /// is null /// is null /// internal void Register(StochasticSoilProfileEntity entity, StochasticSoilProfile model) { Register(stochasticSoilProfiles, entity, model); } /// /// Registers a create or update operation for and the /// that was constructed with the information. /// /// The that was registered. /// The which needed to be registered. /// Thrown when either: /// /// is null /// is null /// internal void Register(SoilProfileEntity entity, PipingSoilProfile model) { Register(soilProfiles, entity, model); } /// /// Registers a create or update operation for and the /// that was constructed with the information. /// /// The that was registered. /// The which needed to be registered. /// Thrown when either: /// /// is null /// is null /// internal void Register(SoilLayerEntity entity, PipingSoilLayer model) { Register(soilLayers, entity, model); } /// /// Checks whether a create or update operations has been registered for the given /// . /// /// The to check for. /// true if the was created before, false otherwise. /// Thrown when is null. internal bool Contains(PipingSoilProfile model) { return ContainsValue(soilProfiles, model); } /// /// Obtains the which was registered for the given /// . /// /// The for which a read operation has been registered. /// The constructed . /// Thrown when is null. /// Thrown when no create operation /// has been registered for . /// Use to find out whether a create operation has /// been registered for . internal SoilProfileEntity Get(PipingSoilProfile model) { return Get(soilProfiles, model); } /// /// Registers a create or update operation for and the /// that was constructed with the information. /// /// The that was registered. /// The which needed /// to be registered. /// Thrown when either: /// /// is null /// is null /// internal void Register(SurfaceLineEntity entity, RingtoetsPipingSurfaceLine model) { Register(surfaceLines, entity, model); } /// /// Registers a create or update operation for and the /// that was constructed with the information. /// /// The that was registered. /// The surfaceline geometry corresponding /// the registered database entity. /// Thrown when either: /// /// is null /// is null /// internal void Register(SurfaceLinePointEntity entity, Point3D model) { Register(surfaceLinePoints, entity, model); } /// /// Obtains the which was registered for the /// given . /// /// The surfaceline geometry for which /// a create or update operation has been registered. /// Thrown when is null. /// Thrown when no create operation /// has been registered for . /// Use to find out whether a create or update /// operation has been registered for . internal SurfaceLinePointEntity GetSurfaceLinePoint(Point3D model) { return Get(surfaceLinePoints, model); } /// /// Registers a create or update operation for and the /// that was constructed with the information. /// /// The that was registered. /// The surfaceline geometry corresponding /// to the characteristic point data being registered. /// Thrown when either: /// /// is null /// is null /// internal void Register(CharacteristicPointEntity entity, Point3D model) { Register(characteristicPoints, entity, model); } /// /// Transfer ids from the created entities to the domain model objects' property. /// internal void TransferIds() { foreach (var entity in projects.Keys) { projects[entity].StorageId = entity.ProjectEntityId; } foreach (var entity in failureMechanisms.Keys) { failureMechanisms[entity].StorageId = entity.FailureMechanismEntityId; } foreach (var entity in failureMechanismSections.Keys) { failureMechanismSections[entity].StorageId = entity.FailureMechanismSectionEntityId; } foreach (var entity in assessmentSections.Keys) { assessmentSections[entity].StorageId = entity.AssessmentSectionEntityId; } foreach (var entity in hydraulicLocations.Keys) { hydraulicLocations[entity].StorageId = entity.HydraulicLocationEntityId; } foreach (var entity in stochasticSoilModels.Keys) { stochasticSoilModels[entity].StorageId = entity.StochasticSoilModelEntityId; } foreach (var entity in stochasticSoilProfiles.Keys) { stochasticSoilProfiles[entity].StorageId = entity.StochasticSoilProfileEntityId; } foreach (var entity in soilProfiles.Keys) { soilProfiles[entity].StorageId = entity.SoilProfileEntityId; } foreach (var entity in soilLayers.Keys) { soilLayers[entity].StorageId = entity.SoilLayerEntityId; } foreach (var entity in surfaceLines.Keys) { surfaceLines[entity].StorageId = entity.SurfaceLineEntityId; } foreach (var entity in surfaceLinePoints.Keys) { surfaceLinePoints[entity].StorageId = entity.SurfaceLinePointEntityId; } // CharacteristicPoints do not really have a 'identity' within the object-model. // As such, no need to copy StorageId. This is already covered by surfaceLinePoints. } /// /// Removes all the entities for which no update operation was registered from the . /// /// The from which to remove the entities. internal void RemoveUntouched(IRingtoetsEntities dbContext) { var projectEntities = dbContext.ProjectEntities; var projectEntitiesToRemove = projectEntities .Local .Where(entity => entity.ProjectEntityId > 0) .Except(projects.Keys); projectEntities.RemoveRange(projectEntitiesToRemove); var assessmentSectionEntities = dbContext.AssessmentSectionEntities; var assessmentSectionEntitiesToRemove = assessmentSectionEntities .Local .Where(entity => entity.AssessmentSectionEntityId > 0) .Except(assessmentSections.Keys); assessmentSectionEntities.RemoveRange(assessmentSectionEntitiesToRemove); var failureMechanismEntities = dbContext.FailureMechanismEntities; var failureMechanismEntitiesToRemove = failureMechanismEntities .Local .Where(entity => entity.FailureMechanismEntityId > 0) .Except(failureMechanisms.Keys); failureMechanismEntities.RemoveRange(failureMechanismEntitiesToRemove); var failureMechanismSectionEntities = dbContext.FailureMechanismSectionEntities; var failureMechanismSectionEntitiesToRemove = failureMechanismSectionEntities .Local .Where(entity => entity.FailureMechanismSectionEntityId > 0) .Except(failureMechanismSections.Keys); failureMechanismSectionEntities.RemoveRange(failureMechanismSectionEntitiesToRemove); var hydraulicLocationEntities = dbContext.HydraulicLocationEntities; var hydraulicLocationEntitiesToRemove = hydraulicLocationEntities .Local .Where(entity => entity.HydraulicLocationEntityId > 0) .Except(hydraulicLocations.Keys); hydraulicLocationEntities.RemoveRange(hydraulicLocationEntitiesToRemove); var stochasticSoilModelEntities = dbContext.StochasticSoilModelEntities; var stochasticSoilModelEntitiesToRemove = stochasticSoilModelEntities .Local .Where(entity => entity.StochasticSoilModelEntityId > 0) .Except(stochasticSoilModels.Keys); stochasticSoilModelEntities.RemoveRange(stochasticSoilModelEntitiesToRemove); var stochasticSoilProfileEntities = dbContext.StochasticSoilProfileEntities; var stochasticSoilProfileEntitiesToRemove = stochasticSoilProfileEntities .Local .Where(entity => entity.StochasticSoilProfileEntityId > 0) .Except(stochasticSoilProfiles.Keys); stochasticSoilProfileEntities.RemoveRange(stochasticSoilProfileEntitiesToRemove); var soilProfileEntities = dbContext.SoilProfileEntities; var soilProfileEntitiesToRemove = soilProfileEntities .Local .Where(entity => entity.SoilProfileEntityId > 0) .Except(soilProfiles.Keys); soilProfileEntities.RemoveRange(soilProfileEntitiesToRemove); var soilLayerEntities = dbContext.SoilLayerEntities; var soilLayerEntitiesToRemove = soilLayerEntities .Local .Where(entity => entity.SoilLayerEntityId > 0) .Except(soilLayers.Keys); soilLayerEntities.RemoveRange(soilLayerEntitiesToRemove); var surfaceLineEntities = dbContext.SurfaceLineEntities; var surfaceLineEntitiesToRemove = surfaceLineEntities .Local .Where(entity => entity.SurfaceLineEntityId > 0) .Except(surfaceLines.Keys); surfaceLineEntities.RemoveRange(surfaceLineEntitiesToRemove); var surfaceLinePointEntities = dbContext.SurfaceLinePointEntities; var surfaceLinePointEntitiesToRemove = surfaceLinePointEntities .Local .Where(entity => entity.SurfaceLinePointEntityId > 0) .Except(surfaceLinePoints.Keys); surfaceLinePointEntities.RemoveRange(surfaceLinePointEntitiesToRemove); var characteristicPointEntities = dbContext.CharacteristicPointEntities; var characteristicPointEntitiesToRemove = characteristicPointEntities .Local .Where(entity => entity.CharacteristicPointEntityId > 0) .Except(characteristicPoints.Keys); characteristicPointEntities.RemoveRange(characteristicPointEntitiesToRemove); } private bool ContainsValue(Dictionary collection, U model) { if (model == null) { throw new ArgumentNullException("model"); } return collection.ContainsValue(model); } private void Register(Dictionary collection, T entity, U model) { if (entity == null) { throw new ArgumentNullException("entity"); } if (model == null) { throw new ArgumentNullException("model"); } collection[entity] = model; } private T Get(Dictionary collection, U model) { if (model == null) { throw new ArgumentNullException("model"); } return collection.Keys.Single(k => ReferenceEquals(collection[k], model)); } } }