Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public class RootNetworkNodeInfo {

private Map<String, UUID> computationReports;

private Map<UUID, UUID> modificationReports;
private UUID modificationReportUuid;

private UUID shortCircuitAnalysisResultUuid;

Expand Down Expand Up @@ -59,7 +59,7 @@ public RootNetworkNodeInfoEntity toEntity() {
.id(id)
.variantId(variantId)
.computationReports(computationReports)
.modificationReports(modificationReports)
.modificationReportUuid(modificationReportUuid)
.shortCircuitAnalysisResultUuid(shortCircuitAnalysisResultUuid)
.oneBusShortCircuitAnalysisResultUuid(oneBusShortCircuitAnalysisResultUuid)
.loadFlowResultUuid(loadFlowResultUuid)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ public class NetworkModificationNode extends AbstractNode {

private NodeBuildStatus nodeBuildStatus;

private Map<String, UUID> computationsReports;

private UUID modificationReportUuid;

@Builder.Default
private NetworkModificationNodeType nodeType = NetworkModificationNodeType.CONSTRUCTION;

Expand All @@ -76,13 +80,9 @@ public void completeDtoFromRootNetworkNodeInfo(RootNetworkNodeInfoEntity rootNet
this.setStateEstimationResultUuid(rootNetworkNodeInfoEntity.getStateEstimationResultUuid());
this.setNodeBuildStatus(rootNetworkNodeInfoEntity.getNodeBuildStatus().toDto());
this.setComputationsReports(new HashMap<>(rootNetworkNodeInfoEntity.getComputationReports()));
this.setModificationReports(new HashMap<>(rootNetworkNodeInfoEntity.getModificationReports()));
this.setModificationReportUuid(rootNetworkNodeInfoEntity.getModificationReportUuid());
}

private Map<String, UUID> computationsReports;

private Map<UUID, UUID> modificationReports;

@Override
public NodeType getType() {
return NodeType.NETWORK_MODIFICATION;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,7 @@ public class RootNetworkNodeInfoEntity {
foreignKey = @ForeignKey(name = "rootNetworkNodeInfoEntity_computationReports_fk1"))
private Map<String, UUID> computationReports;

@ElementCollection
@CollectionTable(name = "modificationReports",
indexes = {@Index(name = "root_network_node_info_entity_modificationReports_idx1", columnList = "root_network_node_info_entity_id")},
foreignKey = @ForeignKey(name = "rootNetworkNodeInfoEntity_modificationReports_fk1"))
private Map<UUID, UUID> modificationReports;
private UUID modificationReportUuid;

@Column(name = "shortCircuitAnalysisResultUuid")
private UUID shortCircuitAnalysisResultUuid;
Expand Down Expand Up @@ -123,7 +119,7 @@ public RootNetworkNodeInfo toDto() {
return RootNetworkNodeInfo.builder()
.id(id)
.computationReports(computationReports)
.modificationReports(modificationReports)
.modificationReportUuid(modificationReportUuid)
.dynamicSimulationResultUuid(dynamicSimulationResultUuid)
.dynamicSecurityAnalysisResultUuid(dynamicSecurityAnalysisResultUuid)
.loadFlowResultUuid(loadFlowResultUuid)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -498,12 +498,11 @@ public void createBasicTree(StudyEntity studyEntity) {
.withAllResourceBundlesFromClasspath()
.withMessageTemplate("study.server.modificationNodeId")
.withUntypedValue("modificationNodeId", modificationNode.getId().toString()).build();
reportService.sendReport(getModificationReportUuid(networkModificationNode.getId(), firstRootNetworkUuid, networkModificationNode.getId()), reportNode);
UUID modificationReportUuid = UUID.randomUUID();
reportService.sendReport(modificationReportUuid, reportNode);

BuildInfos buildInfos = getBuildInfos(modificationNode.getId(), firstRootNetworkUuid);
Map<UUID, UUID> nodeUuidToReportUuid = buildInfos.getReportsInfos().stream().collect(Collectors.toMap(ReportInfos::nodeUuid, ReportInfos::reportUuid));
rootNetworkNodeInfoService.updateRootNetworkNode(networkModificationNode.getId(), firstRootNetworkUuid,
RootNetworkNodeInfo.builder().variantId(FIRST_VARIANT_ID).nodeBuildStatus(NodeBuildStatus.from(BuildStatus.BUILT)).modificationReports(nodeUuidToReportUuid).build());
RootNetworkNodeInfo.builder().variantId(FIRST_VARIANT_ID).nodeBuildStatus(NodeBuildStatus.from(BuildStatus.BUILT)).modificationReportUuid(modificationReportUuid).build());
}

@Transactional
Expand Down Expand Up @@ -754,7 +753,7 @@ public UUID getReportUuid(UUID nodeUuid, UUID rootNetworkUuid) {
if (nodeEntity.getType().equals(NodeType.ROOT)) {
return rootNetworkService.getRootReportUuid(rootNetworkUuid);
} else {
return rootNetworkNodeInfoService.getRootNetworkNodeInfo(nodeUuid, rootNetworkUuid).orElseThrow(() -> new StudyException(ROOT_NETWORK_NOT_FOUND)).getModificationReports().get(nodeUuid);
return rootNetworkNodeInfoService.getRootNetworkNodeInfo(nodeUuid, rootNetworkUuid).orElseThrow(() -> new StudyException(ROOT_NETWORK_NOT_FOUND)).getModificationReportUuid();
}
}

Expand Down Expand Up @@ -819,16 +818,6 @@ public Map<String, UUID> getComputationReports(UUID nodeUuid, UUID rootNetworkUu
return rootNetworkNodeInfoService.getRootNetworkNodeInfo(nodeUuid, rootNetworkUuid).orElseThrow(() -> new StudyException(NODE_NOT_FOUND)).getComputationReports();
}

@Transactional
public void setModificationReports(UUID nodeUuid, UUID rootNetworkUuid, Map<UUID, UUID> modificationReports) {
rootNetworkNodeInfoService.getRootNetworkNodeInfo(nodeUuid, rootNetworkUuid).ifPresent(tpNodeInfo -> tpNodeInfo.setModificationReports(modificationReports));
}

@Transactional
public Map<UUID, UUID> getModificationReports(UUID nodeUuid, UUID rootNetworkUuid) {
return rootNetworkNodeInfoService.getRootNetworkNodeInfo(nodeUuid, rootNetworkUuid).orElseThrow(() -> new StudyException(NODE_NOT_FOUND)).getModificationReports();
}

private void restoreNodeChildren(UUID studyId, UUID parentNodeId) {
getChildren(parentNodeId).forEach(nodeEntity -> {
NetworkModificationNodeInfoEntity modificationNodeToRestore = networkModificationNodeInfoRepository.findById(nodeEntity.getIdNode()).orElseThrow(() -> new StudyException(NODE_NOT_FOUND));
Expand All @@ -848,19 +837,14 @@ public List<NodeEntity> getAllNodes(UUID studyUuid) {
return nodesRepository.findAllByStudyId(studyUuid);
}

private UUID getModificationReportUuid(UUID nodeUuid, UUID rootNetworkUuid, UUID nodeToBuildUuid) {
return self.getModificationReports(nodeToBuildUuid, rootNetworkUuid).getOrDefault(nodeUuid, UUID.randomUUID());
}

private void getBuildInfos(NodeEntity nodeEntity, UUID rootNetworkUuid, BuildInfos buildInfos, UUID nodeToBuildUuid) {
private void getBuildInfos(NodeEntity nodeEntity, UUID rootNetworkUuid, BuildInfos buildInfos) {
AbstractNode node = getSimpleNode(nodeEntity.getIdNode());
if (node.getType() == NodeType.NETWORK_MODIFICATION) {
NetworkModificationNode modificationNode = (NetworkModificationNode) node;
RootNetworkNodeInfoEntity rootNetworkNodeInfoEntity = rootNetworkNodeInfoService.getRootNetworkNodeInfo(nodeEntity.getIdNode(), rootNetworkUuid).orElseThrow(() -> new StudyException(ROOT_NETWORK_NOT_FOUND));
if (!rootNetworkNodeInfoEntity.getNodeBuildStatus().toDto().isBuilt()) {
UUID reportUuid = getModificationReportUuid(nodeEntity.getIdNode(), rootNetworkUuid, nodeToBuildUuid);
buildInfos.insertModificationInfos(modificationNode.getModificationGroupUuid(), rootNetworkNodeInfoEntity.getModificationsUuidsToExclude(), new ReportInfos(reportUuid, modificationNode.getId()));
getBuildInfos(nodeEntity.getParentNode(), rootNetworkUuid, buildInfos, nodeToBuildUuid);
buildInfos.insertModificationInfos(modificationNode.getModificationGroupUuid(), rootNetworkNodeInfoEntity.getModificationsUuidsToExclude(), new ReportInfos(rootNetworkNodeInfoEntity.getModificationReportUuid(), modificationNode.getId()));
getBuildInfos(nodeEntity.getParentNode(), rootNetworkUuid, buildInfos);
} else {
buildInfos.setOriginVariantId(self.getVariantId(nodeEntity.getIdNode(), rootNetworkUuid));
}
Expand All @@ -876,7 +860,7 @@ public BuildInfos getBuildInfos(UUID nodeUuid, UUID rootNetworkUuid) {
throw new StudyException(BAD_NODE_TYPE, "The node " + entity.getIdNode() + " is not a modification node");
} else {
buildInfos.setDestinationVariantId(self.getVariantId(nodeUuid, rootNetworkUuid));
getBuildInfos(entity, rootNetworkUuid, buildInfos, nodeUuid);
getBuildInfos(entity, rootNetworkUuid, buildInfos);
}
}, () -> {
throw new StudyException(ELEMENT_NOT_FOUND);
Expand All @@ -889,7 +873,12 @@ public BuildInfos getBuildInfos(UUID nodeUuid, UUID rootNetworkUuid) {
public InvalidateNodeInfos invalidateNode(UUID nodeUuid, UUID rootNetworkUuid) {
NodeEntity nodeEntity = getNodeEntity(nodeUuid);

InvalidateNodeInfos invalidateNodeInfos = rootNetworkNodeInfoService.invalidateRootNetworkNode(nodeUuid, rootNetworkUuid, InvalidateNodeTreeParameters.ALL);
boolean isNodeBuilt = isNodeBuilt(rootNetworkUuid, nodeEntity);
boolean hasBuiltChildren = hasAnyBuiltChildren(nodeEntity, rootNetworkUuid);
InvalidateNodeInfos invalidateNodeInfos = rootNetworkNodeInfoService.invalidateRootNetworkNode(nodeUuid, rootNetworkUuid, InvalidateNodeTreeParameters.ALL, !hasBuiltChildren);
if (isNodeBuilt && !hasBuiltChildren) {
invalidateAscendantNodesReports(nodeUuid, rootNetworkUuid, invalidateNodeInfos);
}

fillIndexedNodeInfosToInvalidate(nodeEntity, rootNetworkUuid, invalidateNodeInfos);

Expand All @@ -898,19 +887,26 @@ public InvalidateNodeInfos invalidateNode(UUID nodeUuid, UUID rootNetworkUuid) {
return invalidateNodeInfos;
}

private void invalidateAscendantNodesReports(UUID nodeUuid, UUID rootNetworkUuid, InvalidateNodeInfos invalidateNodeInfos) {
List<UUID> allNodesToHighestParentInBuiltBranch = getAllNodesToHighestParentInBuiltBranch(nodeUuid, rootNetworkUuid);
rootNetworkNodeInfoService.getRootNetworkNodes(rootNetworkUuid, allNodesToHighestParentInBuiltBranch).forEach(entity -> invalidateNodeInfos.addReportUuid(entity.getModificationReportUuid()));
}

@Transactional
public InvalidateNodeInfos invalidateNodeTree(UUID nodeUuid, UUID rootNetworkUuid, InvalidateNodeTreeParameters invalidateTreeParameters) {
InvalidateNodeInfos invalidateNodeInfos = new InvalidateNodeInfos();

// Node status before invalidation
NodeEntity nodeEntity = getNodeEntity(nodeUuid);
boolean isModificationNode = nodeEntity.getType().equals(NodeType.NETWORK_MODIFICATION);
boolean isNodeBuilt = self.getNodeBuildStatus(nodeEntity.getIdNode(), rootNetworkUuid).isBuilt();
boolean isNodeBuilt = isNodeBuilt(rootNetworkUuid, nodeEntity);
boolean shouldInvalidateIndexedInfos = isNodeBuilt || hasAnyBuiltChildren(nodeEntity, rootNetworkUuid);

// First node
if (isModificationNode && !invalidateTreeParameters.isOnlyChildren()) {
invalidateNodeInfos = rootNetworkNodeInfoService.invalidateRootNetworkNode(nodeUuid, rootNetworkUuid, invalidateTreeParameters);
// if we enter this case node will be unbuilt anyway and its children too so we will have to remove reports too
invalidateNodeInfos = rootNetworkNodeInfoService.invalidateRootNetworkNode(nodeUuid, rootNetworkUuid, invalidateTreeParameters, true);
invalidateAscendantNodesReports(nodeUuid, rootNetworkUuid, invalidateNodeInfos);
}

// Invalidate indexed nodes
Expand All @@ -936,9 +932,14 @@ private InvalidateNodeInfos invalidateChildrenNodes(UUID nodeUuid, UUID rootNetw
.invalidationMode(InvalidateNodeTreeParameters.InvalidationMode.ALL)
.withBlockedNodeBuild(invalidateTreeParameters.withBlockedNodeBuild())
.build();
rootNetworkNodeInfoEntities.forEach(child ->
invalidateNodeInfos.add(rootNetworkNodeInfoService.invalidateRootNetworkNode(child, invalidateChildrenParameters))
);
rootNetworkNodeInfoEntities.forEach(child -> {
// InvalidationMode is ALL, so I know that all children will be unbuilt,
// so we have to remove reports for all children that are built or have built children
NodeEntity childNodeEntity = getNodeEntity(child.getNodeInfo().getIdNode());
if (isNodeBuilt(rootNetworkUuid, childNodeEntity) || hasAnyBuiltChildren(childNodeEntity, rootNetworkUuid)) {
invalidateNodeInfos.add(rootNetworkNodeInfoService.invalidateRootNetworkNode(child, invalidateChildrenParameters, true));
}
});

return invalidateNodeInfos;
}
Expand All @@ -959,13 +960,12 @@ public void invalidateBlockedBuildNodeTree(UUID rootNetworkUuid, UUID nodeUuid)
*/
private NodeEntity getSubTreeToInvalidateIndexedModifications(UUID nodeUuid, UUID rootNetworkUuid) {
Set<NodeEntity> descendantsChecked = new HashSet<>();

NodeEntity currentNode = getNodeEntity(nodeUuid);

while (currentNode.getParentNode() != null) {
NodeEntity parentNode = currentNode.getParentNode();
if (parentNode.getType().equals(NodeType.ROOT)
|| self.getNodeBuildStatus(parentNode.getIdNode(), rootNetworkUuid).isBuilt()
|| isNodeBuilt(rootNetworkUuid, parentNode)
|| hasAnyBuiltChildren(parentNode, rootNetworkUuid, descendantsChecked)) {
return currentNode;
}
Expand All @@ -976,13 +976,46 @@ private NodeEntity getSubTreeToInvalidateIndexedModifications(UUID nodeUuid, UUI
return currentNode;
}

/**
* Recursively iterate through *nodeUuid* parents until one of them match one of the following conditions :<br>
* - it is of type ROOT<br>
* - it is built<br>
* - one of its children is built
* @param nodeUuid reference node from where the recursion will start
* @param rootNetworkUuid root network necessary to get the build status of each node
* @return A set filled with IDs of all the parents of the current node that does not belong to a built branch in the tree
*/
private List<UUID> getAllNodesToHighestParentInBuiltBranch(UUID nodeUuid, UUID rootNetworkUuid) {
Set<NodeEntity> descendantsChecked = new HashSet<>();
NodeEntity currentNode = getNodeEntity(nodeUuid);
List<UUID> parents = new ArrayList<>();
boolean found = false;

while (!found && currentNode.getParentNode() != null) {
NodeEntity parentNode = currentNode.getParentNode();
if (parentNode.getType().equals(NodeType.ROOT)
|| isNodeBuilt(rootNetworkUuid, parentNode)
|| hasAnyBuiltChildren(parentNode, rootNetworkUuid, descendantsChecked)) {
found = true;
} else {
parents.add(parentNode.getIdNode());
currentNode = parentNode;
}
}

return parents;
}

// TODO Need to optimise with a only one recursive query
private boolean hasAnyBuiltChildren(NodeEntity node, UUID rootNetworkUuid) {
return hasAnyBuiltChildren(node, rootNetworkUuid, new HashSet<>());
return getChildren(node.getIdNode())
.stream()
.map(child -> hasAnyBuiltChildren(child, rootNetworkUuid, new HashSet<>()))
.anyMatch(el -> el.equals(Boolean.TRUE));
}

private boolean hasAnyBuiltChildren(NodeEntity node, UUID rootNetworkUuid, Set<NodeEntity> checkedChildren) {
if (self.getNodeBuildStatus(node.getIdNode(), rootNetworkUuid).isBuilt()) {
if (isNodeBuilt(rootNetworkUuid, node)) {
return true;
}
checkedChildren.add(node);
Expand All @@ -1000,7 +1033,7 @@ && hasAnyBuiltChildren(child, rootNetworkUuid, checkedChildren)) {
private void fillIndexedNodeInfosToInvalidate(NodeEntity nodeEntity, UUID rootNetworkUuid, InvalidateNodeInfos invalidateNodeInfos) {
// when manually invalidating a single node, if this node does not have any built children
// we need to invalidate indexed modifications up to it's last built parent, not included
if (hasAnyBuiltChildren(nodeEntity, rootNetworkUuid)) {
if (isNodeBuilt(rootNetworkUuid, nodeEntity) || hasAnyBuiltChildren(nodeEntity, rootNetworkUuid)) {
return;
}

Expand Down Expand Up @@ -1122,7 +1155,7 @@ private Optional<UUID> doGetParentNode(UUID nodeUuid, NodeType nodeType) {
public long countBuiltNodes(UUID studyUuid, UUID rootNetworkUuid) {
List<NodeEntity> nodes = nodesRepository.findAllByStudyIdAndTypeAndStashed(studyUuid, NodeType.NETWORK_MODIFICATION, false);
// perform N queries, but it's fast: 25 ms for 400 nodes
return nodes.stream().filter(n -> self.getNodeBuildStatus(n.getIdNode(), rootNetworkUuid).isBuilt()).count();
return nodes.stream().filter(n -> isNodeBuilt(rootNetworkUuid, n)).count();
}

private void fillIndexedNodeInfosToInvalidate(UUID parentNodeUuid, boolean includeParentNode, InvalidateNodeInfos invalidateNodeInfos) {
Expand Down Expand Up @@ -1158,4 +1191,8 @@ public NetworkModificationNode createNodeTree(@NonNull StudyEntity study, @NonNu

return nodeInfo;
}

private boolean isNodeBuilt(UUID rootNetworkUuid, NodeEntity nodeEntity) {
return self.getNodeBuildStatus(nodeEntity.getIdNode(), rootNetworkUuid).isBuilt();
}
}
Loading
Loading