Skip to content

Commit

Permalink
Fixes #1987 add reference to module in building blocks (#1988)
Browse files Browse the repository at this point in the history
  • Loading branch information
msevestre authored Apr 21, 2023
1 parent ffa8526 commit 09ad5e5
Show file tree
Hide file tree
Showing 17 changed files with 166 additions and 249 deletions.
2 changes: 1 addition & 1 deletion src/OSPSuite.Assets/UIConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1594,7 +1594,7 @@ public static string MoleculeNameExistsInAnotherList(string moleculeName)
{
return $"Cannot add molecule '{moleculeName}' into both molecules to include and molecules to exclude lists";
}
public static string BuildingBlockTypeNotSupported(string objectName) => $"BuildingBlock type for {objectName} is not supported";
public static string BuildingBlockTypeAlreadyAddedToModule(string objectName, string type) => $"BuildingBlock '{type}' for '{objectName}' was already added to module";

public const string NotImplemented = "This feature is not implemented yet";

Expand Down
39 changes: 26 additions & 13 deletions src/OSPSuite.Core/Converters/v12/Converter110To120.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,40 +54,53 @@ private void convertBuildConfigurationToSimulationConfiguration(XElement buildCo
if (simulationNode == null)
return;

var moleculeStartValueCollectionElement = new XElement("MoleculeStartValuesCollection");
var parameterStartValueCollectionElement = new XElement("ParameterStartValuesCollection");
var simulationConfigurationElement = new XElement(Constants.Serialization.SIMULATION_CONFIGURATION);
var moduleConfigurationList = new XElement("ModuleConfigurations");
var moduleConfiguration = new XElement("ModuleConfiguration");
var moduleElement = new XElement("Module");
var buildingBlockList = new XElement("BuildingBlocks");
moduleElement.Add(buildingBlockList);
moduleConfigurationList.Add(moduleConfiguration);
moduleConfiguration.Add(moduleElement);
simulationConfigurationElement.Add(moduleConfigurationList);

moduleElement.Add(buildConfigurationElement.Element("Molecules"));
moduleElement.Add(buildConfigurationElement.Element("Reactions"));
moduleElement.Add(buildConfigurationElement.Element("PassiveTransports"));
var buildingBlockElement = buildConfigurationElement.Element("Molecules");
buildingBlockElement.Name = "MoleculeBuildingBlock";
buildingBlockList.Add(buildingBlockElement);

buildingBlockElement = buildConfigurationElement.Element("Reactions");
buildingBlockElement.Name = "ReactionBuildingBlock";
buildingBlockList.Add(buildingBlockElement);

buildingBlockElement = buildConfigurationElement.Element("PassiveTransports");
buildingBlockElement.Name = "PassiveTransportBuildingBlock";
buildingBlockList.Add(buildingBlockElement);

//already singular
moduleElement.Add(buildConfigurationElement.Element("SpatialStructure"));
moduleElement.Add(buildConfigurationElement.Element("Observers"));
moduleElement.Add(buildConfigurationElement.Element("EventGroups"));
buildingBlockList.Add(buildConfigurationElement.Element("SpatialStructure"));

buildingBlockElement = buildConfigurationElement.Element("Observers");
buildingBlockElement.Name = "ObserverBuildingBlock";
buildingBlockList.Add(buildingBlockElement);

buildingBlockElement = buildConfigurationElement.Element("EventGroups");
buildingBlockElement.Name = "EventGroupBuildingBlock";
buildingBlockList.Add(buildingBlockElement);

var parameterStartValuesElement = buildConfigurationElement.Element("ParameterStartValues");
var parameterStartValuesId = parameterStartValuesElement.Attribute("id").Value;
parameterStartValuesElement.Name = "ParameterStartValuesBuildingBlock";
parameterStartValueCollectionElement.Add(parameterStartValuesElement);
buildingBlockList.Add(parameterStartValuesElement);

var moleculeStartValueElement = buildConfigurationElement.Element("MoleculeStartValues");
var moleculeStartValuesId = moleculeStartValueElement.Attribute("id").Value;
moleculeStartValueElement.Name = "MoleculeStartValuesBuildingBlock";
moleculeStartValueCollectionElement.Add(moleculeStartValueElement);
buildingBlockList.Add(moleculeStartValueElement);

moduleConfiguration.AddAttribute("selectedMoleculeStartValues", moleculeStartValuesId);
moduleConfiguration.AddAttribute("selectedParameterStartValues", parameterStartValuesId);

moduleElement.Add(parameterStartValueCollectionElement);
moduleElement.Add(moleculeStartValueCollectionElement);


var simulationSettings = buildConfigurationElement.Element("SimulationSettings");
var allCalculationMethods = buildConfigurationElement.Element("AllCalculationMethods");
buildConfigurationElement.Remove();
Expand Down
13 changes: 8 additions & 5 deletions src/OSPSuite.Core/Domain/Builder/BuildingBlock.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ public interface IBuildingBlock : IObjectBase, IWithCreationMetaData
uint Version { set; get; }

void AddFormula(IFormula formula);

/// <summary>
/// Reference to module containing this building block. May be null if the building block is not in a module
/// (Individual, Expressions)
/// </summary>
Module Module { get; set; }
}

