Skip to content

Commit ec6a776

Browse files
authored
Fixes #2057 Events: Assignments: show parameters from Individuals (#2365)
1 parent d051085 commit ec6a776

11 files changed

Lines changed: 235 additions & 133 deletions
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
using MoBi.Core.Domain.Extensions;
2+
using MoBi.Core.Extensions;
3+
using NHibernate.Loader.Custom;
4+
using OSPSuite.Core.Domain;
5+
using OSPSuite.Core.Domain.Builder;
6+
using OSPSuite.Utility.Collections;
7+
using OSPSuite.Utility.Extensions;
8+
using System.Collections.Generic;
9+
using System.Linq;
10+
11+
namespace MoBi.Core.Services
12+
{
13+
public interface IPathAndValueContainerizingTask
14+
{
15+
/// <summary>
16+
/// Builds a synthetic container tree for the given building block, grouping entities by
17+
/// their <see cref="PathAndValueEntity.ContainerPath" />. The root of the synthetic tree is
18+
/// stored in <paramref name="cache" /> keyed by the building block so that subsequent lookups
19+
/// (<see cref="ChildrenFor" />, <see cref="IsInCachedTree" />) can find it.
20+
/// </summary>
21+
IReadOnlyList<IObjectBase> ChildrenFor<TBuildingBlock, TEntity>(TBuildingBlock buildingBlock, ICache<IBuildingBlock, IContainer> cache)
22+
where TBuildingBlock : PathAndValueEntityBuildingBlock<TEntity>
23+
where TEntity : PathAndValueEntity;
24+
25+
/// <summary>
26+
/// Returns the ordered children of a container that is part of any synthetic tree previously
27+
/// built into <paramref name="cache" />. Returns an empty list when the container is not in
28+
/// the cache.
29+
/// </summary>
30+
IReadOnlyList<IObjectBase> ChildrenFor(IContainer container, ICache<IBuildingBlock, IContainer> cache);
31+
32+
/// <summary>
33+
/// Indicates whether <paramref name="container" /> belongs to any synthetic tree previously
34+
/// built into <paramref name="cache" />.
35+
/// </summary>
36+
bool IsInCachedTree(IContainer container, ICache<IBuildingBlock, IContainer> cache);
37+
}
38+
39+
public class PathAndValueContainerizingTask : IPathAndValueContainerizingTask
40+
{
41+
public IReadOnlyList<IObjectBase> ChildrenFor<TBuildingBlock, TEntity>(TBuildingBlock buildingBlock, ICache<IBuildingBlock, IContainer> cache)
42+
where TBuildingBlock : PathAndValueEntityBuildingBlock<TEntity>
43+
where TEntity : PathAndValueEntity
44+
{
45+
if (buildingBlock == null)
46+
return new List<IObjectBase>();
47+
48+
if (cache.Contains(buildingBlock))
49+
return orderedChildrenOf(cache[buildingBlock]); ;
50+
51+
var orderedEntities = buildingBlock.OrderBy(x => x.Path.PathAsString).ToList();
52+
var rootContainer = buildGroups(entitiesExceptSubParameters(orderedEntities));
53+
cache[buildingBlock] = rootContainer;
54+
55+
orderedEntities.Each(x => addToContainer(x, rootContainer));
56+
57+
return orderedChildrenOf(rootContainer);
58+
}
59+
60+
public IReadOnlyList<IObjectBase> ChildrenFor(IContainer container, ICache<IBuildingBlock, IContainer> cache)
61+
{
62+
return IsInCachedTree(container, cache) ? orderedChildrenOf(container) : new List<IObjectBase>();
63+
}
64+
65+
public bool IsInCachedTree(IContainer container, ICache<IBuildingBlock, IContainer> cache)
66+
{
67+
return container != null && cache.Any(x => x.GetAllContainersAndSelf<IContainer>().Contains(container));
68+
}
69+
70+
private static IReadOnlyList<IObjectBase> orderedChildrenOf(IContainer container)
71+
{
72+
var result = new List<IObjectBase>();
73+
result.AddRange(container.GetChildrenSortedByName<IContainer>());
74+
result.AddRange(container.GetChildrenSortedByName<PathAndValueEntity>());
75+
return result;
76+
}
77+
78+
private static IReadOnlyList<TEntity> entitiesExceptSubParameters<TEntity>(IReadOnlyList<TEntity> entities) where TEntity : PathAndValueEntity
79+
{
80+
return entities.Where(x => !isSubParameter(x, entities)).ToList();
81+
}
82+
83+
private static bool isSubParameter<TEntity>(TEntity entity, IReadOnlyList<TEntity> entities) where TEntity : PathAndValueEntity
84+
{
85+
return entities.Any(entity.IsDirectSubParameterOf);
86+
}
87+
88+
private static void addToContainer(PathAndValueEntity entity, IContainer container)
89+
{
90+
var parentContainer = entity.ContainerPath.TryResolve<IContainer>(container);
91+
parentContainer?.Add(entity);
92+
}
93+
94+
private static IContainer buildGroups<TEntity>(IReadOnlyList<TEntity> entities) where TEntity : PathAndValueEntity
95+
{
96+
var rootContainer = new Container();
97+
98+
// construct a new object path to avoid changing the original object path
99+
entities.Select(x => new ObjectPath(x.ContainerPath)).ToList()
100+
.Where(x => x.Any())
101+
.GroupBy(x => x.First())
102+
.Each(x => addContainersFor(x, rootContainer));
103+
104+
return rootContainer;
105+
}
106+
107+
private static void addContainersFor(IGrouping<string, ObjectPath> group, IContainer rootContainer)
108+
{
109+
if (string.IsNullOrEmpty(group.Key))
110+
return;
111+
112+
var groupContainer = new Container().WithName(group.Key);
113+
group.Each(x => x.RemoveFirst());
114+
group.Where(x => x.Any()).GroupBy(x => x.First()).Each(x => addContainersFor(x, groupContainer));
115+
rootContainer.Add(groupContainer);
116+
}
117+
}
118+
}

