Repository: powsybl/powsybl-network-store
Pull request #514: TCK : normalize exception msg
Author: login: SlimaneAmar
Created: 2025-03-21T07:54:01Z | Merged: 2025-03-27T12:33:12Z

**Please check if the PR fulfills these requirements**
<!-- please use `'[x]'` to check the checkboxes, or submit the PR and then click the checkboxes -->
- [x] The commit message follows our guidelines


**Does this PR already have an issue describing the problem?**
<!-- If so, link to this issue using `'Fixes #XXX'` and skip the rest -->
No


**What kind of change does this PR introduce?**
<!-- Bug fix, feature, docs update, ... -->
This PR allows access to the id of an identifiable when it is deleted
Needed to generate the exception message when accessing a removed identifiable


**What is the current behavior?**
<!-- You can also link to an open issue here -->
Some TCK tests fails


**What is the new behavior (if this is a feature change)?**

TCK tests based on the id when a identifiable is removed succeeded


**Does this PR introduce a breaking change or deprecate an API?**
- [x] No

**What changes might users need to make in their application due to this PR? (migration steps)**
<!-- If this PR introduces a breaking change, describe the migration steps -->
<!-- The content of this section will be copied in the migration guide -->
No change



Diff:
diff --git a/network-store-iidm-impl/src/main/java/com/powsybl/network/store/iidm/impl/AbstractIdentifiableImpl.java b/network-store-iidm-impl/src/main/java/com/powsybl/network/store/iidm/impl/AbstractIdentifiableImpl.java
index e23d5c121..95ba041f5 100644
--- a/network-store-iidm-impl/src/main/java/com/powsybl/network/store/iidm/impl/AbstractIdentifiableImpl.java
+++ b/network-store-iidm-impl/src/main/java/com/powsybl/network/store/iidm/impl/AbstractIdentifiableImpl.java
@@ -39,6 +39,10 @@ public abstract class AbstractIdentifiableImpl<I extends Identifiable<I>, D exte
 
     private Resource<D> resource;
 
