// 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));
}
}
}