diff --git a/src/main/java/org/gridsuite/study/server/dto/RootNetworkNodeInfo.java b/src/main/java/org/gridsuite/study/server/dto/RootNetworkNodeInfo.java index 5c6d80807..ae16ecf3e 100644 --- a/src/main/java/org/gridsuite/study/server/dto/RootNetworkNodeInfo.java +++ b/src/main/java/org/gridsuite/study/server/dto/RootNetworkNodeInfo.java @@ -28,7 +28,7 @@ public class RootNetworkNodeInfo { private Map computationReports; - private Map modificationReports; + private UUID modificationReportUuid; private UUID shortCircuitAnalysisResultUuid; @@ -59,7 +59,7 @@ public RootNetworkNodeInfoEntity toEntity() { .id(id) .variantId(variantId) .computationReports(computationReports) - .modificationReports(modificationReports) + .modificationReportUuid(modificationReportUuid) .shortCircuitAnalysisResultUuid(shortCircuitAnalysisResultUuid) .oneBusShortCircuitAnalysisResultUuid(oneBusShortCircuitAnalysisResultUuid) .loadFlowResultUuid(loadFlowResultUuid) diff --git a/src/main/java/org/gridsuite/study/server/networkmodificationtree/dto/NetworkModificationNode.java b/src/main/java/org/gridsuite/study/server/networkmodificationtree/dto/NetworkModificationNode.java index afb256077..be679d700 100644 --- a/src/main/java/org/gridsuite/study/server/networkmodificationtree/dto/NetworkModificationNode.java +++ b/src/main/java/org/gridsuite/study/server/networkmodificationtree/dto/NetworkModificationNode.java @@ -58,6 +58,10 @@ public class NetworkModificationNode extends AbstractNode { private NodeBuildStatus nodeBuildStatus; + private Map computationsReports; + + private UUID modificationReportUuid; + @Builder.Default private NetworkModificationNodeType nodeType = NetworkModificationNodeType.CONSTRUCTION; @@ -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 computationsReports; - - private Map modificationReports; - @Override public NodeType getType() { return NodeType.NETWORK_MODIFICATION; diff --git a/src/main/java/org/gridsuite/study/server/networkmodificationtree/entities/RootNetworkNodeInfoEntity.java b/src/main/java/org/gridsuite/study/server/networkmodificationtree/entities/RootNetworkNodeInfoEntity.java index 33f788f60..36dee0a84 100644 --- a/src/main/java/org/gridsuite/study/server/networkmodificationtree/entities/RootNetworkNodeInfoEntity.java +++ b/src/main/java/org/gridsuite/study/server/networkmodificationtree/entities/RootNetworkNodeInfoEntity.java @@ -63,11 +63,7 @@ public class RootNetworkNodeInfoEntity { foreignKey = @ForeignKey(name = "rootNetworkNodeInfoEntity_computationReports_fk1")) private Map 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 modificationReports; + private UUID modificationReportUuid; @Column(name = "shortCircuitAnalysisResultUuid") private UUID shortCircuitAnalysisResultUuid; @@ -123,7 +119,7 @@ public RootNetworkNodeInfo toDto() { return RootNetworkNodeInfo.builder() .id(id) .computationReports(computationReports) - .modificationReports(modificationReports) + .modificationReportUuid(modificationReportUuid) .dynamicSimulationResultUuid(dynamicSimulationResultUuid) .dynamicSecurityAnalysisResultUuid(dynamicSecurityAnalysisResultUuid) .loadFlowResultUuid(loadFlowResultUuid) diff --git a/src/main/java/org/gridsuite/study/server/service/NetworkModificationTreeService.java b/src/main/java/org/gridsuite/study/server/service/NetworkModificationTreeService.java index 877a02246..4b0efc6db 100644 --- a/src/main/java/org/gridsuite/study/server/service/NetworkModificationTreeService.java +++ b/src/main/java/org/gridsuite/study/server/service/NetworkModificationTreeService.java @@ -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 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 @@ -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(); } } @@ -819,16 +818,6 @@ public Map 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 modificationReports) { - rootNetworkNodeInfoService.getRootNetworkNodeInfo(nodeUuid, rootNetworkUuid).ifPresent(tpNodeInfo -> tpNodeInfo.setModificationReports(modificationReports)); - } - - @Transactional - public Map 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)); @@ -848,19 +837,14 @@ public List 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)); } @@ -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); @@ -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); @@ -898,6 +887,11 @@ public InvalidateNodeInfos invalidateNode(UUID nodeUuid, UUID rootNetworkUuid) { return invalidateNodeInfos; } + private void invalidateAscendantNodesReports(UUID nodeUuid, UUID rootNetworkUuid, InvalidateNodeInfos invalidateNodeInfos) { + List 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(); @@ -905,12 +899,14 @@ public InvalidateNodeInfos invalidateNodeTree(UUID nodeUuid, UUID rootNetworkUui // 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 @@ -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; } @@ -959,13 +960,12 @@ public void invalidateBlockedBuildNodeTree(UUID rootNetworkUuid, UUID nodeUuid) */ private NodeEntity getSubTreeToInvalidateIndexedModifications(UUID nodeUuid, UUID rootNetworkUuid) { Set 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; } @@ -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 :
+ * - it is of type ROOT
+ * - it is built
+ * - 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 getAllNodesToHighestParentInBuiltBranch(UUID nodeUuid, UUID rootNetworkUuid) { + Set descendantsChecked = new HashSet<>(); + NodeEntity currentNode = getNodeEntity(nodeUuid); + List 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 checkedChildren) { - if (self.getNodeBuildStatus(node.getIdNode(), rootNetworkUuid).isBuilt()) { + if (isNodeBuilt(rootNetworkUuid, node)) { return true; } checkedChildren.add(node); @@ -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; } @@ -1122,7 +1155,7 @@ private Optional doGetParentNode(UUID nodeUuid, NodeType nodeType) { public long countBuiltNodes(UUID studyUuid, UUID rootNetworkUuid) { List 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) { @@ -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(); + } } diff --git a/src/main/java/org/gridsuite/study/server/service/RootNetworkNodeInfoService.java b/src/main/java/org/gridsuite/study/server/service/RootNetworkNodeInfoService.java index 3d652dd8a..58907ab9e 100644 --- a/src/main/java/org/gridsuite/study/server/service/RootNetworkNodeInfoService.java +++ b/src/main/java/org/gridsuite/study/server/service/RootNetworkNodeInfoService.java @@ -40,7 +40,6 @@ import java.util.*; import java.util.concurrent.CompletableFuture; -import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -98,7 +97,7 @@ public RootNetworkNodeInfoService(RootNetworkNodeInfoRepository rootNetworkNodeI public void createRootNetworkLinks(@NonNull UUID studyUuid, @NonNull RootNetworkEntity rootNetworkEntity) { // For each network modification node (nodeInfoEntity) create a link with the root network networkModificationNodeInfoRepository.findAllByNodeStudyId(studyUuid).forEach(networkModificationNodeEntity -> { - RootNetworkNodeInfoEntity newRootNetworkNodeInfoEntity = createDefaultEntity(networkModificationNodeEntity.getId()); + RootNetworkNodeInfoEntity newRootNetworkNodeInfoEntity = createDefaultEntity(); addLink(networkModificationNodeEntity, rootNetworkEntity, newRootNetworkNodeInfoEntity); }); } @@ -106,7 +105,7 @@ public void createRootNetworkLinks(@NonNull UUID studyUuid, @NonNull RootNetwork public void createNodeLinks(@NonNull StudyEntity studyEntity, @NonNull NetworkModificationNodeInfoEntity modificationNodeInfoEntity) { // For each root network create a link with the node studyEntity.getRootNetworks().forEach(rootNetworkEntity -> { - RootNetworkNodeInfoEntity newRootNetworkNodeInfoEntity = createDefaultEntity(modificationNodeInfoEntity.getId()); + RootNetworkNodeInfoEntity newRootNetworkNodeInfoEntity = createDefaultEntity(); addLink(modificationNodeInfoEntity, rootNetworkEntity, newRootNetworkNodeInfoEntity); }); } @@ -117,22 +116,21 @@ public void duplicateNodeLinks(List sourceNodeLinks, // when duplicating a rootNetworkNodeInfoEntity, we need to keep modificationsToExclude // use correspondence map to use duplicate modification uuids RootNetworkNodeInfoEntity newRootNetworkNodeInfoEntity = createDefaultEntity( - destinationNodeInfoEntity.getId(), nodeLink.getModificationsUuidsToExclude().stream().map(originToDuplicateModificationUuidMap::get).collect(Collectors.toSet()) ); addLink(destinationNodeInfoEntity, originToDuplicateRootNetworkMap.get(nodeLink.getRootNetwork()), newRootNetworkNodeInfoEntity); }); } - private static RootNetworkNodeInfoEntity createDefaultEntity(UUID nodeUuid) { - return createDefaultEntity(nodeUuid, new HashSet<>()); + private static RootNetworkNodeInfoEntity createDefaultEntity() { + return createDefaultEntity(new HashSet<>()); } - private static RootNetworkNodeInfoEntity createDefaultEntity(UUID nodeUuid, Set modificationsToExclude) { + private static RootNetworkNodeInfoEntity createDefaultEntity(Set modificationsToExclude) { return RootNetworkNodeInfoEntity.builder() .nodeBuildStatus(NodeBuildStatusEmbeddable.from(BuildStatus.NOT_BUILT)) .variantId(UUID.randomUUID().toString()) - .modificationReports(new HashMap<>(Map.of(nodeUuid, UUID.randomUUID()))) + .modificationReportUuid(UUID.randomUUID()) .modificationsUuidsToExclude(modificationsToExclude) .blockedBuild(false) .build(); @@ -173,7 +171,7 @@ public void fillDeleteNodeInfo(UUID nodeUuid, DeleteNodeInfos deleteNodeInfos) { //get all rootnetworknodeinfo info linked to node List rootNetworkNodeInfoEntities = rootNetworkNodeInfoRepository.findAllWithRootNetworkByNodeInfoId(nodeUuid); rootNetworkNodeInfoEntities.forEach(rootNetworkNodeInfoEntity -> { - rootNetworkNodeInfoEntity.getModificationReports().forEach((key, value) -> deleteNodeInfos.addReportUuid(value)); + deleteNodeInfos.addReportUuid(rootNetworkNodeInfoEntity.getModificationReportUuid()); rootNetworkNodeInfoEntity.getComputationReports().forEach((key, value) -> deleteNodeInfos.addReportUuid(value)); String variantId = rootNetworkNodeInfoEntity.getVariantId(); @@ -234,12 +232,12 @@ public void fillDeleteNodeInfo(UUID nodeUuid, DeleteNodeInfos deleteNodeInfos) { }); } - public InvalidateNodeInfos invalidateRootNetworkNode(UUID nodeUuid, UUID rootNetworUuid, InvalidateNodeTreeParameters invalidateTreeParameters) { + public InvalidateNodeInfos invalidateRootNetworkNode(UUID nodeUuid, UUID rootNetworUuid, InvalidateNodeTreeParameters invalidateTreeParameters, boolean shouldRemoveModificationReports) { RootNetworkNodeInfoEntity rootNetworkNodeInfoEntity = rootNetworkNodeInfoRepository.findByNodeInfoIdAndRootNetworkId(nodeUuid, rootNetworUuid).orElseThrow(() -> new StudyException(ROOT_NETWORK_NOT_FOUND)); - return invalidateRootNetworkNode(rootNetworkNodeInfoEntity, invalidateTreeParameters); + return invalidateRootNetworkNode(rootNetworkNodeInfoEntity, invalidateTreeParameters, shouldRemoveModificationReports); } - public InvalidateNodeInfos invalidateRootNetworkNode(RootNetworkNodeInfoEntity rootNetworkNodeInfoEntity, InvalidateNodeTreeParameters invalidateTreeParameters) { + public InvalidateNodeInfos invalidateRootNetworkNode(RootNetworkNodeInfoEntity rootNetworkNodeInfoEntity, InvalidateNodeTreeParameters invalidateTreeParameters, boolean shouldRemoveModificationReports) { boolean notOnlyChildrenBuildStatus = !invalidateTreeParameters.isOnlyChildrenBuildStatus(); // Always update blocked build info @@ -249,13 +247,19 @@ public InvalidateNodeInfos invalidateRootNetworkNode(RootNetworkNodeInfoEntity r // No need to delete node results with a status different of "BUILT" if (!rootNetworkNodeInfoEntity.getNodeBuildStatus().toDto().isBuilt()) { - return new InvalidateNodeInfos(); + InvalidateNodeInfos invalidateNodeInfos = new InvalidateNodeInfos(); + if (shouldRemoveModificationReports) { + invalidateNodeInfos.addReportUuid(rootNetworkNodeInfoEntity.getModificationReportUuid()); + } + return invalidateNodeInfos; } InvalidateNodeInfos invalidateNodeInfos = getInvalidationComputationInfos(rootNetworkNodeInfoEntity, invalidateTreeParameters.computationsInvalidationMode()); if (notOnlyChildrenBuildStatus) { - rootNetworkNodeInfoEntity.getModificationReports().forEach((key, value) -> invalidateNodeInfos.addReportUuid(value)); + if (shouldRemoveModificationReports) { + invalidateNodeInfos.addReportUuid(rootNetworkNodeInfoEntity.getModificationReportUuid()); + } invalidateNodeInfos.addVariantId(rootNetworkNodeInfoEntity.getVariantId()); invalidateBuildStatus(rootNetworkNodeInfoEntity, invalidateNodeInfos); } @@ -268,7 +272,6 @@ public InvalidateNodeInfos invalidateRootNetworkNode(RootNetworkNodeInfoEntity r private static void invalidateBuildStatus(RootNetworkNodeInfoEntity rootNetworkNodeInfoEntity, InvalidateNodeInfos invalidateNodeInfos) { rootNetworkNodeInfoEntity.setNodeBuildStatus(NodeBuildStatusEmbeddable.from(BuildStatus.NOT_BUILT)); rootNetworkNodeInfoEntity.setVariantId(UUID.randomUUID().toString()); - rootNetworkNodeInfoEntity.setModificationReports(new HashMap<>(Map.of(rootNetworkNodeInfoEntity.getNodeInfo().getId(), UUID.randomUUID()))); invalidateNodeInfos.addNodeUuid(rootNetworkNodeInfoEntity.getNodeInfo().getIdNode()); } @@ -482,8 +485,8 @@ public void updateRootNetworkNode(UUID nodeUuid, UUID rootNetworkUuid, RootNetwo if (rootNetworkNodeInfo.getVoltageInitResultUuid() != null) { rootNetworkNodeInfoEntity.setVoltageInitResultUuid(rootNetworkNodeInfo.getVoltageInitResultUuid()); } - if (rootNetworkNodeInfo.getModificationReports() != null) { - rootNetworkNodeInfoEntity.setModificationReports(rootNetworkNodeInfo.getModificationReports()); + if (rootNetworkNodeInfo.getModificationReportUuid() != null) { + rootNetworkNodeInfoEntity.setModificationReportUuid(rootNetworkNodeInfo.getModificationReportUuid()); } } @@ -508,15 +511,14 @@ public Stream> getDeleteRootNetworkNodeInfosFutures(List public ModificationApplicationContext getNetworkModificationApplicationContext(UUID rootNetworkUuid, UUID nodeUuid, UUID networkUuid) { RootNetworkNodeInfoEntity rootNetworkNodeInfoEntity = rootNetworkNodeInfoRepository.findWithModificationsToExcludeByNodeInfoIdAndRootNetworkId(nodeUuid, rootNetworkUuid).orElseThrow(() -> new StudyException(ROOT_NETWORK_NOT_FOUND)); String variantId = rootNetworkNodeInfoEntity.getVariantId(); - UUID reportUuid = rootNetworkNodeInfoEntity.getModificationReports().get(nodeUuid); + UUID reportUuid = rootNetworkNodeInfoEntity.getModificationReportUuid(); return new ModificationApplicationContext(networkUuid, variantId, reportUuid, nodeUuid, rootNetworkNodeInfoEntity.getModificationsUuidsToExclude()); } private List getReportUuids(RootNetworkNodeInfo rootNetworkNodeInfo) { - return Stream.of( - rootNetworkNodeInfo.getModificationReports().values().stream(), + return Stream.concat( + Stream.of(rootNetworkNodeInfo.getModificationReportUuid()), rootNetworkNodeInfo.getComputationReports().values().stream()) - .flatMap(Function.identity()) .toList(); } diff --git a/src/main/java/org/gridsuite/study/server/service/StudyService.java b/src/main/java/org/gridsuite/study/server/service/StudyService.java index 38256ae66..72dc99535 100644 --- a/src/main/java/org/gridsuite/study/server/service/StudyService.java +++ b/src/main/java/org/gridsuite/study/server/service/StudyService.java @@ -1729,8 +1729,6 @@ public void buildNode(@NonNull UUID studyUuid, @NonNull UUID nodeUuid, @NonNull private void buildNode(@NonNull UUID studyUuid, @NonNull UUID nodeUuid, @NonNull UUID rootNetworkUuid, @NonNull String userId, AbstractWorkflowInfos workflowInfos) { assertCanBuildNode(studyUuid, rootNetworkUuid, userId); BuildInfos buildInfos = networkModificationTreeService.getBuildInfos(nodeUuid, rootNetworkUuid); - Map nodeUuidToReportUuid = buildInfos.getReportsInfos().stream().collect(Collectors.toMap(ReportInfos::nodeUuid, ReportInfos::reportUuid)); - networkModificationTreeService.setModificationReports(nodeUuid, rootNetworkUuid, nodeUuidToReportUuid); networkModificationTreeService.updateNodeBuildStatus(nodeUuid, rootNetworkUuid, NodeBuildStatus.from(BuildStatus.BUILDING)); try { networkModificationService.buildNode(nodeUuid, rootNetworkUuid, buildInfos, workflowInfos); @@ -2333,11 +2331,9 @@ private void checkStudyContainsNode(UUID studyUuid, UUID nodeUuid) { private ReportPage getParentNodesReportLogs(UUID nodeUuid, UUID rootNetworkUuid, String messageFilter, Set severityLevels, boolean paged, Pageable pageable) { List nodeIds = nodesTree(nodeUuid); - Map modificationReportsMap = networkModificationTreeService.getModificationReports(nodeUuid, rootNetworkUuid); List reportUuids = nodeIds.stream() - .map(nodeId -> modificationReportsMap.getOrDefault(nodeId, - networkModificationTreeService.getReportUuid(nodeId, rootNetworkUuid))) + .map(nodeId -> networkModificationTreeService.getReportUuid(nodeId, rootNetworkUuid)) .filter(Objects::nonNull) .toList(); return reportService.getPagedMultipleReportLogs(reportUuids, messageFilter, severityLevels, paged, pageable); @@ -2353,11 +2349,9 @@ public ReportPage getReportLogs(UUID nodeUuid, UUID rootNetworkUuid, UUID report private String getSearchTermMatchesInParentNodesFilteredLogs(UUID nodeUuid, UUID rootNetworkUuid, Set severityLevels, String messageFilter, String searchTerm, int pageSize) { List nodeIds = nodesTree(nodeUuid); - Map modificationReportsMap = networkModificationTreeService.getModificationReports(nodeUuid, rootNetworkUuid); List reportUuids = nodeIds.stream() - .map(nodeId -> modificationReportsMap.getOrDefault(nodeId, - networkModificationTreeService.getReportUuid(nodeId, rootNetworkUuid))) + .map(nodeId -> networkModificationTreeService.getReportUuid(nodeId, rootNetworkUuid)) .filter(Objects::nonNull) .toList(); return reportService.getSearchTermMatchesInMultipleFilteredLogs(reportUuids, severityLevels, messageFilter, searchTerm, pageSize); @@ -2374,10 +2368,9 @@ public String getSearchTermMatchesInFilteredLogs(UUID nodeUuid, UUID rootNetwork private Set getParentNodesAggregatedReportSeverities(UUID nodeUuid, UUID rootNetworkUuid) { List nodeIds = nodesTree(nodeUuid); Set severities = new HashSet<>(); - Map modificationReportsMap = networkModificationTreeService.getModificationReports(nodeUuid, rootNetworkUuid); for (UUID nodeId : nodeIds) { - UUID reportId = modificationReportsMap.getOrDefault(nodeId, networkModificationTreeService.getReportUuid(nodeId, rootNetworkUuid)); + UUID reportId = networkModificationTreeService.getReportUuid(nodeId, rootNetworkUuid); severities.addAll(reportService.getReportAggregatedSeverities(reportId)); } return severities; @@ -2421,10 +2414,9 @@ private List getNodeOnlyReport(UUID nodeUuid, UUID rootNetworkUuid, Set< private List getAllModificationReports(UUID nodeUuid, UUID rootNetworkUuid, Set severityLevels) { List nodeIds = nodesTree(nodeUuid); List modificationReports = new ArrayList<>(); - Map modificationReportsMap = networkModificationTreeService.getModificationReports(nodeUuid, rootNetworkUuid); for (UUID nodeId : nodeIds) { - UUID reportId = modificationReportsMap.getOrDefault(nodeId, networkModificationTreeService.getReportUuid(nodeId, rootNetworkUuid)); + UUID reportId = networkModificationTreeService.getReportUuid(nodeId, rootNetworkUuid); modificationReports.add(reportService.getReport(reportId, nodeId.toString(), severityLevels)); } diff --git a/src/main/resources/db/changelog/changesets/changelog_20250716T142255Z.xml b/src/main/resources/db/changelog/changesets/changelog_20250716T142255Z.xml new file mode 100644 index 000000000..62bff99e9 --- /dev/null +++ b/src/main/resources/db/changelog/changesets/changelog_20250716T142255Z.xml @@ -0,0 +1,29 @@ + + + + + + + + + + UPDATE root_network_node_info + SET modification_report_uuid = ( + SELECT mr.modification_reports + FROM modification_reports mr + WHERE mr.modification_reports_key = root_network_node_info.node_info_id + AND mr.root_network_node_info_entity_id = root_network_node_info.id + LIMIT 1 + ) + WHERE EXISTS ( + SELECT 1 + FROM modification_reports mr2 + WHERE mr2.modification_reports_key = root_network_node_info.node_info_id + AND mr2.root_network_node_info_entity_id = root_network_node_info.id + ); + + + + + + diff --git a/src/main/resources/db/changelog/db.changelog-master.yaml b/src/main/resources/db/changelog/db.changelog-master.yaml index dc7e63463..2c97778c2 100644 --- a/src/main/resources/db/changelog/db.changelog-master.yaml +++ b/src/main/resources/db/changelog/db.changelog-master.yaml @@ -334,4 +334,7 @@ databaseChangeLog: relativeToChangelogFile: true - include: file: changesets/changelog_20250723T152653Z.xml + relativeToChangelogFile: true + - include: + file: changesets/changelog_20250716T142255Z.xml relativeToChangelogFile: true \ No newline at end of file diff --git a/src/test/java/org/gridsuite/study/server/LoadFLowIntegrationTest.java b/src/test/java/org/gridsuite/study/server/LoadFLowIntegrationTest.java index f03371d84..a349d9161 100644 --- a/src/test/java/org/gridsuite/study/server/LoadFLowIntegrationTest.java +++ b/src/test/java/org/gridsuite/study/server/LoadFLowIntegrationTest.java @@ -302,7 +302,7 @@ private UUID insertNode(StudyEntity study, String variantId, UUID reportUuid, No // We can't use the method RootNetworkNodeInfoService::createNodeLinks because there is no transaction in a session private void createNodeLinks(RootNetworkEntity rootNetworkEntity, NetworkModificationNodeInfoEntity modificationNodeInfoEntity, String variantId, UUID reportUuid, BuildStatus buildStatus) { - RootNetworkNodeInfoEntity rootNetworkNodeInfoEntity = RootNetworkNodeInfoEntity.builder().variantId(variantId).modificationReports(Map.of(modificationNodeInfoEntity.getId(), reportUuid)).nodeBuildStatus(NodeBuildStatus.from(buildStatus).toEntity()).blockedBuild(false).build(); + RootNetworkNodeInfoEntity rootNetworkNodeInfoEntity = RootNetworkNodeInfoEntity.builder().variantId(variantId).modificationReportUuid(reportUuid).nodeBuildStatus(NodeBuildStatus.from(buildStatus).toEntity()).blockedBuild(false).build(); modificationNodeInfoEntity.addRootNetworkNodeInfo(rootNetworkNodeInfoEntity); rootNetworkEntity.addRootNetworkNodeInfo(rootNetworkNodeInfoEntity); rootNetworkNodeInfoRepository.save(rootNetworkNodeInfoEntity); diff --git a/src/test/java/org/gridsuite/study/server/ModificationIndexationTest.java b/src/test/java/org/gridsuite/study/server/ModificationIndexationTest.java index 75279b4fa..e9358f0d7 100644 --- a/src/test/java/org/gridsuite/study/server/ModificationIndexationTest.java +++ b/src/test/java/org/gridsuite/study/server/ModificationIndexationTest.java @@ -93,7 +93,7 @@ void testInvalidateBuiltNodeAndItsChildren() { node3.getModificationGroupUuid() )); - SQLStatementCountValidator.assertSelectCount(17); + SQLStatementCountValidator.assertSelectCount(23); } @Test @@ -105,7 +105,7 @@ void testInvalidateNotBuiltNodeAndItsChildren() { node5.getModificationGroupUuid() )); - SQLStatementCountValidator.assertSelectCount(17); + SQLStatementCountValidator.assertSelectCount(23); } @Test @@ -116,7 +116,7 @@ void testInvalidateBuiltNodeChildrenOnly() { node5.getModificationGroupUuid() )); - SQLStatementCountValidator.assertSelectCount(8); + SQLStatementCountValidator.assertSelectCount(17); } @Test @@ -128,7 +128,7 @@ void testInvalidateNotBuiltNodeChildrenOnly() { node3.getModificationGroupUuid() )); - SQLStatementCountValidator.assertSelectCount(17); + SQLStatementCountValidator.assertSelectCount(23); } @Test @@ -137,7 +137,7 @@ void testInvalidateBuiltNodeOnlyWithBuiltChildren() { assertThat(invalidateNodeInfos.getGroupUuids()).isEmpty(); - SQLStatementCountValidator.assertSelectCount(8); + SQLStatementCountValidator.assertSelectCount(9); } @Test @@ -149,7 +149,7 @@ void testInvalidateBuiltNodeOnlyWithoutBuiltChildren() { node3.getModificationGroupUuid() )); - SQLStatementCountValidator.assertSelectCount(19); + SQLStatementCountValidator.assertSelectCount(27); } private void createStudyAndNodesWithIndexedModification() { diff --git a/src/test/java/org/gridsuite/study/server/NetworkModificationTest.java b/src/test/java/org/gridsuite/study/server/NetworkModificationTest.java index b5415ffec..324ae180b 100644 --- a/src/test/java/org/gridsuite/study/server/NetworkModificationTest.java +++ b/src/test/java/org/gridsuite/study/server/NetworkModificationTest.java @@ -594,7 +594,7 @@ void testBuild() throws Exception { } @Test - void testLocalBuildValue() throws Exception { + void testLocalBuildValue(final MockWebServer server) throws Exception { StudyEntity studyEntity = insertDummyStudy(UUID.fromString(NETWORK_UUID_STRING), CASE_UUID, "UCTE"); UUID rootNetworkUuid = studyEntity.getFirstRootNetwork().getId(); UUID studyNameUserIdUuid = studyEntity.getId(); @@ -664,6 +664,9 @@ void testLocalBuildValue() throws Exception { //Build modification node 2, local status should be BUILT and computed one should be BUILT_WITH_ERRORS assertEquals(BuildStatus.BUILT, networkModificationTreeService.getNodeBuildStatus(modificationNode2Uuid, rootNetworkUuid).getLocalBuildStatus()); assertEquals(BuildStatus.BUILT_WITH_ERROR, networkModificationTreeService.getNodeBuildStatus(modificationNode2Uuid, rootNetworkUuid).getGlobalBuildStatus()); + + Set requests = TestUtils.getRequestsWithBodyDone(1, server); + assertTrue(requests.stream().anyMatch(r -> r.getPath().matches("/v1/reports"))); } @Test @@ -761,7 +764,7 @@ void testNetworkModificationSwitch(final MockWebServer server) throws Exception modificationBody = Pair.of(bodyJson, List.of(rootNetworkNodeInfoService.getNetworkModificationApplicationContext(firstRootNetworkUuid, modificationNode1Uuid, NETWORK_UUID))); wireMockUtils.verifyNetworkModificationPostWithVariant(stubPostId, getModificationContextJsonString(mapper, modificationBody)); - Set requests = TestUtils.getRequestsWithBodyDone(1, server); + Set requests = TestUtils.getRequestsWithBodyDone(3, server); assertTrue(requests.stream().anyMatch(r -> r.getPath().matches("/v1/reports"))); // modificationNode2 is still built @@ -772,7 +775,7 @@ void testNetworkModificationSwitch(final MockWebServer server) throws Exception } @Test - void testNetworkModificationEquipment() throws Exception { + void testNetworkModificationEquipment(final MockWebServer server) throws Exception { MvcResult mvcResult; String resultAsString; String userId = "userId"; @@ -831,10 +834,13 @@ void testNetworkModificationEquipment() throws Exception { checkElementUpdatedMessageSent(studyNameUserIdUuid, userId); modificationBody = Pair.of(bodyJson, List.of(rootNetworkNodeInfoService.getNetworkModificationApplicationContext(firstRootNetworkUuid, modificationNodeUuid2, NETWORK_UUID))); wireMockUtils.verifyNetworkModificationPostWithVariant(stubPostId, getModificationContextJsonString(mapper, modificationBody)); + + Set requests = TestUtils.getRequestsWithBodyDone(1, server); + assertTrue(requests.stream().anyMatch(r -> r.getPath().matches("/v1/reports"))); } @Test - void testCreateGenerator() throws Exception { + void testCreateGenerator(final MockWebServer server) throws Exception { String userId = "userId"; StudyEntity studyEntity = insertDummyStudy(UUID.fromString(NETWORK_UUID_STRING), CASE_UUID, "UCTE"); UUID studyNameUserIdUuid = studyEntity.getId(); @@ -924,10 +930,13 @@ void testCreateGenerator() throws Exception { .content(bodyJsonCreateBis).contentType(MediaType.APPLICATION_JSON) .header(USER_ID_HEADER, userId)) .andExpect(status().isForbidden()); + + Set requests = TestUtils.getRequestsWithBodyDone(1, server); + assertTrue(requests.stream().anyMatch(r -> r.getPath().matches("/v1/reports"))); } @Test - void testCreateShuntsCompensator() throws Exception { + void testCreateShuntsCompensator(final MockWebServer server) throws Exception { String userId = "userId"; StudyEntity studyEntity = insertDummyStudy(UUID.fromString(NETWORK_UUID_STRING), CASE_UUID, "UCTE"); UUID studyNameUserIdUuid = studyEntity.getId(); @@ -979,10 +988,13 @@ void testCreateShuntsCompensator() throws Exception { .content(createShuntCompensatorAttributes2).contentType(MediaType.APPLICATION_JSON) .header(USER_ID_HEADER, userId)) .andExpect(status().isForbidden()); + + Set requests = TestUtils.getRequestsWithBodyDone(1, server); + assertTrue(requests.stream().anyMatch(r -> r.getPath().matches("/v1/reports"))); } @Test - void testCreateLine() throws Exception { + void testCreateLine(final MockWebServer server) throws Exception { String userId = "userId"; StudyEntity studyEntity = insertDummyStudy(UUID.fromString(NETWORK_UUID_STRING), CASE_UUID, "UCTE"); UUID studyNameUserIdUuid = studyEntity.getId(); @@ -1068,10 +1080,13 @@ void testCreateLine() throws Exception { .content(createLineAttributes2).contentType(MediaType.APPLICATION_JSON) .header(USER_ID_HEADER, userId)) .andExpect(status().isForbidden()); + + Set requests = TestUtils.getRequestsWithBodyDone(1, server); + assertTrue(requests.stream().anyMatch(r -> r.getPath().matches("/v1/reports"))); } @Test - void testCreateTwoWindingsTransformer() throws Exception { + void testCreateTwoWindingsTransformer(final MockWebServer server) throws Exception { String userId = "userId"; StudyEntity studyEntity = insertDummyStudy(UUID.fromString(NETWORK_UUID_STRING), CASE_UUID, "UCTE"); UUID studyNameUserIdUuid = studyEntity.getId(); @@ -1140,6 +1155,9 @@ void testCreateTwoWindingsTransformer() throws Exception { .content(createTwoWindingsTransformerAttributes2).contentType(MediaType.APPLICATION_JSON) .header(USER_ID_HEADER, userId)) .andExpect(status().isForbidden()); + + Set requests = TestUtils.getRequestsWithBodyDone(1, server); + assertTrue(requests.stream().anyMatch(r -> r.getPath().matches("/v1/reports"))); } @Test @@ -1189,7 +1207,7 @@ void deleteModificationRequest() throws Exception { } @Test - void testUpdateLines() throws Exception { + void testUpdateLines(final MockWebServer server) throws Exception { String userId = "userId"; StudyEntity studyEntity = insertDummyStudy(UUID.fromString(NETWORK_UUID_STRING), CASE_UUID, "UCTE"); UUID studyNameUserIdUuid = studyEntity.getId(); @@ -1340,10 +1358,13 @@ void testUpdateLines() throws Exception { checkElementUpdatedMessageSent(studyNameUserIdUuid, userId); modificationBody = Pair.of(bodyJsonCreate9, List.of(rootNetworkNodeInfoService.getNetworkModificationApplicationContext(firstRootNetworkUuid, modificationNode2Uuid, NETWORK_UUID))); wireMockUtils.verifyNetworkModificationPostWithVariant(stubPostId, getModificationContextJsonString(mapper, modificationBody)); + + Set requests = TestUtils.getRequestsWithBodyDone(9, server); + assertTrue(requests.stream().anyMatch(r -> r.getPath().matches("/v1/reports"))); } @Test - void testCreateLoad() throws Exception { + void testCreateLoad(final MockWebServer server) throws Exception { String userId = "userId"; StudyEntity studyEntity = insertDummyStudy(UUID.fromString(NETWORK_UUID_STRING), CASE_UUID, "UCTE"); UUID studyNameUserIdUuid = studyEntity.getId(); @@ -1416,10 +1437,13 @@ void testCreateLoad() throws Exception { .content(createLoadAttributes2).contentType(MediaType.APPLICATION_JSON) .header(USER_ID_HEADER, userId)) .andExpect(status().isForbidden()); + + Set requests = TestUtils.getRequestsWithBodyDone(3, server); + assertTrue(requests.stream().anyMatch(r -> r.getPath().matches("/v1/reports"))); } @Test - void testModifyLoad() throws Exception { + void testModifyLoad(final MockWebServer server) throws Exception { String userId = "userId"; StudyEntity studyEntity = insertDummyStudy(UUID.fromString(NETWORK_UUID_STRING), CASE_UUID, "UCTE"); UUID studyNameUserIdUuid = studyEntity.getId(); @@ -1477,10 +1501,13 @@ void testModifyLoad() throws Exception { checkEquipmentUpdatingFinishedMessagesReceived(studyNameUserIdUuid, modificationNodeUuid); checkElementUpdatedMessageSent(studyNameUserIdUuid, userId); wireMockUtils.verifyNetworkModificationPut(stubPutId, MODIFICATION_UUID, loadAttributesUpdated); + + Set requests = TestUtils.getRequestsWithBodyDone(3, server); + assertTrue(requests.stream().anyMatch(r -> r.getPath().matches("/v1/reports"))); } @Test - void testModifyEquipment() throws Exception { + void testModifyEquipment(final MockWebServer server) throws Exception { String userId = "userId"; StudyEntity studyEntity = insertDummyStudy(UUID.fromString(NETWORK_UUID_STRING), CASE_UUID, "UCTE"); UUID studyNameUserIdUuid = studyEntity.getId(); @@ -1535,10 +1562,13 @@ void testModifyEquipment() throws Exception { checkEquipmentUpdatingFinishedMessagesReceived(studyNameUserIdUuid, modificationNodeUuid); checkElementUpdatedMessageSent(studyNameUserIdUuid, userId); wireMockUtils.verifyNetworkModificationPut(stubPutId, MODIFICATION_UUID, generatorAttributesUpdated); + + Set requests = TestUtils.getRequestsWithBodyDone(3, server); + assertTrue(requests.stream().anyMatch(r -> r.getPath().matches("/v1/reports"))); } @Test - void testCreateSubstation() throws Exception { + void testCreateSubstation(final MockWebServer server) throws Exception { String userId = "userId"; StudyEntity studyEntity = insertDummyStudy(UUID.fromString(NETWORK_UUID_STRING), CASE_UUID, "UCTE"); UUID studyNameUserIdUuid = studyEntity.getId(); @@ -1607,10 +1637,13 @@ void testCreateSubstation() throws Exception { .content(createSubstationAttributes2).contentType(MediaType.APPLICATION_JSON) .header(USER_ID_HEADER, userId)) .andExpect(status().isForbidden()); + + Set requests = TestUtils.getRequestsWithBodyDone(3, server); + assertTrue(requests.stream().anyMatch(r -> r.getPath().matches("/v1/reports"))); } @Test - void testCreateVoltageLevel() throws Exception { + void testCreateVoltageLevel(final MockWebServer server) throws Exception { String userId = "userId"; StudyEntity studyEntity = insertDummyStudy(UUID.fromString(NETWORK_UUID_STRING), CASE_UUID, "UCTE"); UUID studyNameUserIdUuid = studyEntity.getId(); @@ -1681,10 +1714,13 @@ void testCreateVoltageLevel() throws Exception { .content(createVoltageLevelAttributes2).contentType(MediaType.APPLICATION_JSON) .header(USER_ID_HEADER, userId)) .andExpect(status().isForbidden()); + + Set requests = TestUtils.getRequestsWithBodyDone(3, server); + assertTrue(requests.stream().anyMatch(r -> r.getPath().matches("/v1/reports"))); } @Test - void testLineSplitWithVoltageLevel() throws Exception { + void testLineSplitWithVoltageLevel(final MockWebServer server) throws Exception { String userId = "userId"; StudyEntity studyEntity = insertDummyStudy(UUID.fromString(NETWORK_UUID_STRING), CASE_UUID, "UCTE"); UUID studyNameUserIdUuid = studyEntity.getId(); @@ -1752,10 +1788,13 @@ void testLineSplitWithVoltageLevel() throws Exception { checkEquipmentUpdatingFinishedMessagesReceived(studyNameUserIdUuid, modificationNodeUuid); wireMockUtils.verifyNetworkModificationPost(stubPostId, modificationBodyJson); wireMockUtils.verifyNetworkModificationPut(stubPutId, MODIFICATION_UUID, badBody); + + Set requests = TestUtils.getRequestsWithBodyDone(3, server); + assertTrue(requests.stream().anyMatch(r -> r.getPath().matches("/v1/reports"))); } @Test - void testLineAttachToVoltageLevel() throws Exception { + void testLineAttachToVoltageLevel(final MockWebServer server) throws Exception { String userId = "userId"; StudyEntity studyEntity = insertDummyStudy(UUID.fromString(NETWORK_UUID_STRING), CASE_UUID, "UCTE"); UUID studyNameUserIdUuid = studyEntity.getId(); @@ -1792,10 +1831,13 @@ void testLineAttachToVoltageLevel() throws Exception { checkEquipmentUpdatingFinishedMessagesReceived(studyNameUserIdUuid, modificationNodeUuid); checkElementUpdatedMessageSent(studyNameUserIdUuid, userId); wireMockUtils.verifyNetworkModificationPut(stubPutId, MODIFICATION_UUID, createLineAttachToVoltageLevelAttributes); + + Set requests = TestUtils.getRequestsWithBodyDone(2, server); + assertTrue(requests.stream().anyMatch(r -> r.getPath().matches("/v1/reports"))); } @Test - void testLinesAttachToSplitLines() throws Exception { + void testLinesAttachToSplitLines(final MockWebServer server) throws Exception { String userId = "userId"; StudyEntity studyEntity = insertDummyStudy(UUID.fromString(NETWORK_UUID_STRING), CASE_UUID, "UCTE"); UUID studyNameUserIdUuid = studyEntity.getId(); @@ -1847,6 +1889,9 @@ void testLinesAttachToSplitLines() throws Exception { checkEquipmentUpdatingFinishedMessagesReceived(studyNameUserIdUuid, modificationNodeUuid); wireMockUtils.verifyNetworkModificationPost(stubPostId, modificationBodyJson); wireMockUtils.verifyNetworkModificationPut(stubPutId, MODIFICATION_UUID, badBody); + + Set requests = TestUtils.getRequestsWithBodyDone(3, server); + assertTrue(requests.stream().anyMatch(r -> r.getPath().matches("/v1/reports"))); } @ParameterizedTest @@ -1909,7 +1954,7 @@ void testScaling(ModificationType scalingType) throws Exception { } @Test - void testDeleteVoltageLevelOnline() throws Exception { + void testDeleteVoltageLevelOnline(final MockWebServer server) throws Exception { String userId = "userId"; StudyEntity studyEntity = insertDummyStudy(UUID.fromString(NETWORK_UUID_STRING), CASE_UUID, "UCTE"); UUID studyNameUserIdUuid = studyEntity.getId(); @@ -1959,10 +2004,13 @@ void testDeleteVoltageLevelOnline() throws Exception { checkEquipmentUpdatingMessagesReceived(studyNameUserIdUuid, modificationNodeUuid); checkEquipmentUpdatingFinishedMessagesReceived(studyNameUserIdUuid, modificationNodeUuid); wireMockUtils.verifyNetworkModificationPut(stubIdPutErr, MODIFICATION_UUID, badBody); + + Set requests = TestUtils.getRequestsWithBodyDone(3, server); + assertTrue(requests.stream().anyMatch(r -> r.getPath().matches("/v1/reports"))); } @Test - void testDeleteAttachingline() throws Exception { + void testDeleteAttachingline(final MockWebServer server) throws Exception { String userId = "userId"; StudyEntity studyEntity = insertDummyStudy(UUID.fromString(NETWORK_UUID_STRING), CASE_UUID, "UCTE"); UUID studyNameUserIdUuid = studyEntity.getId(); @@ -2013,10 +2061,13 @@ void testDeleteAttachingline() throws Exception { checkEquipmentUpdatingMessagesReceived(studyNameUserIdUuid, modificationNodeUuid); checkEquipmentUpdatingFinishedMessagesReceived(studyNameUserIdUuid, modificationNodeUuid); wireMockUtils.verifyNetworkModificationPut(stubIdPutErr, MODIFICATION_UUID, badBody); + + Set requests = TestUtils.getRequestsWithBodyDone(3, server); + assertTrue(requests.stream().anyMatch(r -> r.getPath().matches("/v1/reports"))); } @Test - void testReorderModification() throws Exception { + void testReorderModification(final MockWebServer server) throws Exception { String userId = "userId"; StudyEntity studyEntity = insertDummyStudy(UUID.fromString(NETWORK_UUID_STRING), CASE_UUID, "UCTE"); UUID studyNameUserIdUuid = studyEntity.getId(); @@ -2068,6 +2119,9 @@ void testReorderModification() throws Exception { "build", WireMock.equalTo("false"), "before", WireMock.equalTo(modification2.toString())), expectedBodyStr); + + Set requests = TestUtils.getRequestsWithBodyDone(2, server); + assertTrue(requests.stream().anyMatch(r -> r.getPath().matches("/v1/reports"))); } @Test @@ -2095,7 +2149,7 @@ void testReorderModificationErrorCase() throws Exception { } @Test - void testDuplicateModification() throws Exception { + void testDuplicateModification(final MockWebServer server) throws Exception { String userId = "userId"; StudyEntity studyEntity = insertDummyStudy(UUID.fromString(NETWORK_UUID_STRING), CASE_UUID, "UCTE"); UUID studyUuid = studyEntity.getId(); @@ -2162,6 +2216,9 @@ void testDuplicateModification() throws Exception { wireMockUtils.verifyPutRequestWithUrlMatching(groupStubId, url, Map.of( "action", WireMock.equalTo("COPY")), expectedBody); + + Set requests = TestUtils.getRequestsWithBodyDone(1, server); + assertTrue(requests.stream().anyMatch(r -> r.getPath().matches("/v1/reports"))); } @Test @@ -2193,7 +2250,7 @@ void testDuplicateModificationErrorCase() throws Exception { } @Test - void testCutAndPasteModification() throws Exception { + void testCutAndPasteModification(final MockWebServer server) throws Exception { String userId = "userId"; StudyEntity studyEntity = insertDummyStudy(UUID.fromString(NETWORK_UUID_STRING), CASE_UUID, "UCTE"); UUID studyUuid = studyEntity.getId(); @@ -2267,6 +2324,9 @@ void testCutAndPasteModification() throws Exception { .content(modificationUuidListBody) .header(USER_ID_HEADER, "userId")) .andExpect(status().isBadRequest()); + + Set requests = TestUtils.getRequestsWithBodyDone(3, server); + assertTrue(requests.stream().anyMatch(r -> r.getPath().matches("/v1/reports"))); } @Test @@ -2299,7 +2359,7 @@ void testCutAndPasteModificationErrorCase() throws Exception { } @Test - void testDeleteEquipment() throws Exception { + void testDeleteEquipment(final MockWebServer server) throws Exception { String userId = "userId"; StudyEntity studyEntity = insertDummyStudy(UUID.fromString(NETWORK_UUID_STRING), CASE_UUID, "UCTE"); UUID studyNameUserIdUuid = studyEntity.getId(); @@ -2361,6 +2421,9 @@ void testDeleteEquipment() throws Exception { checkEquipmentUpdatingFinishedMessagesReceived(studyNameUserIdUuid, modificationNode1Uuid); checkElementUpdatedMessageSent(studyNameUserIdUuid, userId); wireMockUtils.verifyNetworkModificationPut(stubPutId, MODIFICATION_UUID, bodyJson); + + Set requests = TestUtils.getRequestsWithBodyDone(3, server); + assertTrue(requests.stream().anyMatch(r -> r.getPath().matches("/v1/reports"))); } @Test @@ -2533,7 +2596,7 @@ void testRemoveLoadFlowComputationReport(final MockWebServer server) throws Exce } @Test - void testUpdateOfBuildStatus() throws Exception { + void testUpdateOfBuildStatus(final MockWebServer server) throws Exception { StudyEntity studyEntity = insertDummyStudy(UUID.fromString(NETWORK_UUID_STRING), CASE_UUID, "UCTE"); UUID firstRootNetworkUuid = studyTestUtils.getOneRootNetworkUuid(studyEntity.getId()); UUID studyNameUserIdUuid = studyEntity.getId(); @@ -2616,6 +2679,9 @@ void testUpdateOfBuildStatus() throws Exception { assertEquals(BuildStatus.BUILT_WITH_ERROR, networkModificationTreeService.getNodeBuildStatus(modificationNodeUuid, firstRootNetworkUuid).getGlobalBuildStatus()); modificationBody = Pair.of(jsonCreateLoadInfos, List.of(rootNetworkNodeInfoService.getNetworkModificationApplicationContext(firstRootNetworkUuid, modificationNodeUuid, NETWORK_UUID))); wireMockUtils.verifyNetworkModificationPostWithVariant(stubPostId, getModificationContextJsonString(mapper, modificationBody)); + + Set requests = TestUtils.getRequestsWithBodyDone(1, server); + assertTrue(requests.stream().anyMatch(r -> r.getPath().matches("/v1/reports"))); } private void testBuildWithNodeUuid(UUID studyUuid, UUID nodeUuid, UUID rootNetworkUuid, String userId, UUID profileStubId) throws Exception { @@ -2933,7 +2999,7 @@ private NetworkModificationNode createNetworkModificationNode(UUID studyUuid, UU } @Test - void testCreateModificationWithErrors() throws Exception { + void testCreateModificationWithErrors(final MockWebServer server) throws Exception { StudyEntity studyEntity = insertDummyStudy(UUID.fromString(NETWORK_UUID_STRING), CASE_UUID, "UCTE"); UUID studyNameUserIdUuid = studyEntity.getId(); UUID firstRootNetworkUuid = studyTestUtils.getOneRootNetworkUuid(studyNameUserIdUuid); @@ -2993,6 +3059,9 @@ void testCreateModificationWithErrors() throws Exception { checkEquipmentCreatingMessagesReceived(studyNameUserIdUuid, modificationNodeUuid); checkEquipmentUpdatingFinishedMessagesReceived(studyNameUserIdUuid, modificationNodeUuid); wireMockUtils.verifyNetworkModificationPost(stubId, modificationBodyJson); + + Set requests = TestUtils.getRequestsWithBodyDone(4, server); + assertTrue(requests.stream().anyMatch(r -> r.getPath().matches("/v1/reports"))); } private void checkElementUpdatedMessageSent(UUID elementUuid, String userId) { diff --git a/src/test/java/org/gridsuite/study/server/NetworkModificationUnitTest.java b/src/test/java/org/gridsuite/study/server/NetworkModificationUnitTest.java index 2e16b343a..76528e966 100644 --- a/src/test/java/org/gridsuite/study/server/NetworkModificationUnitTest.java +++ b/src/test/java/org/gridsuite/study/server/NetworkModificationUnitTest.java @@ -50,7 +50,6 @@ import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.List; -import java.util.Map; import java.util.TreeSet; import java.util.UUID; import java.util.stream.Collectors; @@ -336,7 +335,7 @@ private NodeEntity insertNode(StudyEntity study, UUID nodeId, NetworkModificatio // We can't use the method RootNetworkNodeInfoService::createNodeLinks because there is no transaction in a session private void createNodeLinks(RootNetworkEntity rootNetworkEntity, NetworkModificationNodeInfoEntity modificationNodeInfoEntity, String variantId, UUID reportUuid, BuildStatus buildStatus) { - RootNetworkNodeInfoEntity rootNetworkNodeInfoEntity = RootNetworkNodeInfoEntity.builder().variantId(variantId).modificationReports(Map.of(modificationNodeInfoEntity.getId(), reportUuid)).nodeBuildStatus(NodeBuildStatus.from(buildStatus).toEntity()).build(); + RootNetworkNodeInfoEntity rootNetworkNodeInfoEntity = RootNetworkNodeInfoEntity.builder().variantId(variantId).modificationReportUuid(reportUuid).nodeBuildStatus(NodeBuildStatus.from(buildStatus).toEntity()).build(); modificationNodeInfoEntity.addRootNetworkNodeInfo(rootNetworkNodeInfoEntity); rootNetworkEntity.addRootNetworkNodeInfo(rootNetworkNodeInfoEntity); rootNetworkNodeInfoRepository.save(rootNetworkNodeInfoEntity); diff --git a/src/test/java/org/gridsuite/study/server/StudyTest.java b/src/test/java/org/gridsuite/study/server/StudyTest.java index f088b9133..58e0ccb0b 100644 --- a/src/test/java/org/gridsuite/study/server/StudyTest.java +++ b/src/test/java/org/gridsuite/study/server/StudyTest.java @@ -2153,6 +2153,9 @@ void testCutAndPasteNode(final MockWebServer mockWebServer) throws Exception { && nodeEntity.getParentNode().getIdNode().equals(rootNode.getId())) .map(NodeEntity::getIdNode) .collect(Collectors.toList())); + + Set request = TestUtils.getRequestsDone(7, mockWebServer); + assertTrue(request.stream().allMatch(r -> r.matches("/v1/reports"))); } @Test @@ -2204,9 +2207,6 @@ void testCutAndPasteNodeWithoutModification(final MockWebServer server) throws E cutAndPasteNode(study1Uuid, emptyNode, node1.getId(), InsertMode.BEFORE, 1, userId); - Set request = TestUtils.getRequestsDone(1, server); - assertTrue(request.stream().allMatch(r -> r.matches("/v1/reports"))); - assertEquals(BuildStatus.NOT_BUILT, networkModificationTreeService.getNodeBuildStatus(emptyNode.getId(), rootNetworkUuid).getGlobalBuildStatus()); assertEquals(BuildStatus.BUILT, networkModificationTreeService.getNodeBuildStatus(node1.getId(), rootNetworkUuid).getGlobalBuildStatus()); assertEquals(BuildStatus.BUILT, networkModificationTreeService.getNodeBuildStatus(emptyNodeChild.getId(), rootNetworkUuid).getGlobalBuildStatus()); diff --git a/src/test/java/org/gridsuite/study/server/VoltageInitTest.java b/src/test/java/org/gridsuite/study/server/VoltageInitTest.java index 7a703e05f..4e66346d7 100644 --- a/src/test/java/org/gridsuite/study/server/VoltageInitTest.java +++ b/src/test/java/org/gridsuite/study/server/VoltageInitTest.java @@ -885,7 +885,7 @@ private NodeEntity insertNode(StudyEntity study, NodeEntity parentNode, String f // We can't use the method RootNetworkNodeInfoService::createNodeLinks because there is no transaction in a session private void createNodeLinks(RootNetworkEntity rootNetworkEntity, NetworkModificationNodeInfoEntity modificationNodeInfoEntity, String variantId, UUID reportUuid, BuildStatus buildStatus) { - RootNetworkNodeInfoEntity rootNetworkNodeInfoEntity = RootNetworkNodeInfoEntity.builder().variantId(variantId).modificationReports(Map.of(modificationNodeInfoEntity.getId(), reportUuid)).nodeBuildStatus(NodeBuildStatus.from(buildStatus).toEntity()).build(); + RootNetworkNodeInfoEntity rootNetworkNodeInfoEntity = RootNetworkNodeInfoEntity.builder().variantId(variantId).modificationReportUuid(reportUuid).nodeBuildStatus(NodeBuildStatus.from(buildStatus).toEntity()).build(); modificationNodeInfoEntity.addRootNetworkNodeInfo(rootNetworkNodeInfoEntity); rootNetworkEntity.addRootNetworkNodeInfo(rootNetworkNodeInfoEntity); rootNetworkNodeInfoRepository.save(rootNetworkNodeInfoEntity);