// 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.Data.Entity;
using System.Diagnostics;
using System.Linq;
using Application.Ringtoets.Storage.Converters;
using Application.Ringtoets.Storage.DbContext;
using Application.Ringtoets.Storage.Exceptions;
using Application.Ringtoets.Storage.Properties;
using Core.Common.Base.Data;
using Ringtoets.Integration.Data;
namespace Application.Ringtoets.Storage.Persistors
{
///
/// Persistor for .
///
public class ProjectPersistor
{
private readonly DbSet projectEntitySet;
private readonly ProjectConverter converter;
private readonly Dictionary insertedList = new Dictionary();
private readonly ICollection modifiedList = new List();
private readonly AssessmentSectionPersistor assessmentSectionEntityPersistor;
///
/// Instantiate a new .
///
/// The storage context.
/// Thrown when is null.
public ProjectPersistor(IRingtoetsEntities ringtoetsContext)
{
if (ringtoetsContext == null)
{
throw new ArgumentNullException("ringtoetsContext");
}
projectEntitySet = ringtoetsContext.ProjectEntities;
converter = new ProjectConverter();
assessmentSectionEntityPersistor = new AssessmentSectionPersistor(ringtoetsContext);
}
///
/// Gets the only as from the sequence.
///
/// A new , loaded from the sequence, or null when not found.
/// Thrown when there are more than one elements in the sequence.
public Project GetEntityAsModel()
{
var entry = projectEntitySet.SingleOrDefault();
if (entry == null)
{
return null;
}
var project = converter.ConvertEntityToModel(entry);
var nrOfItems = entry.AssessmentSectionEntities.Count;
var assessmentSections = new object[nrOfItems];
foreach (var sectionEntity in entry.AssessmentSectionEntities)
{
assessmentSections[sectionEntity.Order] = assessmentSectionEntityPersistor.LoadModel(sectionEntity);
}
// Add to items sorted
foreach (var assessmentSection in assessmentSections)
{
project.Items.Add(assessmentSection);
}
return project;
}
///
/// Insert the , based upon the , in the sequence.
///
/// Execute afterwards to update the storage.
/// to be inserted in the sequence.
/// New instance of .
/// Thrown when is null.
/// The parentNavigationProperty is read-only.
public void InsertModel(Project project)
{
if (project == null)
{
throw new ArgumentNullException("project", @"Cannot update databaseSet when no project is set.");
}
var entity = new ProjectEntity();
projectEntitySet.Add(entity);
insertedList.Add(entity, project);
converter.ConvertModelToEntity(project, entity);
if (project.StorageId > 0)
{
modifiedList.Add(entity);
}
InsertChildren(project, entity);
}
///
/// Updates the , based upon the , in the sequence.
///
/// Execute afterwards to update the storage.
/// The to be saved in the storage.
/// The .
/// Thrown when is null.
/// Thrown when:
/// - is not found.
/// - More than one satisfies the condition in predicate.
///
/// The parentNavigationProperty is read-only.
public void UpdateModel(Project model)
{
if (model == null)
{
throw new ArgumentNullException("model", @"Cannot update databaseSet when no project is set.");
}
ProjectEntity entity;
try
{
entity = projectEntitySet.SingleOrDefault(db => db.ProjectEntityId == model.StorageId);
}
catch (InvalidOperationException exception)
{
throw new EntityNotFoundException(String.Format(Resources.Error_Entity_Not_Found_0_1, "ProjectEntity", model.StorageId), exception);
}
if (entity == null)
{
throw new EntityNotFoundException(String.Format(Resources.Error_Entity_Not_Found_0_1, "ProjectEntity", model.StorageId));
}
modifiedList.Add(entity);
converter.ConvertModelToEntity(model, entity);
UpdateChildren(model, entity);
}
///
/// Removes all entities from that are not marked as 'updated'.
///
public void RemoveUnModifiedEntries()
{
var untouchedList = projectEntitySet.ToList().Where(e => !modifiedList.Contains(e));
projectEntitySet.RemoveRange(untouchedList);
modifiedList.Clear();
}
///
/// Perform actions that can only be executed after has been called.
///
public void PerformPostSaveActions()
{
UpdateStorageIdsInModel();
assessmentSectionEntityPersistor.PerformPostSaveActions();
}
///
/// Updates the children of , in reference to , in the storage.
///
/// The of which children need to be updated.
/// Referenced .
private void UpdateChildren(Project project, ProjectEntity entity)
{
var order = 0;
foreach (var item in project.Items.Where(i => i is AssessmentSection).Cast())
{
assessmentSectionEntityPersistor.UpdateModel(entity.AssessmentSectionEntities, item, order);
order++;
}
assessmentSectionEntityPersistor.RemoveUnModifiedEntries(entity.AssessmentSectionEntities);
}
///
/// Inserts the children of , in reference to , in the storage.
///
/// The of which children need to be inserted.
/// Referenced .
private void InsertChildren(Project project, ProjectEntity entity)
{
var order = 0;
foreach (var item in project.Items.Where(i => i is AssessmentSection).Cast())
{
assessmentSectionEntityPersistor.InsertModel(entity.AssessmentSectionEntities, item, order);
order++;
}
assessmentSectionEntityPersistor.RemoveUnModifiedEntries(entity.AssessmentSectionEntities);
}
///
/// Updates the StorageId of each inserted to the
/// of the corresponding .
///
/// must have been called to update the ids.
private void UpdateStorageIdsInModel()
{
foreach (var entry in insertedList)
{
Debug.Assert(entry.Key.ProjectEntityId > 0,
"ProjectEntityId is not set. Have you called IRingtoetsEntities.SaveChanges?");
entry.Value.StorageId = entry.Key.ProjectEntityId;
}
insertedList.Clear();
}
}
}