src/MoBi.Presentation/Mappers/ObjectBaseDTOToReferenceNodeMapper.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,8 @@
1010

1111
namespace MoBi.Presentation.Mappers
1212
{
13-
public interface IObjectBaseDTOToReferenceNodeMapper : IMapper<IObjectBase, ITreeNode>
13+
public interface IObjectBaseDTOToReferenceNodeMapper : IMapper<IObjectBase, ITreeNode>, IMapper<ObjectBaseDTO, ITreeNode>
1414
{
15-
ITreeNode MapFrom(ObjectBaseDTO objectBaseDTO);
16-
1715
void Initialize(Func<ObjectBaseDTO, IEnumerable<ObjectBaseDTO>> getChildren);
1816
}
1917

src/MoBi.Presentation/Presenter/SelectContanerInTreePresenter.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
using System.Collections.Generic;
33
using System.Linq;
44
using MoBi.Core.Domain.Extensions;
5-
using MoBi.Core.Domain.Model;
65
using MoBi.Presentation.DTO;
76
using MoBi.Presentation.Mappers;
87
using MoBi.Presentation.Views;
@@ -25,9 +24,8 @@ public class SelectContainerInTreePresenter : SelectEntityInTreePresenter, ISele
2524

2625
public SelectContainerInTreePresenter(ISelectEntityInTreeView view,
2726
IObjectPathFactory objectPathFactory,
28-
IMoBiContext context,
2927
IContainerToContainerDTOMapper containerDTOMapper,
30-
IObjectBaseDTOToSpatialStructureNodeMapper spatialStructureNodeMapper) : base(view, objectPathFactory, context, spatialStructureNodeMapper)
28+
IObjectBaseDTOToReferenceNodeMapper referenceNodeMapper) : base(view, objectPathFactory, referenceNodeMapper)
3129
{
3230
_containerDTOMapper = containerDTOMapper;
3331
_objectPathFactory = objectPathFactory;

src/MoBi.Presentation/Presenter/SelectEventAssignmentTargetPresenter.cs

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,10 @@
44
using MoBi.Assets;
55
using MoBi.Core.Domain.Extensions;
66
using MoBi.Core.Domain.Model;
7-
using MoBi.Core.Domain.Repository;
7+
using MoBi.Core.Services;
88
using MoBi.Presentation.DTO;
99
using MoBi.Presentation.Mappers;
1010
using MoBi.Presentation.Views;
11-
using OSPSuite.Assets;
1211
using OSPSuite.Core.Domain;
1312
using OSPSuite.Core.Domain.Builder;
1413
using OSPSuite.Core.Domain.Services;
@@ -39,6 +38,8 @@ public class SelectEventAssignmentTargetPresenter : AbstractDisposablePresenter<
3938
private readonly ISelectEntityInTreePresenter _selectEntityInTreePresenter;
4039
private readonly ISpatialStructureToSpatialStructureDTOMapper _spatialStructureDTOMapper;
4140
private readonly IBuildingBlockRepository _buildingBlockRepository;
41+
private readonly IPathAndValueContainerizingTask _containerizingTask;
42+
private readonly Cache<IBuildingBlock, IContainer> _pathAndValueContainers = new Cache<IBuildingBlock, IContainer>();
4243
private IReadOnlyList<MoleculeBuilder> _molecules;
4344
private IReadOnlyList<ReactionBuilder> _reactions;
4445
private ICache<IObjectBase, string> _forbiddenAssignees;
@@ -54,7 +55,8 @@ public SelectEventAssignmentTargetPresenter(
5455
IReactionDimensionRetriever dimensionRetriever,
5556
ISelectEntityInTreePresenter selectEntityInTreePresenter,
5657
ISpatialStructureToSpatialStructureDTOMapper spatialStructureDTOMapper,
57-
IBuildingBlockRepository buildingBlockRepository
58+
IBuildingBlockRepository buildingBlockRepository,
59+
IPathAndValueContainerizingTask containerizingTask
5860
)
5961
: base(view)
6062
{
@@ -63,6 +65,7 @@ IBuildingBlockRepository buildingBlockRepository
6365
_selectEntityInTreePresenter = selectEntityInTreePresenter;
6466
_spatialStructureDTOMapper = spatialStructureDTOMapper;
6567
_buildingBlockRepository = buildingBlockRepository;
68+
_containerizingTask = containerizingTask;
6669
_objectPathFactory = objectPathFactory;
6770
_dummyMoleculeDTOMapper = dummyMoleculeDTOMapper;
6871
_dummyReactionDTOMapper = dummyReactionDTOMapper;
@@ -94,14 +97,18 @@ public IReadOnlyList<ObjectBaseDTO> GetChildren(ObjectBaseDTO parentDTO)
9497
if (parent.IsAnImplementationOf<IDistributedParameter>())
9598
return Array.Empty<ObjectBaseDTO>();
9699

97-
var spatialStructureDTO = parentDTO as SpatialStructureDTO;
98-
if (spatialStructureDTO != null)
100+
if (parentDTO is SpatialStructureDTO spatialStructureDTO)
99101
return mapSpatialStructureChildren(spatialStructureDTO);
100102

101-
var container = parent as IContainer;
102-
if (container == null)
103+
if (parent is IndividualBuildingBlock individualBuildingBlock)
104+
return map(_containerizingTask.ChildrenFor<IndividualBuildingBlock, IndividualParameter>(individualBuildingBlock, _pathAndValueContainers));
105+
106+
if (!(parent is IContainer container))
103107
return Array.Empty<ObjectBaseDTO>();
104108

109+
if (_containerizingTask.IsInCachedTree(container, _pathAndValueContainers))
110+
return map(_containerizingTask.ChildrenFor(container, _pathAndValueContainers));
111+
105112
if (parent.IsAnImplementationOf<MoleculeBuilder>() || parent.IsAnImplementationOf<ReactionBuilder>())
106113
{
107114
//Molecule builder and reaction builder are dummy entities at that stage=>add dummy parameters
@@ -112,7 +119,7 @@ public IReadOnlyList<ObjectBaseDTO> GetChildren(ObjectBaseDTO parentDTO)
112119
return map(globalParameterUnder(container));
113120
}
114121

115-
//Real structural container.
122+
//Real structural container.
116123
var list = new List<ObjectBaseDTO>();
117124

118125
//Add sub containers
@@ -136,10 +143,10 @@ private IReadOnlyList<ObjectBaseDTO> mapSpatialStructureChildren(SpatialStructur
136143
if (spatialStructureDTO.MoleculeProperties != null)
137144
objectBaseDTOs.Add(spatialStructureDTO.MoleculeProperties);
138145

139-
if(spatialStructureDTO.TopContainers != null && spatialStructureDTO.TopContainers.Any())
146+
if (spatialStructureDTO.TopContainers != null && spatialStructureDTO.TopContainers.Any())
140147
objectBaseDTOs.AddRange(spatialStructureDTO.TopContainers);
141148

142-
if(spatialStructureDTO.Neighborhoods != null)
149+
if (spatialStructureDTO.Neighborhoods != null)
143150
objectBaseDTOs.Add(spatialStructureDTO.Neighborhoods);
144151

145152
return objectBaseDTOs;
@@ -199,9 +206,11 @@ public void Init(IContainer container, ICache<IObjectBase, string> forbiddenAssi
199206
_molecules = _buildingBlockRepository.MoleculeBlockCollection.SelectMany(bb => bb.All()).Distinct(new NameComparer<MoleculeBuilder>()).OrderBy(x => x.Name).ToList();
200207
_reactions = _buildingBlockRepository.ReactionBlockCollection.SelectMany(bb => bb.All()).Distinct(new NameComparer<ReactionBuilder>()).OrderBy(x => x.Name).ToList();
201208
_forbiddenAssignees = forbiddenAssignees;
209+
_pathAndValueContainers.Clear();
202210
var list = new List<ObjectBaseDTO>();
203211
list.AddRange(_buildingBlockRepository.SpatialStructureCollection.MapAllUsing(_spatialStructureDTOMapper));
204212
list.Add(_objectBaseDTOMapper.MapFrom(container));
213+
list.AddRange(_buildingBlockRepository.IndividualsCollection.MapAllUsing(_objectBaseDTOMapper));
205214
list.AddRange(globalReactionParameters());
206215

207216
_selectEntityInTreePresenter.InitTreeStructure(list);
@@ -229,6 +238,12 @@ private FormulaUsablePath generatePathFromDTO(ObjectBaseDTO dto)
229238
return formulaUsablePathFrom(path, getDimensionFor(dto));
230239
}
231240

241+
if (dto.ObjectBase is IndividualParameter individualParameter)
242+
{
243+
var path = new ObjectPath(individualParameter.Path);
244+
return formulaUsablePathFrom(path, individualParameter.Dimension);
245+
}
246+
232247
var selectedEntity = _context.Get<IEntity>(dto.Id);
233248
if (selectedEntity.IsAnImplementationOf<IUsingFormula>())
234249
{
@@ -259,8 +274,6 @@ private IEntity getExistingParentContainerFromDTO(ObjectBaseDTO dto)
259274
return dtoParent.ObjectBase as IEntity;
260275
}
261276

262-
263-
264277
private IEnumerable<ObjectBaseDTO> getLocalInformationForReaction(IContainer container)
265278
{
266279
return _reactions.Select(x => _dummyReactionDTOMapper.MapFrom(x, container));

src/MoBi.Presentation/Presenter/SelectObjectInTreePresenter.cs

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -40,19 +40,17 @@ public interface ISelectEntityInTreePresenter : IPresenter<ISelectEntityInTreeVi
4040
public class SelectEntityInTreePresenter : AbstractPresenter<ISelectEntityInTreeView, ISelectEntityInTreePresenter>, ISelectEntityInTreePresenter
4141
{
4242
private readonly IObjectPathFactory _objectPathFactory;
43-
private readonly IMoBiContext _context;
4443
public event EventHandler<SelectedEntityChangedArgs> OnSelectedEntityChanged = delegate { };
45-
private readonly IObjectBaseDTOToSpatialStructureNodeMapper _spatialStructureNodeMapper;
44+
private readonly IObjectBaseDTOToReferenceNodeMapper _referenceNodeMapper;
4645

47-
public SelectEntityInTreePresenter(ISelectEntityInTreeView view, IObjectPathFactory objectPathFactory, IMoBiContext context, IObjectBaseDTOToSpatialStructureNodeMapper spatialStructureNodeMapper) : base(view)
46+
public SelectEntityInTreePresenter(ISelectEntityInTreeView view, IObjectPathFactory objectPathFactory, IObjectBaseDTOToReferenceNodeMapper referenceNodeMapper) : base(view)
4847
{
4948
_objectPathFactory = objectPathFactory;
50-
_context = context;
51-
_spatialStructureNodeMapper = spatialStructureNodeMapper;
52-
_spatialStructureNodeMapper.Initialize(objectBase => GetChildren(objectBase));
49+
_referenceNodeMapper = referenceNodeMapper;
50+
_referenceNodeMapper.Initialize(objectBase => GetChildren(objectBase));
5351
}
5452

55-
protected IEntity EntityFrom(ObjectBaseDTO dto) => _context.Get<IEntity>(dto.Id);
53+
protected IEntity EntityFrom(ObjectBaseDTO dto) => dto.ObjectBase as IEntity;
5654

5755
public virtual ObjectPath SelectedEntityPath => SelectedEntity != null ? _objectPathFactory.CreateAbsoluteObjectPath(SelectedEntity) : null;
5856

@@ -86,29 +84,30 @@ private ITreeNode mapToNode(ObjectBaseDTO dto)
8684
case BuildingBlockDTO buildingBlockDTO:
8785
return getBuildingBlockNode(buildingBlockDTO);
8886
default:
89-
return _spatialStructureNodeMapper.MapFrom(dto);
87+
return _referenceNodeMapper.MapFrom(dto);
9088
}
9189
}
9290

93-
private HierarchicalStructureNode getBuildingBlockNode(BuildingBlockDTO buildingBlockDTO)
91+
private ITreeNode getBuildingBlockNode(BuildingBlockDTO buildingBlockDTO)
9492
{
95-
var buildingBlockNode = _spatialStructureNodeMapper.MapFrom(buildingBlockDTO);
96-
buildingBlockDTO.Builder.MapAllUsing(_spatialStructureNodeMapper).Each(buildingBlockNode.AddChild);
93+
var buildingBlockNode = _referenceNodeMapper.MapFrom(buildingBlockDTO);
94+
95+
buildingBlockDTO.Builder.MapAllUsing<ObjectBaseDTO, ITreeNode>(_referenceNodeMapper).Each(buildingBlockNode.AddChild);
9796
return buildingBlockNode;
9897
}
9998

100-
private HierarchicalStructureNode getSpatialStructureNode(SpatialStructureDTO spatialStructureDTO)
99+
private ITreeNode getSpatialStructureNode(SpatialStructureDTO spatialStructureDTO)
101100
{
102-
var spatialStructureNode = _spatialStructureNodeMapper.MapFrom(spatialStructureDTO);
101+
var spatialStructureNode = _referenceNodeMapper.MapFrom(spatialStructureDTO);
103102

104103
if (spatialStructureDTO.MoleculeProperties != null)
105-
spatialStructureNode.AddChild(_spatialStructureNodeMapper.MapFrom(spatialStructureDTO.MoleculeProperties));
104+
spatialStructureNode.AddChild(_referenceNodeMapper.MapFrom(spatialStructureDTO.MoleculeProperties));
106105

107106
if (spatialStructureDTO.TopContainers != null && spatialStructureDTO.TopContainers.Any())
108-
spatialStructureDTO.TopContainers.Each(dto => spatialStructureNode.AddChild(_spatialStructureNodeMapper.MapFrom(dto)));
107+
spatialStructureDTO.TopContainers.Each(dto => spatialStructureNode.AddChild(_referenceNodeMapper.MapFrom(dto)));
109108

110109
if (spatialStructureDTO.Neighborhoods != null)
111-
spatialStructureNode.AddChild(_spatialStructureNodeMapper.MapFrom(spatialStructureDTO.Neighborhoods));
110+
spatialStructureNode.AddChild(_referenceNodeMapper.MapFrom(spatialStructureDTO.Neighborhoods));
112111

113112
return spatialStructureNode;
114113
}

0 commit comments

Comments
 (0)