Index: Application/Ringtoets/src/Application.Ringtoets.Storage/Application.Ringtoets.Storage.csproj =================================================================== diff -u -r7c766c291e763a54ef8ce4e2b9cadabda9e8296d -ra760d63747f5c44e99f4e747ace1b4e51c040362 --- Application/Ringtoets/src/Application.Ringtoets.Storage/Application.Ringtoets.Storage.csproj (.../Application.Ringtoets.Storage.csproj) (revision 7c766c291e763a54ef8ce4e2b9cadabda9e8296d) +++ Application/Ringtoets/src/Application.Ringtoets.Storage/Application.Ringtoets.Storage.csproj (.../Application.Ringtoets.Storage.csproj) (revision a760d63747f5c44e99f4e747ace1b4e51c040362) @@ -53,6 +53,7 @@ Properties\GlobalAssembly.cs + Index: Application/Ringtoets/src/Application.Ringtoets.Storage/Create/CalculationGroupCreateExtensions.cs =================================================================== diff -u --- Application/Ringtoets/src/Application.Ringtoets.Storage/Create/CalculationGroupCreateExtensions.cs (revision 0) +++ Application/Ringtoets/src/Application.Ringtoets.Storage/Create/CalculationGroupCreateExtensions.cs (revision a760d63747f5c44e99f4e747ace1b4e51c040362) @@ -0,0 +1,76 @@ +// 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 Application.Ringtoets.Storage.DbContext; + +using Ringtoets.Common.Data.Calculation; + +namespace Application.Ringtoets.Storage.Create +{ + /// + /// Extension methods for related to creating an . + /// + internal static class CalculationGroupCreateExtensions + { + /// + /// Creates a based on the information of the . + /// + /// The calculation group to create a database entity for. + /// The object keeping track of create operations. + /// The index at which resides within its parent. + /// A new . + /// Thrown when is null. + internal static CalculationGroupEntity Create(this CalculationGroup group, PersistenceRegistry registry, int order) + { + if (registry == null) + { + throw new ArgumentNullException("registry"); + } + + var entity = new CalculationGroupEntity + { + Name = group.Name, + IsEditable = group.IsNameEditable ? (byte)1 : (byte)0, + Order = order + }; + CreateChildElements(group, entity, registry); + + registry.Register(entity, group); + return entity; + } + + private static void CreateChildElements(CalculationGroup parentGroup, CalculationGroupEntity entity, PersistenceRegistry registry) + { + for (int i = 0; i < parentGroup.Children.Count; i++) + { + ICalculationBase calculationBase = parentGroup.Children[i]; + + var childGroup = calculationBase as CalculationGroup; + if (childGroup != null) + { + entity.CalculationGroupEntity1.Add(childGroup.Create(registry, i)); + } + } + } + } +} \ No newline at end of file Index: Application/Ringtoets/src/Application.Ringtoets.Storage/Create/PersistenceRegistry.cs =================================================================== diff -u -r71123d9c364c97a5ef2eec81acd1bf877a1297b0 -ra760d63747f5c44e99f4e747ace1b4e51c040362 --- Application/Ringtoets/src/Application.Ringtoets.Storage/Create/PersistenceRegistry.cs (.../PersistenceRegistry.cs) (revision 71123d9c364c97a5ef2eec81acd1bf877a1297b0) +++ Application/Ringtoets/src/Application.Ringtoets.Storage/Create/PersistenceRegistry.cs (.../PersistenceRegistry.cs) (revision a760d63747f5c44e99f4e747ace1b4e51c040362) @@ -29,6 +29,7 @@ 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; @@ -50,6 +51,7 @@ 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 stochasticSoilModels = new Dictionary(new ReferenceEqualityComparer()); private readonly Dictionary stochasticSoilProfiles = new Dictionary(new ReferenceEqualityComparer()); private readonly Dictionary soilProfiles = new Dictionary(new ReferenceEqualityComparer()); @@ -78,6 +80,22 @@ /// 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 be registered. /// Thrown when either: @@ -327,6 +345,11 @@ hydraulicLocations[entity].StorageId = entity.HydraulicLocationEntityId; } + foreach (var entity in calculationGroups.Keys) + { + calculationGroups[entity].StorageId = entity.CalculationGroupEntityId; + } + foreach (var entity in stochasticSoilModels.Keys) { stochasticSoilModels[entity].StorageId = entity.StochasticSoilModelEntityId; @@ -402,6 +425,13 @@ .Except(hydraulicLocations.Keys); hydraulicLocationEntities.RemoveRange(hydraulicLocationEntitiesToRemove); + var calculationGroupEntities = dbContext.CalculationGroupEntities; + var calculationGroupEntitiesToRemove = calculationGroupEntities + .Local + .Where(entity => entity.CalculationGroupEntityId > 0) + .Except(calculationGroups.Keys); + calculationGroupEntities.RemoveRange(calculationGroupEntitiesToRemove); + var stochasticSoilModelEntities = dbContext.StochasticSoilModelEntities; var stochasticSoilModelEntitiesToRemove = stochasticSoilModelEntities .Local Index: Application/Ringtoets/test/Application.Ringtoets.Storage.Test/Application.Ringtoets.Storage.Test.csproj =================================================================== diff -u -r219f8633c1b5b24f9e9aec3e903734fa94775f0e -ra760d63747f5c44e99f4e747ace1b4e51c040362 --- Application/Ringtoets/test/Application.Ringtoets.Storage.Test/Application.Ringtoets.Storage.Test.csproj (.../Application.Ringtoets.Storage.Test.csproj) (revision 219f8633c1b5b24f9e9aec3e903734fa94775f0e) +++ Application/Ringtoets/test/Application.Ringtoets.Storage.Test/Application.Ringtoets.Storage.Test.csproj (.../Application.Ringtoets.Storage.Test.csproj) (revision a760d63747f5c44e99f4e747ace1b4e51c040362) @@ -81,6 +81,7 @@ + Index: Application/Ringtoets/test/Application.Ringtoets.Storage.Test/Create/CalculationGroupCreateExtensionsTest.cs =================================================================== diff -u --- Application/Ringtoets/test/Application.Ringtoets.Storage.Test/Create/CalculationGroupCreateExtensionsTest.cs (revision 0) +++ Application/Ringtoets/test/Application.Ringtoets.Storage.Test/Create/CalculationGroupCreateExtensionsTest.cs (revision a760d63747f5c44e99f4e747ace1b4e51c040362) @@ -0,0 +1,128 @@ +// 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 NUnit.Framework; + +using Ringtoets.Common.Data.Calculation; + +namespace Application.Ringtoets.Storage.Test.Create +{ + [TestFixture] + public class CalculationGroupCreateExtensionsTest + { + [Test] + public void Create_RegistryIsNull_ThrowArgumentNullException() + { + // Setup + var group = new CalculationGroup(); + + // Call + TestDelegate call = () => group.Create(null, 0); + + // Assert + string paramName = Assert.Throws(call).ParamName; + Assert.AreEqual("registry", paramName); + } + + [Test] + [TestCase(true, 0)] + [TestCase(false, 123)] + public void Create_GroupWithoutChildren_CreateEntity(bool isNameEditable, int order) + { + // Setup + const string name = "blaballab"; + var group = new CalculationGroup(name, isNameEditable); + + var registry = new PersistenceRegistry(); + + // Call + CalculationGroupEntity entity = group.Create(registry, order); + + // Assert + Assert.AreEqual(name, entity.Name); + byte expectedIsEditableValue = isNameEditable ? (byte)1 : (byte)0; + Assert.AreEqual(expectedIsEditableValue, entity.IsEditable); + Assert.AreEqual(order, entity.Order); + + CollectionAssert.IsEmpty(entity.CalculationGroupEntity1); + Assert.IsNull(entity.FailureMechanismEntity); + Assert.IsNull(entity.ParentCalculationGroupEntityId); + } + + [Test] + public void Create_GroupWithChildren_CreateEntities() + { + // Setup + const string name = "blaballab"; + var group = new CalculationGroup(name, true); + group.Children.Add(new CalculationGroup("A", true) + { + Children = + { + new CalculationGroup("AA", false), + new CalculationGroup("AB", true) + } + }); + group.Children.Add(new CalculationGroup("B", false)); + + var registry = new PersistenceRegistry(); + + // Call + CalculationGroupEntity entity = group.Create(registry, 0); + + // Assert + Assert.AreEqual(name, entity.Name); + Assert.AreEqual(1, entity.IsEditable); + Assert.AreEqual(0, entity.Order); + + CalculationGroupEntity[] childGroupEntities = entity.CalculationGroupEntity1.ToArray(); + Assert.AreEqual(2, childGroupEntities.Length); + + CalculationGroupEntity childEntity1 = childGroupEntities[0]; + Assert.AreEqual("A", childEntity1.Name); + Assert.AreEqual(1, childEntity1.IsEditable); + Assert.AreEqual(0, childEntity1.Order); + Assert.AreEqual(2, childEntity1.CalculationGroupEntity1.Count); + CalculationGroupEntity childEntity1ChildEntity1 = childEntity1.CalculationGroupEntity1.ElementAt(0); + Assert.AreEqual("AA", childEntity1ChildEntity1.Name); + Assert.AreEqual(0, childEntity1ChildEntity1.IsEditable); + Assert.AreEqual(0, childEntity1ChildEntity1.Order); + CollectionAssert.IsEmpty(childEntity1ChildEntity1.CalculationGroupEntity1); + CalculationGroupEntity childEntity1ChildEntity2 = childEntity1.CalculationGroupEntity1.ElementAt(1); + Assert.AreEqual("AB", childEntity1ChildEntity2.Name); + Assert.AreEqual(1, childEntity1ChildEntity2.IsEditable); + Assert.AreEqual(1, childEntity1ChildEntity2.Order); + CollectionAssert.IsEmpty(childEntity1ChildEntity2.CalculationGroupEntity1); + + CalculationGroupEntity childEntity2 = childGroupEntities[1]; + Assert.AreEqual("B", childEntity2.Name); + Assert.AreEqual(0, childEntity2.IsEditable); + Assert.AreEqual(1, childEntity2.Order); + CollectionAssert.IsEmpty(childEntity2.CalculationGroupEntity1); + } + } +} \ No newline at end of file Index: Application/Ringtoets/test/Application.Ringtoets.Storage.Test/Create/PersistenceRegistryTest.cs =================================================================== diff -u -r71123d9c364c97a5ef2eec81acd1bf877a1297b0 -ra760d63747f5c44e99f4e747ace1b4e51c040362 --- Application/Ringtoets/test/Application.Ringtoets.Storage.Test/Create/PersistenceRegistryTest.cs (.../PersistenceRegistryTest.cs) (revision 71123d9c364c97a5ef2eec81acd1bf877a1297b0) +++ Application/Ringtoets/test/Application.Ringtoets.Storage.Test/Create/PersistenceRegistryTest.cs (.../PersistenceRegistryTest.cs) (revision a760d63747f5c44e99f4e747ace1b4e51c040362) @@ -31,6 +31,7 @@ using NUnit.Framework; using Rhino.Mocks; using Ringtoets.Common.Data.AssessmentSection; +using Ringtoets.Common.Data.Calculation; using Ringtoets.Common.Data.FailureMechanism; using Ringtoets.HydraRing.Data; using Ringtoets.Integration.Data; @@ -311,6 +312,34 @@ } [Test] + public void Register_WithNullCalculationGroupEntity_ThrowsArgumentNullException() + { + // Setup + var collector = new PersistenceRegistry(); + + // Call + TestDelegate test = () => collector.Register(null, new CalculationGroup()); + + // Assert + var paramName = Assert.Throws(test).ParamName; + Assert.AreEqual("entity", paramName); + } + + [Test] + public void Register_WithNullCalculationGroup_ThrowsArgumentNullException() + { + // Setup + var collector = new PersistenceRegistry(); + + // Call + TestDelegate test = () => collector.Register(new CalculationGroupEntity(), null); + + // Assert + var paramName = Assert.Throws(test).ParamName; + Assert.AreEqual("model", paramName); + } + + [Test] public void Register_WithNullStochasticSoilModelEntity_ThrowsArgumentNullException() { // Setup @@ -609,6 +638,27 @@ } [Test] + public void TransferId_WithCalculationGroupEntityAdded_EqualCalculationGroupEntityIdAndCalculationGroupStorageId() + { + // Setup + var collector = new PersistenceRegistry(); + + long storageId = new Random(21).Next(1, 4000); + var entity = new CalculationGroupEntity + { + CalculationGroupEntityId = storageId + }; + var model = new CalculationGroup(); + collector.Register(entity, model); + + // Call + collector.TransferIds(); + + // Assert + Assert.AreEqual(storageId, model.StorageId); + } + + [Test] public void TransferId_WithStochasticSoilModelEntityAdded_EqualStochasticSoilModelEntityIdAndStochasticSoilModelStorageId() { // Setup @@ -905,6 +955,39 @@ } [Test] + public void RemoveUntouched_CalculationGroupEntity_OrphanedEntityIsRemovedFromRingtoetsEntities() + { + // Setup + var mocks = new MockRepository(); + IRingtoetsEntities dbContext = RingtoetsEntitiesHelper.Create(mocks); + mocks.ReplayAll(); + + var orphanedEntity = new CalculationGroupEntity + { + CalculationGroupEntityId = 1 + }; + var persistentEntity = new CalculationGroupEntity + { + CalculationGroupEntityId = 2 + }; + dbContext.CalculationGroupEntities.Add(orphanedEntity); + dbContext.CalculationGroupEntities.Add(persistentEntity); + + var calculationGroup = new CalculationGroup{ StorageId = persistentEntity.CalculationGroupEntityId }; + + var collector = new PersistenceRegistry(); + collector.Register(persistentEntity, calculationGroup); + + // Call + collector.RemoveUntouched(dbContext); + + // Assert + Assert.AreEqual(1, dbContext.CalculationGroupEntities.Count()); + CollectionAssert.Contains(dbContext.CalculationGroupEntities, persistentEntity); + mocks.VerifyAll(); + } + + [Test] public void RemoveUntouched_StochasticSoilModelEntity_OrphanedEntityIsRemovedFromRingtoetsEntities() { // Setup @@ -1151,6 +1234,5 @@ } #endregion - } } \ No newline at end of file Index: Ringtoets/Common/src/Ringtoets.Common.Data/Calculation/CalculationGroup.cs =================================================================== diff -u -rfff12e249602fb700b2854c14a3b7cdd0b73c023 -ra760d63747f5c44e99f4e747ace1b4e51c040362 --- Ringtoets/Common/src/Ringtoets.Common.Data/Calculation/CalculationGroup.cs (.../CalculationGroup.cs) (revision fff12e249602fb700b2854c14a3b7cdd0b73c023) +++ Ringtoets/Common/src/Ringtoets.Common.Data/Calculation/CalculationGroup.cs (.../CalculationGroup.cs) (revision a760d63747f5c44e99f4e747ace1b4e51c040362) @@ -21,15 +21,18 @@ using System; using System.Collections.Generic; + using Core.Common.Base; +using Core.Common.Base.Storage; + using Ringtoets.Common.Data.Properties; namespace Ringtoets.Common.Data.Calculation { /// /// Class to allow grouping one or multiple instances. /// - public class CalculationGroup : Observable, ICalculationBase + public class CalculationGroup : Observable, ICalculationBase, IStorable { private string name; @@ -76,5 +79,7 @@ name = value; } } + + public long StorageId { get; set; } } } \ No newline at end of file Index: Ringtoets/Common/test/Ringtoets.Common.Data.Test/Calculation/CalculationGroupTest.cs =================================================================== diff -u -r33e0fdc6b375e7e2a1eb332c7adc1d558c6b47d1 -ra760d63747f5c44e99f4e747ace1b4e51c040362 --- Ringtoets/Common/test/Ringtoets.Common.Data.Test/Calculation/CalculationGroupTest.cs (.../CalculationGroupTest.cs) (revision 33e0fdc6b375e7e2a1eb332c7adc1d558c6b47d1) +++ Ringtoets/Common/test/Ringtoets.Common.Data.Test/Calculation/CalculationGroupTest.cs (.../CalculationGroupTest.cs) (revision a760d63747f5c44e99f4e747ace1b4e51c040362) @@ -21,6 +21,8 @@ using System; using Core.Common.Base; +using Core.Common.Base.Storage; + using NUnit.Framework; using Rhino.Mocks; using Ringtoets.Common.Data.Calculation; @@ -39,9 +41,12 @@ // Assert Assert.IsInstanceOf(group); Assert.IsInstanceOf(group); + Assert.IsInstanceOf(group); + Assert.IsTrue(group.IsNameEditable); Assert.AreEqual("Nieuwe map", group.Name); CollectionAssert.IsEmpty(group.Children); + Assert.AreEqual(0, group.StorageId); } [Test]