+    // When we remove an identifiable, we need to access to the id
+    // Needed to generate the exception message when accessing a removed identifiable
+    private String idBeforeRemoval;
+
     protected AbstractIdentifiableImpl(NetworkObjectIndex index, Resource<D> resource) {
         this.index = index;
         this.resource = resource;
@@ -69,6 +73,7 @@ public Resource<D> getNullableResource() {
     }
 
     public void setResource(Resource<D> resource) {
+        idBeforeRemoval = resource == null ? this.resource.getId() : null;
         this.resource = resource;
     }
 
@@ -87,7 +92,7 @@ protected Optional<Resource<D>> getOptionalResource() {
     }
 
     public String getId() {
-        return getResource().getId();
+        return resource == null ? idBeforeRemoval : resource.getId();
     }
 
     @Deprecated
@@ -296,7 +301,9 @@ public boolean removeProperty(String key) {
     }
 
     public NetworkImpl getNetwork() {
-        getResource();
+        if (resource == null) {
+            throw new PowsyblException("Cannot access network of removed equipment " + getId());
+        }
         return index.getNetwork();
     }
 
diff --git a/network-store-iidm-impl/src/main/java/com/powsybl/network/store/iidm/impl/SubstationImpl.java b/network-store-iidm-impl/src/main/java/com/powsybl/network/store/iidm/impl/SubstationImpl.java
index 42fe60597..e03d2a01d 100644
--- a/network-store-iidm-impl/src/main/java/com/powsybl/network/store/iidm/impl/SubstationImpl.java
+++ b/network-store-iidm-impl/src/main/java/com/powsybl/network/store/iidm/impl/SubstationImpl.java
@@ -7,6 +7,7 @@
 package com.powsybl.network.store.iidm.impl;
 
 import com.google.common.collect.Lists;
+import com.powsybl.commons.PowsyblException;
 import com.powsybl.commons.extensions.Extension;
 import com.powsybl.entsoe.util.EntsoeArea;
 import com.powsybl.entsoe.util.EntsoeAreaImpl;
@@ -38,6 +39,14 @@ public ContainerType getContainerType() {
         return ContainerType.SUBSTATION;
     }
 
+    @Override
+    public NetworkImpl getNetwork() {
+        if (getOptionalResource().isEmpty()) {
+            throw new PowsyblException("Cannot access network of removed substation " + getId());
+        }
+        return super.getNetwork();
+    }
+
     @Override
     public Optional<Country> getCountry() {
         return Optional.ofNullable(getResource().getAttributes().getCountry());
@@ -93,7 +102,9 @@ public Substation addGeographicalTag(String tag) {
         if (tag == null) {
             throw new ValidationException(this, "geographical tag is null");
         }
+        Set<String> oldGeographicalTags = new HashSet<>(getResource().getAttributes().getGeographicalTags());
         updateResource(r -> r.getAttributes().getGeographicalTags().add(tag));
+        index.notifyUpdate(this, "geographicalTags", null, oldGeographicalTags, getResource().getAttributes().getGeographicalTags());
         index.notifyPropertyAdded(this, "geographicalTags", tag);
         return this;
     }
diff --git a/network-store-iidm-impl/src/main/java/com/powsybl/network/store/iidm/impl/TerminalBusBreakerViewImpl.java b/network-store-iidm-impl/src/main/java/com/powsybl/network/store/iidm/impl/TerminalBusBreakerViewImpl.java
index 2ea96a8cc..5ec216167 100644
--- a/network-store-iidm-impl/src/main/java/com/powsybl/network/store/iidm/impl/TerminalBusBreakerViewImpl.java
+++ b/network-store-iidm-impl/src/main/java/com/powsybl/network/store/iidm/impl/TerminalBusBreakerViewImpl.java
@@ -42,10 +42,16 @@ private AbstractIdentifiableImpl<?, U> getAbstractIdentifiable() {
     }
 
     private InjectionAttributes getAttributes(Resource<U> resource) {
+        if (getAbstractIdentifiable().getOptionalResource().isEmpty()) {
+            throw new PowsyblException("Cannot modify removed equipment " + connectable.getId());
+        }
         return attributesGetter.apply(resource);
     }
 
     private InjectionAttributes getAttributes() {
+        if (getAbstractIdentifiable().getOptionalResource().isEmpty()) {
+            throw new PowsyblException("Cannot modify removed equipment " + connectable.getId());
+        }
         return getAttributes(getAbstractIdentifiable().getResource());
     }
 
@@ -81,7 +87,9 @@ private Bus calculateBus() {
 
     @Override
     public Bus getBus() {
-        getAbstractIdentifiable().getResource();
+        if (getAbstractIdentifiable().getOptionalResource().isEmpty()) {
+            throw new PowsyblException("Cannot access bus of removed equipment " + connectable.getId());
+        }
         if (isNodeBeakerTopologyKind()) { // calculated bus
             return calculateBus();
         } else {  // configured bus
@@ -92,7 +100,9 @@ public Bus getBus() {
 
     @Override
     public Bus getConnectableBus() {
-        getAbstractIdentifiable().getResource();
+        if (getAbstractIdentifiable().getOptionalResource().isEmpty()) {
+            throw new PowsyblException("Cannot access bus of removed equipment " + connectable.getId());
+        }
         if (isBusBeakerTopologyKind()) { // Configured bus
             String busId = getAttributes().getConnectableBus();
             return index.getConfiguredBus(busId).orElseThrow(() -> new AssertionError(busId + " " + NOT_FOUND));
diff --git a/network-store-iidm-impl/src/main/java/com/powsybl/network/store/iidm/impl/TerminalBusViewImpl.java b/network-store-iidm-impl/src/main/java/com/powsybl/network/store/iidm/impl/TerminalBusViewImpl.java
index 996aa286c..7f3c37372 100644
--- a/network-store-iidm-impl/src/main/java/com/powsybl/network/store/iidm/impl/TerminalBusViewImpl.java
+++ b/network-store-iidm-impl/src/main/java/com/powsybl/network/store/iidm/impl/TerminalBusViewImpl.java
@@ -6,6 +6,7 @@
  */
 package com.powsybl.network.store.iidm.impl;
 
+import com.powsybl.commons.PowsyblException;
 import com.powsybl.iidm.network.*;
 import com.powsybl.math.graph.TraverseResult;
 import com.powsybl.network.store.model.IdentifiableAttributes;
@@ -64,13 +65,16 @@ private Bus calculateBus() {
 
     @Override
     public Bus getBus() {
+        if (getAbstractIdentifiable().getOptionalResource().isEmpty()) {
+            throw new PowsyblException("Cannot access bus of removed equipment " + connectable.getId());
+        }
         return calculateBus();
     }
 
     @Override
     public Bus getConnectableBus() {
         if (getAbstractIdentifiable().getOptionalResource().isEmpty()) {
-            return null;
+            throw new PowsyblException("Cannot access bus of removed equipment " + connectable.getId());
         }
 
         var attributes = getAttributes();
diff --git a/network-store-iidm-impl/src/main/java/com/powsybl/network/store/iidm/impl/TerminalImpl.java b/network-store-iidm-impl/src/main/java/com/powsybl/network/store/iidm/impl/TerminalImpl.java
index 154b965a4..0d1877360 100644
--- a/network-store-iidm-impl/src/main/java/com/powsybl/network/store/iidm/impl/TerminalImpl.java
+++ b/network-store-iidm-impl/src/main/java/com/powsybl/network/store/iidm/impl/TerminalImpl.java
@@ -100,17 +100,23 @@ private AbstractIdentifiableImpl<?, U> getAbstractIdentifiable() {
     }
 
     private InjectionAttributes getAttributes(Resource<U> r) {
+        if (getAbstractIdentifiable().getOptionalResource().isEmpty()) {
+            throw new PowsyblException("Cannot modify removed equipment " + connectable.getId());
+        }
         return attributesGetter.apply(r);
     }
 
     private InjectionAttributes getAttributes() {
+        if (getAbstractIdentifiable().getOptionalResource().isEmpty()) {
+            throw new PowsyblException("Cannot modify removed equipment " + connectable.getId());
+        }
         return getAttributes(getAbstractIdentifiable().getResource());
     }
 
     @Override
     public VoltageLevelImpl getVoltageLevel() {
         if (getAbstractIdentifiable().getOptionalResource().isEmpty()) {
-            return null;
+            throw new PowsyblException("Cannot access voltage level of removed equipment " + connectable.getId());
         }
         return index.getVoltageLevel(getAttributes().getVoltageLevelId()).orElseThrow(AssertionError::new);
     }
@@ -289,37 +295,29 @@ protected void connectBusBreaker() {
     public boolean connect(Predicate<Switch> isTypeSwitchToOperate) {
         boolean done = false;
 
-        try {
-            Resource<VoltageLevelAttributes> voltageLevelResource = getVoltageLevelResource();
-            VoltageLevelAttributes voltageLevelAttributes = voltageLevelResource.getAttributes();
-            boolean connectedBefore = isConnected();
-            index.notifyUpdate(getConnectable(), "beginConnect", index.getNetwork().getVariantManager().getWorkingVariantId(), connectedBefore, null);
-            if (isNodeBeakerTopologyKind()) {
-                if (connectNodeBreaker(isTypeSwitchToOperate)) {
-                    done = true;
-                }
-            } else { // TopologyKind.BUS_BREAKER
-                // Check that the bus-breaker terminal has no bus defined (i.e. it is disconnected)
-                if (getAttributes().getBus() == null) {
-                    connectBusBreaker();
-                    done = true;
-                }
+        Resource<VoltageLevelAttributes> voltageLevelResource = getVoltageLevelResource();
+        VoltageLevelAttributes voltageLevelAttributes = voltageLevelResource.getAttributes();
+        boolean connectedBefore = isConnected();
+        index.notifyUpdate(getConnectable(), "beginConnect", index.getNetwork().getVariantManager().getWorkingVariantId(), connectedBefore, null);
+        if (isNodeBeakerTopologyKind()) {
+            if (connectNodeBreaker(isTypeSwitchToOperate)) {
+                done = true;
+            }
+        } else { // TopologyKind.BUS_BREAKER
+            // Check that the bus-breaker terminal has no bus defined (i.e. it is disconnected)
+            if (getAttributes().getBus() == null) {
+                connectBusBreaker();
+                done = true;
             }
+        }
 
-            boolean connectedAfter = isConnected();
-            index.notifyUpdate(getConnectable(), "endConnect", index.getNetwork().getVariantManager().getWorkingVariantId(), null, connectedAfter);
+        boolean connectedAfter = isConnected();
+        index.notifyUpdate(getConnectable(), "endConnect", index.getNetwork().getVariantManager().getWorkingVariantId(), null, connectedAfter);
 
-            if (done) {
-                // to invalidate calculated buses
-                voltageLevelAttributes.setCalculatedBusesValid(false);
-                index.updateVoltageLevelResource(voltageLevelResource);
-            }
-        } catch (PowsyblException exception) {
-            if (exception.getMessage().contains("Object has been removed in current variant")) {
-                throw new PowsyblException("Cannot modify removed equipment", exception);
-            } else {
-                throw exception;
-            }
+        if (done) {
+            // to invalidate calculated buses
+            voltageLevelAttributes.setCalculatedBusesValid(false);
+            index.updateVoltageLevelResource(voltageLevelResource);
         }
 
         return done;
@@ -509,35 +507,27 @@ protected boolean disconnectBusBreaker() {
     public boolean disconnect(Predicate<Switch> isSwitchOpenable) {
         boolean done = false;
 
-        try {
-            Resource<VoltageLevelAttributes> voltageLevelResource = getVoltageLevelResource();
-            VoltageLevelAttributes voltageLevelAttributes = voltageLevelResource.getAttributes();
-            boolean disconnectedBefore = !isConnected();
-            index.notifyUpdate(getConnectable(), "beginDisconnect", index.getNetwork().getVariantManager().getWorkingVariantId(), disconnectedBefore, null);
-            if (isNodeBeakerTopologyKind()) {
-                if (disconnectNodeBreaker(isSwitchOpenable)) {
-                    done = true;
-                }
-            } else { // TopologyKind.BUS_BREAKER
-                if (disconnectBusBreaker()) {
-                    done = true;
-                }
+        Resource<VoltageLevelAttributes> voltageLevelResource = getVoltageLevelResource();
+        VoltageLevelAttributes voltageLevelAttributes = voltageLevelResource.getAttributes();
+        boolean disconnectedBefore = !isConnected();
+        index.notifyUpdate(getConnectable(), "beginDisconnect", index.getNetwork().getVariantManager().getWorkingVariantId(), disconnectedBefore, null);
+        if (isNodeBeakerTopologyKind()) {
+            if (disconnectNodeBreaker(isSwitchOpenable)) {
+                done = true;
+            }
+        } else { // TopologyKind.BUS_BREAKER
+            if (disconnectBusBreaker()) {
+                done = true;
             }
+        }
 
-            boolean disconnectedAfter = !isConnected();
-            index.notifyUpdate(getConnectable(), "endDisconnect", index.getNetwork().getVariantManager().getWorkingVariantId(), null, disconnectedAfter);
+        boolean disconnectedAfter = !isConnected();
+        index.notifyUpdate(getConnectable(), "endDisconnect", index.getNetwork().getVariantManager().getWorkingVariantId(), null, disconnectedAfter);
 
-            if (done) {
-                // to invalidate calculated buses
-                voltageLevelAttributes.setCalculatedBusesValid(false);
-                index.updateVoltageLevelResource(voltageLevelResource);
-            }
-        } catch (PowsyblException exception) {
-            if (exception.getMessage().contains("Object has been removed in current variant")) {
-                throw new PowsyblException("Cannot modify removed equipment", exception);
-            } else {
-                throw exception;
-            }
+        if (done) {
+            // to invalidate calculated buses
+            voltageLevelAttributes.setCalculatedBusesValid(false);
+            index.updateVoltageLevelResource(voltageLevelResource);
         }
 
         return done;
@@ -556,6 +546,9 @@ public boolean disconnect() {
 
     @Override
     public boolean isConnected() {
+        if (getAbstractIdentifiable().getOptionalResource().isEmpty()) {
+            throw new PowsyblException("Cannot access connectivity status of removed equipment " + connectable.getId());
+        }
         if (isNodeBeakerTopologyKind()) {
             return this.getBusView().getBus() != null;
         } else {
@@ -578,7 +571,7 @@ public void traverse(Terminal.TopologyTraverser traverser) {
     public void traverse(Terminal.TopologyTraverser traverser, TraversalType traversalType) {
         Set<Terminal> traversedTerminals = new HashSet<>();
         if (getAbstractIdentifiable().getOptionalResource().isEmpty()) {
-            throw new PowsyblException("Associated equipment is removed");
+            throw new PowsyblException(String.format("Associated equipment %s is removed", connectable.getId()));
         }
 
         // One side
diff --git a/network-store-iidm-impl/src/main/java/com/powsybl/network/store/iidm/impl/TerminalNodeBreakerViewImpl.java b/network-store-iidm-impl/src/main/java/com/powsybl/network/store/iidm/impl/TerminalNodeBreakerViewImpl.java
index 286606fbc..331a22c20 100644
--- a/network-store-iidm-impl/src/main/java/com/powsybl/network/store/iidm/impl/TerminalNodeBreakerViewImpl.java
+++ b/network-store-iidm-impl/src/main/java/com/powsybl/network/store/iidm/impl/TerminalNodeBreakerViewImpl.java
@@ -40,10 +40,16 @@ private AbstractIdentifiableImpl<?, U> getAbstractIdentifiable() {
     }
 
     private InjectionAttributes getAttributes() {
+        if (getAbstractIdentifiable().getOptionalResource().isEmpty()) {
+            throw new PowsyblException("Cannot modify removed equipment " + connectable.getId());
+        }
         return getAttributes(getAbstractIdentifiable().getResource());
     }
 
     private InjectionAttributes getAttributes(Resource<U> resource) {
+        if (getAbstractIdentifiable().getOptionalResource().isEmpty()) {
+            throw new PowsyblException("Cannot modify removed equipment " + connectable.getId());
+        }
         return attributesGetter.apply(resource);
     }
 
@@ -53,6 +59,9 @@ private VoltageLevelImpl getVoltageLevel() {
 
     @Override
     public int getNode() {
+        if (getAbstractIdentifiable().getOptionalResource().isEmpty()) {
+            throw new PowsyblException("Cannot access node of removed equipment " + connectable.getId());
+        }
         Integer node = getAttributes().getNode();
         if (node == null) {
             throw new PowsyblException("Not supported in a bus breaker topology");
diff --git a/network-store-iidm-impl/src/main/java/com/powsybl/network/store/iidm/impl/VoltageLevelImpl.java b/network-store-iidm-impl/src/main/java/com/powsybl/network/store/iidm/impl/VoltageLevelImpl.java
index 0417a9dd3..9553e027d 100644
--- a/network-store-iidm-impl/src/main/java/com/powsybl/network/store/iidm/impl/VoltageLevelImpl.java
+++ b/network-store-iidm-impl/src/main/java/com/powsybl/network/store/iidm/impl/VoltageLevelImpl.java
@@ -62,8 +62,19 @@ public ContainerType getContainerType() {
         return ContainerType.VOLTAGE_LEVEL;
     }
 
+    @Override
+    public NetworkImpl getNetwork() {
+        if (getOptionalResource().isEmpty()) {
+            throw new PowsyblException("Cannot access network of removed voltage level " + getId());
+        }
+        return super.getNetwork();
+    }
+
     @Override
     public Optional<Substation> getSubstation() {
+        if (getOptionalResource().isEmpty()) {
+            throw new PowsyblException("Cannot access substation of removed voltage level " + getId());
+        }
         String substationId = getResource().getAttributes().getSubstationId();
         return substationId == null ? Optional.empty() : index.getSubstation(substationId).map(Function.identity());
     }
diff --git a/network-store-iidm-impl/src/test/java/com/powsybl/network/store/iidm/impl/tck/BatteryTest.java b/network-store-iidm-impl/src/test/java/com/powsybl/network/store/iidm/impl/tck/BatteryTest.java
index cd3c821df..72f79b419 100644
--- a/network-store-iidm-impl/src/test/java/com/powsybl/network/store/iidm/impl/tck/BatteryTest.java
+++ b/network-store-iidm-impl/src/test/java/com/powsybl/network/store/iidm/impl/tck/BatteryTest.java
@@ -12,8 +12,4 @@
  * @author Geoffroy Jamgotchian <geoffroy.jamgotchian at rte-france.com>
  */
 public class BatteryTest extends AbstractBatteryTest {
-    @Override
-    public void testRemove() {
-        // FIXME remove this test when exception msg are homogenized with the powsybl-core
-    }
 }
diff --git a/network-store-iidm-impl/src/test/java/com/powsybl/network/store/iidm/impl/tck/GeneratorTest.java b/network-store-iidm-impl/src/test/java/com/powsybl/network/store/iidm/impl/tck/GeneratorTest.java
index a6e164ab7..098e274d2 100644
--- a/network-store-iidm-impl/src/test/java/com/powsybl/network/store/iidm/impl/tck/GeneratorTest.java
+++ b/network-store-iidm-impl/src/test/java/com/powsybl/network/store/iidm/impl/tck/GeneratorTest.java
@@ -12,9 +12,4 @@
  * @author Geoffroy Jamgotchian <geoffroy.jamgotchian at rte-france.com>
  */
 class GeneratorTest extends AbstractGeneratorTest {
-
-    @Override
-    public void testRemove() {
-        // FIXME remove this test when exception msg are homogenized with the powsybl-core
-    }
 }
diff --git a/network-store-iidm-impl/src/test/java/com/powsybl/network/store/iidm/impl/tck/LineTest.java b/network-store-iidm-impl/src/test/java/com/powsybl/network/store/iidm/impl/tck/LineTest.java
index 58de3c340..71d884c89 100644
--- a/network-store-iidm-impl/src/test/java/com/powsybl/network/store/iidm/impl/tck/LineTest.java
+++ b/network-store-iidm-impl/src/test/java/com/powsybl/network/store/iidm/impl/tck/LineTest.java
@@ -36,11 +36,6 @@ public void baseAcLineTests() {
         // FIXME remove this test when we use the release containing this PR : https://github.com/powsybl/powsybl-core/pull/3022
     }
 
-    @Override
-    public void testRemoveAcLine() {
-        // FIXME remove this test when exception msg are homogenized with the powsybl-core
-    }
-
     @Override
     @Test
     public void testChangesNotification() {
diff --git a/network-store-iidm-impl/src/test/java/com/powsybl/network/store/iidm/impl/tck/SubstationTest.java b/network-store-iidm-impl/src/test/java/com/powsybl/network/store/iidm/impl/tck/SubstationTest.java
index 883475cba..1284a3696 100644
--- a/network-store-iidm-impl/src/test/java/com/powsybl/network/store/iidm/impl/tck/SubstationTest.java
+++ b/network-store-iidm-impl/src/test/java/com/powsybl/network/store/iidm/impl/tck/SubstationTest.java
@@ -12,9 +12,4 @@
  * @author Geoffroy Jamgotchian <geoffroy.jamgotchian at rte-france.com>
  */
 public class SubstationTest extends AbstractSubstationTest {
-
-    @Override
-    public void baseTests() {
-        // FIXME remove this test when exception msg are homogenized with the powsybl-core
-    }
 }
diff --git a/network-store-iidm-impl/src/test/java/com/powsybl/network/store/iidm/impl/tck/VoltageLevelTest.java b/network-store-iidm-impl/src/test/java/com/powsybl/network/store/iidm/impl/tck/VoltageLevelTest.java
index 619e8c325..d832d21c1 100644
--- a/network-store-iidm-impl/src/test/java/com/powsybl/network/store/iidm/impl/tck/VoltageLevelTest.java
+++ b/network-store-iidm-impl/src/test/java/com/powsybl/network/store/iidm/impl/tck/VoltageLevelTest.java
@@ -12,8 +12,4 @@
  * @author Geoffroy Jamgotchian <geoffroy.jamgotchian at rte-france.com>
  */
 public class VoltageLevelTest extends AbstractVoltageLevelTest {
-    @Override
-    public void baseTests() {
-        // FIXME remove this test when exception msg are homogenized with the powsybl-core
-    }
 }


Reviews:
user: login: antoinebhs
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-21T10:28:21Z
user: login: SlimaneAmar
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-21T11:59:55Z
user: login: SlimaneAmar
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-24T14:14:35Z
user: login: antoinebhs
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-26T14:28:41Z
user: login: SlimaneAmar
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-26T14:47:27Z
user: login: antoinebhs
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-27T10:09:12Z
user: login: SlimaneAmar
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-27T10:17:26Z
user: login: antoinebhs
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-27T10:19:04Z
user: login: antoinebhs
body: Code OK
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-03-27T12:31:15Z

Review comments:
diff_hunk: @@ -69,6 +71,9 @@ public Resource<D> getNullableResource() {
     }
 
     public void setResource(Resource<D> resource) {
+        if (resource == null) {
+            idIfRemoved = this.resource.getId();
+        }
path: network-store-iidm-impl/src/main/java/com/powsybl/network/store/iidm/impl/AbstractIdentifiableImpl.java
user: login: antoinebhs
body: This works only if the resource has been deleted in this varaint, right?
If you : delete in variant 1
save to server
load variant 1
does it work ?
clone variant 1 -> variant 2 
does it work?
created_at: 2025-03-21T10:28:21Z
author_association: COLLABORATOR
diff_hunk: @@ -69,6 +71,9 @@ public Resource<D> getNullableResource() {
     }
 
     public void setResource(Resource<D> resource) {
+        if (resource == null) {
+            idIfRemoved = this.resource.getId();
+        }
path: network-store-iidm-impl/src/main/java/com/powsybl/network/store/iidm/impl/AbstractIdentifiableImpl.java
user: login: SlimaneAmar
body: ```
    public void setResource(Resource<D> resource) {
        idIfRemoved = resource == null ? this.resource.getId() : null;
        this.resource = resource;
    }
```

More secure ?
created_at: 2025-03-21T11:59:53Z
author_association: COLLABORATOR
diff_hunk: @@ -69,6 +71,9 @@ public Resource<D> getNullableResource() {
     }
 
     public void setResource(Resource<D> resource) {
+        if (resource == null) {
+            idIfRemoved = this.resource.getId();
+        }
path: network-store-iidm-impl/src/main/java/com/powsybl/network/store/iidm/impl/AbstractIdentifiableImpl.java
user: login: SlimaneAmar
body: Done
created_at: 2025-03-24T14:14:35Z
author_association: COLLABORATOR
diff_hunk: @@ -93,7 +102,9 @@ public Substation addGeographicalTag(String tag) {
         if (tag == null) {
             throw new ValidationException(this, "geographical tag is null");
         }
+        Set<String> oldGeographicalTags = new HashSet<>(getResource().getAttributes().getGeographicalTags());
         updateResource(r -> r.getAttributes().getGeographicalTags().add(tag));
+        index.notifyUpdate(this, "geographicalTags", null, oldGeographicalTags, getResource().getAttributes().getGeographicalTags());
path: network-store-iidm-impl/src/main/java/com/powsybl/network/store/iidm/impl/SubstationImpl.java
user: login: antoinebhs
body: Not sure what's the link with this PR?
created_at: 2025-03-26T14:28:41Z
author_association: COLLABORATOR
diff_hunk: @@ -93,7 +102,9 @@ public Substation addGeographicalTag(String tag) {
         if (tag == null) {
             throw new ValidationException(this, "geographical tag is null");
         }
+        Set<String> oldGeographicalTags = new HashSet<>(getResource().getAttributes().getGeographicalTags());
         updateResource(r -> r.getAttributes().getGeographicalTags().add(tag));
+        index.notifyUpdate(this, "geographicalTags", null, oldGeographicalTags, getResource().getAttributes().getGeographicalTags());
path: network-store-iidm-impl/src/main/java/com/powsybl/network/store/iidm/impl/SubstationImpl.java
user: login: SlimaneAmar
body: Whe we remove all `FIXME remove this test when exception msg are homogenized with the powsybl-core`
This test is executed and fails
created_at: 2025-03-26T14:47:27Z
author_association: COLLABORATOR
diff_hunk: @@ -39,6 +39,8 @@ public abstract class AbstractIdentifiableImpl<I extends Identifiable<I>, D exte
 
     private Resource<D> resource;
 
+    private String idIfRemoved;
path: network-store-iidm-impl/src/main/java/com/powsybl/network/store/iidm/impl/AbstractIdentifiableImpl.java
user: login: antoinebhs
body: ```suggestion
    private String removedResourceId;
```
or `resourceIdBeforeRemoval` ?
created_at: 2025-03-27T10:09:12Z
author_association: COLLABORATOR
diff_hunk: @@ -39,6 +39,8 @@ public abstract class AbstractIdentifiableImpl<I extends Identifiable<I>, D exte
 
     private Resource<D> resource;
 
+    private String idIfRemoved;
path: network-store-iidm-impl/src/main/java/com/powsybl/network/store/iidm/impl/AbstractIdentifiableImpl.java
user: login: SlimaneAmar
body: `idBeforeRemoval` ?
created_at: 2025-03-27T10:17:26Z
author_association: COLLABORATOR
diff_hunk: @@ -39,6 +39,8 @@ public abstract class AbstractIdentifiableImpl<I extends Identifiable<I>, D exte
 
     private Resource<D> resource;
 
+    private String idIfRemoved;
path: network-store-iidm-impl/src/main/java/com/powsybl/network/store/iidm/impl/AbstractIdentifiableImpl.java
user: login: antoinebhs
body: Ok !
created_at: 2025-03-27T10:19:04Z
author_association: COLLABORATOR

PR comments:
user: login: antoinebhs
created_at: 2025-03-21T10:14:04Z
body: Would be nice to use the powsybl template for the PR and explain a bit what's done
author_association: COLLABORATOR
user: login: sonarqubecloud[bot]
created_at: 2025-03-27T11:27:51Z
body: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=com.powsybl%3Apowsybl-network-store&pullRequest=514) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=com.powsybl%3Apowsybl-network-store&pullRequest=514&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=com.powsybl%3Apowsybl-network-store&pullRequest=514&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=com.powsybl%3Apowsybl-network-store&pullRequest=514&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [89.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=com.powsybl%3Apowsybl-network-store&pullRequest=514&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=com.powsybl%3Apowsybl-network-store&pullRequest=514&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=com.powsybl%3Apowsybl-network-store&pullRequest=514)


author_association: NONE