Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes #2041 Create initial conditions for ExpressionProfileBuildingBlock #2042

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 27 additions & 9 deletions src/OSPSuite.Core/Domain/Services/InitialConditionsCreator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using OSPSuite.Core.Domain.Builder;
using OSPSuite.Core.Domain.Formulas;
using OSPSuite.Core.Domain.UnitSystem;
using OSPSuite.Utility.Extensions;

namespace OSPSuite.Core.Domain.Services
{
Expand All @@ -23,21 +24,28 @@ public interface IInitialConditionsCreator : IEmptyStartValueCreator<InitialCond
/// <param name="valueOrigin">The value origin for the value</param>
/// <returns>an InitialCondition object</returns>
InitialCondition CreateInitialCondition(ObjectPath containerPath, string moleculeName, IDimension dimension, Unit displayUnit = null, ValueOrigin valueOrigin = null);

/// <summary>
/// Creates a new initial conditions for the <paramref name="molecule" /> in the <paramref name="containers" /> and adds
/// them to the <paramref name="buildingBlock" />, initializing the default values and formulae.
/// The <paramref name="containers"/> list are containers where an initial condition will be created for each using the container path
/// </summary>
void AddToExpressionProfile(ExpressionProfileBuildingBlock buildingBlock, IReadOnlyList<IContainer> containers, MoleculeBuilder molecule);
}

internal class InitialConditionsCreator : IInitialConditionsCreator
{
private readonly IObjectBaseFactory _objectBaseFactory;
private readonly IObjectPathFactory _objectPathFactory;
private readonly IEntityPathResolver _entityPathResolver;
private readonly IIdGenerator _idGenerator;
private readonly ICloneManagerForBuildingBlock _cloneManagerForBuildingBlock;

public InitialConditionsCreator(
IObjectBaseFactory objectBaseFactory, IObjectPathFactory objectPathFactory, IIdGenerator idGenerator,
IObjectBaseFactory objectBaseFactory, IEntityPathResolver entityPathResolver, IIdGenerator idGenerator,
ICloneManagerForBuildingBlock cloneManagerForBuildingBlock)
{
_objectBaseFactory = objectBaseFactory;
_objectPathFactory = objectPathFactory;
_entityPathResolver = entityPathResolver;
_cloneManagerForBuildingBlock = cloneManagerForBuildingBlock;
_idGenerator = idGenerator;
}
Expand All @@ -54,21 +62,31 @@ public InitialConditionsBuildingBlock CreateFrom(SpatialStructure spatialStructu
return initialConditions;
}

private InitialCondition createInitialCondition(IBuildingBlock initialConditionsBuildingBlock, IEntity container, MoleculeBuilder molecule)
{
var initialCondition = CreateInitialCondition(_entityPathResolver.ObjectPathFor(container), molecule.Name, molecule.Dimension, molecule.DisplayUnit);
setInitialCondition(molecule, initialCondition);
setInitialConditionFormula(molecule.DefaultStartFormula, initialCondition, initialConditionsBuildingBlock);
return initialCondition;
}

private void addMoleculesFrom(InitialConditionsBuildingBlock initialConditionsBuildingBlock, IEntity container, IEnumerable<MoleculeBuilder> molecules)
{
foreach (var molecule in molecules)
{
var initialCondition = CreateInitialCondition(_objectPathFactory.CreateAbsoluteObjectPath(container), molecule.Name, molecule.Dimension, molecule.DisplayUnit);
setInitialCondition(molecule, initialCondition);
setInitialConditionFormula(molecule.DefaultStartFormula, initialCondition, initialConditionsBuildingBlock);
initialConditionsBuildingBlock.Add(initialCondition);
initialConditionsBuildingBlock.Add(createInitialCondition(initialConditionsBuildingBlock, container, molecule));
}
}

private void setInitialConditionFormula(IFormula formula, InitialCondition initialCondition, IBuildingBlock moleculesStartValues)
public void AddToExpressionProfile(ExpressionProfileBuildingBlock buildingBlock, IReadOnlyList<IContainer> containers, MoleculeBuilder molecule)
{
containers.Each(container => { buildingBlock.AddInitialCondition(createInitialCondition(buildingBlock, container, molecule)); });
}

private void setInitialConditionFormula(IFormula formula, InitialCondition initialCondition, IBuildingBlock buildingBlock)
{
if (!formula.IsConstant())
initialCondition.Formula = _cloneManagerForBuildingBlock.Clone(formula, moleculesStartValues.FormulaCache);
initialCondition.Formula = _cloneManagerForBuildingBlock.Clone(formula, buildingBlock.FormulaCache);
}

private static void setInitialCondition(MoleculeBuilder moleculeBuilder, InitialCondition initialCondition)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,67 @@ protected override void Context()
_baseFactory = A.Fake<IObjectBaseFactory>();
A.CallTo(() => _baseFactory.Create<InitialConditionsBuildingBlock>()).ReturnsLazily(() => new InitialConditionsBuildingBlock());
_cloneManagerForBuildingBlock = A.Fake<ICloneManagerForBuildingBlock>();
sut = new InitialConditionsCreator(_baseFactory, new ObjectPathFactory(new AliasCreator()),
sut = new InitialConditionsCreator(_baseFactory, new EntityPathResolver(new ObjectPathFactory(new AliasCreator())),
new IdGenerator(), _cloneManagerForBuildingBlock);
}
}

internal class when_adding_initial_conditions_to_expression_profile : concern_for_InitialConditionsCreator
{
private MoleculeBuilder _molecule;
private Container _container;
private ExpressionProfileBuildingBlock _expressionProfile;
protected override void Context()
{
base.Context();
_molecule = new MoleculeBuilder().WithName("moleculeName").WithDimension(Constants.Dimension.NO_DIMENSION);
_molecule.DefaultStartFormula = new ExplicitFormula("y = mx + b)");
_expressionProfile = new ExpressionProfileBuildingBlock().WithName("moleculeName");
var topContainer = new Container
{
ContainerType = ContainerType.Organ,
Mode = ContainerMode.Physical,
Name = "topContainer"
};

_container = new Container
{
ContainerType = ContainerType.Organ,
Mode = ContainerMode.Physical,
Name = "physicalContainer"
};

_container.Add(new Container
{
ContainerType = ContainerType.Molecule,
Name = _expressionProfile.MoleculeName,
Mode = ContainerMode.Logical
});
topContainer.Add(_container);

A.CallTo(() => _cloneManagerForBuildingBlock.Clone(_molecule.DefaultStartFormula, _expressionProfile.FormulaCache)).Returns(new ExplicitFormula("y = mx + b)"));
}

protected override void Because()
{
sut.AddToExpressionProfile(_expressionProfile, new []{ _container }, _molecule);
}

[Observation]
public void initial_conditions_should_be_created_for_physical_containers_with_molecules()
{
_expressionProfile.InitialConditions.Count.ShouldBeEqualTo(1);
_expressionProfile.InitialConditions.First().Path.ToString().ShouldBeEqualTo("topContainer|physicalContainer|moleculeName");
_expressionProfile.InitialConditions.First().Formula.ToString().ShouldBeEqualTo("y = mx + b)");
}

[Observation]
public void the_clone_manager_is_used_to_clone_the_formula_and_add_to_the_cache()
{
A.CallTo(() => _cloneManagerForBuildingBlock.Clone(_molecule.DefaultStartFormula, _expressionProfile.FormulaCache)).MustHaveHappened();
}
}

internal class when_generating_new_start_values_building_block : concern_for_InitialConditionsCreator
{
private InitialConditionsBuildingBlock _result;
Expand Down