// 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.Calculation; 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 calculationGroups = new Dictionary(new ReferenceEqualityComparer()); private readonly Dictionary pipingCalculations = 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()); private readonly Dictionary pipingProbabilityAssessmentInputs = 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 registered. /// Thrown when either: /// /// is null /// is null /// public void Register(CalculationGroupEntity entity, CalculationGroup model) { Register(calculationGroups, 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 registered. /// Thrown when either: /// /// is null /// is null /// public void Register(PipingCalculationEntity entity, PipingCalculationScenario model) { Register(pipingCalculations, 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(StochasticSoilModel model) { return ContainsValue(stochasticSoilModels, 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(StochasticSoilProfile model) { return ContainsValue(stochasticSoilProfiles, 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); } /// /// 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(HydraulicBoundaryLocation model) { return ContainsValue(hydraulicLocations, 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(RingtoetsPipingSurfaceLine model) { return ContainsValue(surfaceLines, model); } /// /// Obtains the which was registered for /// the given . /// /// The for which a read/update /// operation has been registered. /// The created . /// 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 StochasticSoilModelEntity Get(StochasticSoilModel model) { return Get(stochasticSoilModels, model); } /// /// Obtains the which was registered for /// the given . /// /// The for which a read/update /// operation has been registered. /// The created . /// 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 StochasticSoilProfileEntity Get(StochasticSoilProfile model) { return Get(stochasticSoilProfiles, 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); } /// /// Obtains the which was registered for the given /// . /// /// The for which a /// read/update operation has been registered. /// The constructed . /// Thrown when is null. /// Thrown when no create/update operation /// has been registered for . /// Use to find out /// whether a create/update operation has been registered for . internal SurfaceLineEntity Get(RingtoetsPipingSurfaceLine model) { return Get(surfaceLines, model); } /// /// Obtains the which was registered for the /// given . /// /// The for which a /// read/update operation has been registered. /// The constructed . /// Thrown when is null. /// Thrown when no create/update operation /// has been registered for . /// Use to find out /// whether a create/update operation has been registered for . internal HydraulicLocationEntity Get(HydraulicBoundaryLocation model) { return Get(hydraulicLocations, 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 . 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); } internal void Register(PipingFailureMechanismMetaEntity entity, PipingProbabilityAssessmentInput model) { Register(pipingProbabilityAssessmentInputs, 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 calculationGroups.Keys) { calculationGroups[entity].StorageId = entity.CalculationGroupEntityId; } foreach (var entity in pipingCalculations.Keys) { pipingCalculations[entity].StorageId = entity.PipingCalculationEntityId; } 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; } foreach (var entity in pipingProbabilityAssessmentInputs.Keys) { pipingProbabilityAssessmentInputs[entity].StorageId = entity.PipingFailureMechanismMetaEntityId; } // 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) { IList orphanedProjectEntities = new List(); foreach (ProjectEntity projectEntity in dbContext.ProjectEntities .Where(e => e.ProjectEntityId > 0)) { if (!projects.ContainsKey(projectEntity)) { orphanedProjectEntities.Add(projectEntity); } } dbContext.ProjectEntities.RemoveRange(orphanedProjectEntities); IList orphanedAssessmentSectionEntities = new List(); foreach (AssessmentSectionEntity assessmentSectionEntity in dbContext.AssessmentSectionEntities .Where(e => e.AssessmentSectionEntityId > 0)) { if (!assessmentSections.ContainsKey(assessmentSectionEntity)) { orphanedAssessmentSectionEntities.Add(assessmentSectionEntity); } } dbContext.AssessmentSectionEntities.RemoveRange(orphanedAssessmentSectionEntities); IList orphanedFailureMechanismEntities = new List(); foreach (FailureMechanismEntity failureMechanismEntity in dbContext.FailureMechanismEntities .Where(e => e.FailureMechanismEntityId > 0)) { if (!failureMechanisms.ContainsKey(failureMechanismEntity)) { orphanedFailureMechanismEntities.Add(failureMechanismEntity); } } dbContext.FailureMechanismEntities.RemoveRange(orphanedFailureMechanismEntities); IList orphanedFailureMechanismSectionEntities = new List(); foreach (FailureMechanismSectionEntity failureMechanismSectionEntity in dbContext.FailureMechanismSectionEntities .Where(e => e.FailureMechanismSectionEntityId > 0)) { if (!failureMechanismSections.ContainsKey(failureMechanismSectionEntity)) { orphanedFailureMechanismSectionEntities.Add(failureMechanismSectionEntity); } } dbContext.FailureMechanismSectionEntities.RemoveRange(orphanedFailureMechanismSectionEntities); IList orphanedHydraulicLocationEntities = new List(); foreach (HydraulicLocationEntity hydraulicLocationEntity in dbContext.HydraulicLocationEntities .Where(e => e.HydraulicLocationEntityId > 0)) { if (!hydraulicLocations.ContainsKey(hydraulicLocationEntity)) { orphanedHydraulicLocationEntities.Add(hydraulicLocationEntity); } } dbContext.HydraulicLocationEntities.RemoveRange(orphanedHydraulicLocationEntities); IList orphanedCalculationGroupEntities = new List(); foreach (CalculationGroupEntity calculationGroupEntity in dbContext.CalculationGroupEntities .Where(e => e.CalculationGroupEntityId > 0)) { if (!calculationGroups.ContainsKey(calculationGroupEntity)) { orphanedCalculationGroupEntities.Add(calculationGroupEntity); } } dbContext.CalculationGroupEntities.RemoveRange(orphanedCalculationGroupEntities); IList orphanedPipingCalculationEntities = new List(); foreach (PipingCalculationEntity pipingCalculationEntity in dbContext.PipingCalculationEntities .Where(e => e.PipingCalculationEntityId > 0)) { if (!pipingCalculations.ContainsKey(pipingCalculationEntity)) { orphanedPipingCalculationEntities.Add(pipingCalculationEntity); } } dbContext.PipingCalculationEntities.RemoveRange(orphanedPipingCalculationEntities); IList orphanedStochasticSoilModelEntities = new List(); foreach (StochasticSoilModelEntity stochasticSoilModelEntity in dbContext.StochasticSoilModelEntities .Where(e => e.StochasticSoilModelEntityId > 0)) { if (!stochasticSoilModels.ContainsKey(stochasticSoilModelEntity)) { orphanedStochasticSoilModelEntities.Add(stochasticSoilModelEntity); } } dbContext.StochasticSoilModelEntities.RemoveRange(orphanedStochasticSoilModelEntities); IList orphanedStochasticSoilProfileEntities = new List(); foreach (StochasticSoilProfileEntity stochasticSoilProfileEntity in dbContext.StochasticSoilProfileEntities .Where(e => e.StochasticSoilProfileEntityId > 0)) { if (!stochasticSoilProfiles.ContainsKey(stochasticSoilProfileEntity)) { orphanedStochasticSoilProfileEntities.Add(stochasticSoilProfileEntity); } } dbContext.StochasticSoilProfileEntities.RemoveRange(orphanedStochasticSoilProfileEntities); IList orphanedSoilProfileEntities = new List(); foreach (SoilProfileEntity soilProfileEntity in dbContext.SoilProfileEntities .Where(e => e.SoilProfileEntityId > 0)) { if (!soilProfiles.ContainsKey(soilProfileEntity)) { orphanedSoilProfileEntities.Add(soilProfileEntity); } } dbContext.SoilProfileEntities.RemoveRange(orphanedSoilProfileEntities); IList orphanedSoilLayerEntities = new List(); foreach (SoilLayerEntity soilLayerEntity in dbContext.SoilLayerEntities .Where(e => e.SoilLayerEntityId > 0)) { if (!soilLayers.ContainsKey(soilLayerEntity)) { orphanedSoilLayerEntities.Add(soilLayerEntity); } } dbContext.SoilLayerEntities.RemoveRange(orphanedSoilLayerEntities); IList orphanedSurfaceLineEntities = new List(); foreach (SurfaceLineEntity surfaceLineEntity in dbContext.SurfaceLineEntities .Where(e => e.SurfaceLineEntityId > 0)) { if (!surfaceLines.ContainsKey(surfaceLineEntity)) { orphanedSurfaceLineEntities.Add(surfaceLineEntity); } } dbContext.SurfaceLineEntities.RemoveRange(orphanedSurfaceLineEntities); IList orphanedSurfaceLinePointEntities = new List(); foreach (SurfaceLinePointEntity surfaceLinePointEntity in dbContext.SurfaceLinePointEntities .Where(e => e.SurfaceLinePointEntityId > 0)) { if (!surfaceLinePoints.ContainsKey(surfaceLinePointEntity)) { orphanedSurfaceLinePointEntities.Add(surfaceLinePointEntity); } } dbContext.SurfaceLinePointEntities.RemoveRange(orphanedSurfaceLinePointEntities); IList orphanedCharacteristicPointEntities = new List(); foreach (CharacteristicPointEntity characteristicPointEntity in dbContext.CharacteristicPointEntities .Where(e => e.CharacteristicPointEntityId > 0)) { if (!characteristicPoints.ContainsKey(characteristicPointEntity)) { orphanedCharacteristicPointEntities.Add(characteristicPointEntity); } } dbContext.CharacteristicPointEntities.RemoveRange(orphanedCharacteristicPointEntities); IList orphanedPipingFailureMechanismMetaEntities = new List(); foreach (PipingFailureMechanismMetaEntity pipingFailureMechanismMetaEntity in dbContext.PipingFailureMechanismMetaEntities .Where(e => e.PipingFailureMechanismMetaEntityId > 0)) { if (!pipingProbabilityAssessmentInputs.ContainsKey(pipingFailureMechanismMetaEntity)) { orphanedPipingFailureMechanismMetaEntities.Add(pipingFailureMechanismMetaEntity); } } dbContext.PipingFailureMechanismMetaEntities.RemoveRange(orphanedPipingFailureMechanismMetaEntities); } 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)); } } }