/// <summary>
Expand All @@ -35,6 +41,7 @@ public abstract class BuildingBlock : ObjectBase, IBuildingBlock
public IFormulaCache FormulaCache { get; }
public uint Version { set; get; }
public CreationMetaData Creation { get; set; }
public Module Module { get; set; }

public void AddFormula(IFormula formula)
{
Expand Down Expand Up @@ -64,11 +71,7 @@ public override void UpdatePropertiesFrom(IUpdatable source, ICloneManager clone
}
}

public interface IBuilder : IObjectBase
{
//Reference to building block containing this entity. This does not have to be serialized
IBuildingBlock BuildingBlock { get; set; }
}


public interface IBuildingBlock<TBuilder> : IBuildingBlock, IEnumerable<TBuilder> where TBuilder : IBuilder
{
Expand Down
8 changes: 8 additions & 0 deletions src/OSPSuite.Core/Domain/Builder/IBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace OSPSuite.Core.Domain.Builder
{
public interface IBuilder : IObjectBase
{
//Reference to building block containing this entity. This does not have to be serialized
IBuildingBlock BuildingBlock { get; set; }
}
}
170 changes: 43 additions & 127 deletions src/OSPSuite.Core/Domain/Module.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using OSPSuite.Assets;
Expand All @@ -9,28 +10,28 @@

namespace OSPSuite.Core.Domain
{
public class Module : ObjectBase
public class Module : ObjectBase, IEnumerable<IBuildingBlock>
{
private readonly List<MoleculeStartValuesBuildingBlock> _moleculeStartValuesCollection = new List<MoleculeStartValuesBuildingBlock>();
private readonly List<ParameterStartValuesBuildingBlock> _parameterStartValuesCollection = new List<ParameterStartValuesBuildingBlock>();
private readonly List<IBuildingBlock> _buildingBlocks = new List<IBuildingBlock>();

private T buildingBlockByType<T>() where T : IBuildingBlock => _buildingBlocks.OfType<T>().SingleOrDefault();
private IReadOnlyList<T> buildingBlocksByType<T>() where T : IBuildingBlock => _buildingBlocks.OfType<T>().ToList();

public bool ReadOnly { get; set; } = false;

public EventGroupBuildingBlock EventGroups { set; get; }
public MoleculeBuildingBlock Molecules { set; get; }
public ObserverBuildingBlock Observers { set; get; }
public ReactionBuildingBlock Reactions { set; get; }
public PassiveTransportBuildingBlock PassiveTransports { set; get; }
public SpatialStructure SpatialStructure { set; get; }
public IReadOnlyList<MoleculeStartValuesBuildingBlock> MoleculeStartValuesCollection => _moleculeStartValuesCollection;
public IReadOnlyList<ParameterStartValuesBuildingBlock> ParameterStartValuesCollection => _parameterStartValuesCollection;
public EventGroupBuildingBlock EventGroups => buildingBlockByType<EventGroupBuildingBlock>();
public MoleculeBuildingBlock Molecules => buildingBlockByType<MoleculeBuildingBlock>();
public ObserverBuildingBlock Observers => buildingBlockByType<ObserverBuildingBlock>();
public ReactionBuildingBlock Reactions => buildingBlockByType<ReactionBuildingBlock>();
public PassiveTransportBuildingBlock PassiveTransports => buildingBlockByType<PassiveTransportBuildingBlock>();
public SpatialStructure SpatialStructure => buildingBlockByType<SpatialStructure>();

public IReadOnlyList<MoleculeStartValuesBuildingBlock> MoleculeStartValuesCollection => buildingBlocksByType<MoleculeStartValuesBuildingBlock>();

public IReadOnlyList<ParameterStartValuesBuildingBlock> ParameterStartValuesCollection => buildingBlocksByType<ParameterStartValuesBuildingBlock>();

public virtual ExtendedProperties ExtendedProperties { get; } = new ExtendedProperties();

public Module()
{
Icon = IconNames.Module;
}

public override void UpdatePropertiesFrom(IUpdatable source, ICloneManager cloneManager)
{
base.UpdatePropertiesFrom(source, cloneManager);
Expand All @@ -39,132 +40,37 @@ public override void UpdatePropertiesFrom(IUpdatable source, ICloneManager clone
return;

ReadOnly = sourceModule.ReadOnly;
// Cloning these properties within the update for now. It could change based on specs
Molecules = cloneManager.Clone(sourceModule.Molecules);
Reactions = cloneManager.Clone(sourceModule.Reactions);
PassiveTransports = cloneManager.Clone(sourceModule.PassiveTransports);
SpatialStructure = cloneManager.Clone(sourceModule.SpatialStructure);
Observers = cloneManager.Clone(sourceModule.Observers);
EventGroups = cloneManager.Clone(sourceModule.EventGroups);

sourceModule.MoleculeStartValuesCollection.Each(x => _moleculeStartValuesCollection.Add(cloneManager.Clone(x)));
sourceModule.ParameterStartValuesCollection.Each(x => _parameterStartValuesCollection.Add(cloneManager.Clone(x)));

_buildingBlocks.AddRange(sourceModule.BuildingBlocks.Select(cloneManager.Clone));
ExtendedProperties.UpdateFrom(sourceModule.ExtendedProperties);
}

public void AddParameterStartValueBlock(ParameterStartValuesBuildingBlock parameterStartValuesBuildingBlock)
{
_parameterStartValuesCollection.Add(parameterStartValuesBuildingBlock);
}

public void AddMoleculeStartValueBlock(MoleculeStartValuesBuildingBlock moleculeStartValuesBuildingBlock)
{
_moleculeStartValuesCollection.Add(moleculeStartValuesBuildingBlock);
}

public void RemoveParameterStartValueBlock(ParameterStartValuesBuildingBlock parameterStartValuesBuildingBlock)
{
_parameterStartValuesCollection.Remove(parameterStartValuesBuildingBlock);
}

public void RemoveMoleculeStartValueBlock(MoleculeStartValuesBuildingBlock moleculeStartValuesBuildingBlock)
{
_moleculeStartValuesCollection.Remove(moleculeStartValuesBuildingBlock);
}

public void AddBuildingBlock(IBuildingBlock buildingBlock)
public void Add(IBuildingBlock buildingBlock)
{
switch (buildingBlock)
if (isSingle(buildingBlock))
{
case MoleculeBuildingBlock molecule:
Molecules = molecule;
break;
case ReactionBuildingBlock reaction:
Reactions = reaction;
break;
case SpatialStructure spatialStructure:
SpatialStructure = spatialStructure;
break;
case PassiveTransportBuildingBlock passiveTransport:
PassiveTransports = passiveTransport;
break;
case EventGroupBuildingBlock eventGroup:
EventGroups = eventGroup;
break;
case ObserverBuildingBlock observer:
Observers = observer;
break;
case ParameterStartValuesBuildingBlock parameterStartValues:
AddParameterStartValueBlock(parameterStartValues);
break;
case MoleculeStartValuesBuildingBlock moleculeStartValues:
AddMoleculeStartValueBlock(moleculeStartValues);
break;
case null:
return;
default:
throw new OSPSuiteException(Error.BuildingBlockTypeNotSupported(buildingBlock.Name));
var type = buildingBlock.GetType();
var existingBuildingBlock = _buildingBlocks.FirstOrDefault(x => x.IsAnImplementationOf(type));
if (existingBuildingBlock != null)
throw new OSPSuiteException(Error.BuildingBlockTypeAlreadyAddedToModule(buildingBlock.Name, type.Name));
}
buildingBlock.Module = this;
_buildingBlocks.Add(buildingBlock);
}

public void RemoveBuildingBlock(IBuildingBlock buildingBlock)
{
switch (buildingBlock)
{
case MoleculeBuildingBlock _:
Molecules = null;
break;
case ReactionBuildingBlock _:
Reactions = null;
break;
case SpatialStructure _:
SpatialStructure = null;
break;
case PassiveTransportBuildingBlock _:
PassiveTransports = null;
break;
case EventGroupBuildingBlock _:
EventGroups = null;
break;
case ObserverBuildingBlock _:
Observers = null;
break;
case ParameterStartValuesBuildingBlock parameterStartValues:
RemoveParameterStartValueBlock(parameterStartValues);
break;
case MoleculeStartValuesBuildingBlock moleculeStartValues:
RemoveMoleculeStartValueBlock(moleculeStartValues);
break;
case null:
return;
default:
throw new OSPSuiteException(Error.BuildingBlockTypeNotSupported(buildingBlock.Name));
}
}
private bool isSingle(IBuildingBlock buildingBlock) => !(buildingBlock.IsAnImplementationOf<MoleculeStartValuesBuildingBlock>() || buildingBlock.IsAnImplementationOf<ParameterStartValuesBuildingBlock>());

public IReadOnlyList<IBuildingBlock> AllBuildingBlocks()
public void Remove(IBuildingBlock buildingBlock)
{
var buildingBlocks = new List<IBuildingBlock>
{
SpatialStructure,
EventGroups,
PassiveTransports,
Molecules,
Observers,
Reactions,
};

buildingBlocks.AddRange(ParameterStartValuesCollection);
buildingBlocks.AddRange(MoleculeStartValuesCollection);

return buildingBlocks.Where(x => x != null).ToList();
buildingBlock.Module = null;
_buildingBlocks.Remove(buildingBlock);
}

public IReadOnlyList<IBuildingBlock> BuildingBlocks => _buildingBlocks;

public override void AcceptVisitor(IVisitor visitor)
{
base.AcceptVisitor(visitor);
AllBuildingBlocks().Each(x => x.AcceptVisitor(visitor));
BuildingBlocks.Each(x => x.AcceptVisitor(visitor));
}

public void AddExtendedProperty<T>(string propertyName, T property)
Expand All @@ -182,5 +88,15 @@ public T ExtendedPropertyValueFor<T>(string propertyName)
{
return ExtendedProperties.Contains(propertyName) ? ExtendedProperties[propertyName].ValueAsObject.ConvertedTo<T>() : default(T);
}

public IEnumerator<IBuildingBlock> GetEnumerator()
{
return _buildingBlocks.GetEnumerator();
}

IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
}
9 changes: 1 addition & 8 deletions src/OSPSuite.Core/Serialization/Xml/ModuleXmlSerializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,7 @@ public class ModuleXmlSerializer : ObjectBaseXmlSerializer<Module>
public override void PerformMapping()
{
base.PerformMapping();
Map(x => x.Molecules);
Map(x => x.Reactions);
Map(x => x.PassiveTransports);
Map(x => x.SpatialStructure);
Map(x => x.Observers);
Map(x => x.EventGroups);
MapEnumerable(x => x.MoleculeStartValuesCollection, x => x.AddMoleculeStartValueBlock);
MapEnumerable(x => x.ParameterStartValuesCollection, x => x.AddParameterStartValueBlock);
MapEnumerable(x => x.BuildingBlocks, x => x.Add);
MapEnumerable(x => x.ExtendedProperties, x => x.ExtendedProperties.Add);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ public void TestSerialization()
var module1 = CreateObject<Module>().WithName("Module1");

module1.AddExtendedProperty("PKSimVersion", "version1");
module1.EventGroups = CreateObject<EventGroupBuildingBlock>().WithName("EventGroup");
module1.PassiveTransports = CreateObject<PassiveTransportBuildingBlock>().WithName("PassiveTransport");
module1.Molecules = CreateObject<MoleculeBuildingBlock>().WithName("Molecule");
module1.Reactions = CreateObject<ReactionBuildingBlock>().WithName("Reaction");
module1.SpatialStructure = CreateObject<SpatialStructure>().WithName("SpatialStructure");
module1.Observers = CreateObject<ObserverBuildingBlock>().WithName("Observer");
module1.Add(CreateObject<EventGroupBuildingBlock>().WithName("EventGroup"));
module1.Add(CreateObject<PassiveTransportBuildingBlock>().WithName("PassiveTransport"));
module1.Add(CreateObject<MoleculeBuildingBlock>().WithName("Molecule"));
module1.Add(CreateObject<ReactionBuildingBlock>().WithName("Reaction"));
module1.Add(CreateObject<SpatialStructure>().WithName("SpatialStructure"));
module1.Add(CreateObject<ObserverBuildingBlock>().WithName("Observer"));

module1.AddMoleculeStartValueBlock(CreateObject<MoleculeStartValuesBuildingBlock>().WithName("MSVBB"));
module1.AddParameterStartValueBlock(CreateObject<ParameterStartValuesBuildingBlock>().WithName("PSVBB"));
module1.Add(CreateObject<MoleculeStartValuesBuildingBlock>().WithName("MSVBB"));
module1.Add(CreateObject<ParameterStartValuesBuildingBlock>().WithName("PSVBB"));

var module2 = SerializeAndDeserialize(module1);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ protected override void Context()
reactionBuildingBlock.Add(reactionAtoB);
reactionBuildingBlock.Add(reactionBtoA);

var module = new Module {Reactions = reactionBuildingBlock};
var module = new Module {reactionBuildingBlock};
var moduleConfiguration = new ModuleConfiguration(module, null, null);
_simulation.Configuration.AddModuleConfiguration(moduleConfiguration);
}
Expand Down
4 changes: 2 additions & 2 deletions tests/OSPSuite.Core.Tests/Domain/ModelValidatorSpecs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,10 @@ protected override void Context()
base.Context();
var module = new Module();
var reactions = new ReactionBuildingBlock {new ReactionBuilder().WithName("REACTION")};
module.Reactions = reactions;
module.Add(reactions);

var passiveTransports = new PassiveTransportBuildingBlock {new TransportBuilder().WithName("TRANSPORT")};
module.PassiveTransports = passiveTransports;
module.Add(passiveTransports);

_simulationConfiguration.AddModuleConfiguration(new ModuleConfiguration(module));
sut = new ValidatorForReactionsAndTransports(_objectTypeResolver, _objectPathFactory);
Expand Down
Loading

0 comments on commit 09ad5e5

Please sign in to comment.