diff --git a/src/main/java/org/gridsuite/network/map/dto/common/CurrentLimitsData.java b/src/main/java/org/gridsuite/network/map/dto/common/CurrentLimitsData.java index b9b199fb..c90e606b 100644 --- a/src/main/java/org/gridsuite/network/map/dto/common/CurrentLimitsData.java +++ b/src/main/java/org/gridsuite/network/map/dto/common/CurrentLimitsData.java @@ -10,7 +10,7 @@ import lombok.Builder; import lombok.EqualsAndHashCode; import lombok.Getter; -import org.springframework.util.CollectionUtils; +import lombok.ToString; import java.util.List; import java.util.Objects; @@ -22,6 +22,7 @@ @Builder @Getter @EqualsAndHashCode +@ToString public class CurrentLimitsData { // may be null in case we just need the selected limit set and don't really need its name/id @JsonInclude(JsonInclude.Include.NON_NULL) @@ -42,10 +43,6 @@ public enum Applicability { SIDE2, } - public boolean hasLimits() { - return permanentLimit != null && !Double.isNaN(permanentLimit) || !CollectionUtils.isEmpty(temporaryLimits); - } - public boolean limitsEquals(CurrentLimitsData other) { return Objects.equals(permanentLimit, other.permanentLimit) && Objects.equals(temporaryLimits, other.temporaryLimits); diff --git a/src/main/java/org/gridsuite/network/map/dto/common/TemporaryLimitData.java b/src/main/java/org/gridsuite/network/map/dto/common/TemporaryLimitData.java index 3c5e1a74..8c0436d2 100644 --- a/src/main/java/org/gridsuite/network/map/dto/common/TemporaryLimitData.java +++ b/src/main/java/org/gridsuite/network/map/dto/common/TemporaryLimitData.java @@ -10,6 +10,7 @@ import lombok.Builder; import lombok.EqualsAndHashCode; import lombok.Getter; +import lombok.ToString; /** * @author David Braquart @@ -17,6 +18,7 @@ @Builder @Getter @EqualsAndHashCode +@ToString public class TemporaryLimitData { private String name; diff --git a/src/main/java/org/gridsuite/network/map/dto/utils/ElementUtils.java b/src/main/java/org/gridsuite/network/map/dto/utils/ElementUtils.java index fcd02bbf..7dae13ce 100644 --- a/src/main/java/org/gridsuite/network/map/dto/utils/ElementUtils.java +++ b/src/main/java/org/gridsuite/network/map/dto/utils/ElementUtils.java @@ -11,16 +11,13 @@ import com.powsybl.iidm.network.extensions.*; import com.powsybl.math.graph.TraversalType; import org.gridsuite.network.map.dto.common.*; +import org.gridsuite.network.map.dto.common.CurrentLimitsData.Applicability; import org.gridsuite.network.map.dto.definition.extension.*; import org.gridsuite.network.map.dto.definition.threewindingstransformer.ThreeWindingsTransformerTabInfos; +import org.springframework.lang.Nullable; import org.springframework.util.CollectionUtils; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; +import java.util.*; import java.util.function.Consumer; import java.util.function.Function; import java.util.stream.Collectors; @@ -93,7 +90,7 @@ public static void buildCurrentLimits(Collection current } } - private static CurrentLimitsData copyCurrentLimitsData(CurrentLimitsData currentLimitsData, CurrentLimitsData.Applicability applicability) { + private static CurrentLimitsData copyCurrentLimitsData(CurrentLimitsData currentLimitsData, Applicability applicability) { return CurrentLimitsData.builder() .id(currentLimitsData.getId()) .applicability(applicability) @@ -111,15 +108,17 @@ public static void mergeCurrentLimits(Collection operati // Build temporary limit from side 1 and 2 List currentLimitsData1 = operationalLimitsGroups1.stream() - .map(currentLimitsData -> - ElementUtils.operationalLimitsGroupToMapDataCurrentLimits(currentLimitsData, SIDE1)).toList(); + .map(currentLimitsData -> ElementUtils.operationalLimitsGroupToMapDataCurrentLimits(currentLimitsData, SIDE1)) + .filter(Objects::nonNull) + .toList(); ArrayList currentLimitsData2 = new ArrayList<>(operationalLimitsGroups2.stream() - .map(currentLimitsData -> - ElementUtils.operationalLimitsGroupToMapDataCurrentLimits(currentLimitsData, SIDE2)).toList()); + .map(currentLimitsData -> ElementUtils.operationalLimitsGroupToMapDataCurrentLimits(currentLimitsData, SIDE2)) + .filter(Objects::nonNull) + .toList()); // combine 2 sides in one list - // simple case : one of the arrays are empty + // simple case: one of the arrays are empty if (currentLimitsData2.isEmpty() && !currentLimitsData1.isEmpty()) { mergedLimitsData.addAll(currentLimitsData1); build.accept(mergedLimitsData); @@ -134,30 +133,22 @@ public static void mergeCurrentLimits(Collection operati // more complex case for (CurrentLimitsData limitsData : currentLimitsData1) { Optional l2 = currentLimitsData2.stream().filter(l -> l.getId().equals(limitsData.getId())).findFirst(); - if (l2.isPresent()) { CurrentLimitsData limitsData2 = l2.get(); - // Only side one has limits - if (limitsData.hasLimits() && !limitsData2.hasLimits()) { + // both sides have limits and limits are equals + if (limitsData.limitsEquals(limitsData2)) { + mergedLimitsData.add(copyCurrentLimitsData(limitsData, EQUIPMENT)); + // both sides have limits and are different: create 2 different limit sets + } else { + // Side 1 mergedLimitsData.add(limitsData); - // only side two has limits - } else if (limitsData2.hasLimits() && !limitsData.hasLimits()) { + // Side 2 mergedLimitsData.add(limitsData2); - } else { - // both sides have limits and limits are equals - if (limitsData.limitsEquals(limitsData2)) { - mergedLimitsData.add(copyCurrentLimitsData(limitsData, EQUIPMENT)); - // both side have limits and they are different : create 2 different limit sets - } else { - // Side 1 - mergedLimitsData.add(limitsData); - // Side 2 - mergedLimitsData.add(limitsData2); - } } // remove processed limits from side 2 currentLimitsData2.remove(l2.get()); } else { + // only one side has limits mergedLimitsData.add(limitsData); } } @@ -261,7 +252,8 @@ public static CurrentLimitsData operationalLimitsGroupToMapDataCurrentLimits(Ope return operationalLimitsGroupToMapDataCurrentLimits(operationalLimitsGroup, null); } - public static CurrentLimitsData operationalLimitsGroupToMapDataCurrentLimits(OperationalLimitsGroup operationalLimitsGroup, CurrentLimitsData.Applicability applicability) { + @Nullable + public static CurrentLimitsData operationalLimitsGroupToMapDataCurrentLimits(OperationalLimitsGroup operationalLimitsGroup, Applicability applicability) { if (operationalLimitsGroup == null || operationalLimitsGroup.getCurrentLimits().isEmpty()) { return null; } diff --git a/src/test/java/org/gridsuite/network/map/utils/ElementUtilsTest.java b/src/test/java/org/gridsuite/network/map/utils/ElementUtilsTest.java new file mode 100644 index 00000000..ab4bcd7c --- /dev/null +++ b/src/test/java/org/gridsuite/network/map/utils/ElementUtilsTest.java @@ -0,0 +1,240 @@ +package org.gridsuite.network.map.utils; + +import com.powsybl.iidm.network.OperationalLimitsGroup; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.tuple.Triple; +import org.assertj.core.api.WithAssertions; +import org.assertj.core.api.junit.jupiter.SoftAssertionsExtension; +import org.gridsuite.network.map.dto.common.CurrentLimitsData; +import org.gridsuite.network.map.dto.common.CurrentLimitsData.Applicability; +import org.gridsuite.network.map.dto.common.TemporaryLimitData; +import org.gridsuite.network.map.dto.utils.ElementUtils; +import org.gridsuite.network.map.utils.MockDto.CurrentLimitsDtoTest; +import org.gridsuite.network.map.utils.MockDto.OperationalLimitsGroupDtoTest; +import org.gridsuite.network.map.utils.MockDto.TemporaryLimitDtoTest; +import org.junit.jupiter.api.*; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Optional; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.stream.Stream; + +@ExtendWith({ SoftAssertionsExtension.class, MockitoExtension.class }) +class ElementUtilsTest implements WithAssertions { + /** Tests for {@link ElementUtils#operationalLimitsGroupToMapDataCurrentLimits(OperationalLimitsGroup)} */ + @Nested + @DisplayName("fn operationalLimitsGroupToMapDataCurrentLimits(…)") + class OperationalLimitsGroupToMapDataCurrentLimits { + private final List mocks = new ArrayList<>(); + + @AfterEach + void setDown() { + if (!mocks.isEmpty()) { + Mockito.verifyNoMoreInteractions(mocks.toArray(Object[]::new)); + mocks.clear(); + } + } + + /* All cases possibles: + * null -> null + * operationalLimitsGroup(currentLimits=empty, *=any) -> null + * operationalLimitsGroup(currentLimits={PermanentLimit=NaN, TemporaryLimits=null, *=any}, *=any) -> null + * operationalLimitsGroup(currentLimits={PermanentLimit=NaN, TemporaryLimits=[], *=any}, *=any) -> null + * operationalLimitsGroup(currentLimits={permanentLimit=NaN, temporaryLimits=[any], *=any}, *=any) -> (id=*, applicability=null, permanentLimit=null, temporaryLimits=[any]) + * operationalLimitsGroup(currentLimits={PermanentLimit=_non_NaN_, TemporaryLimits=null, *=any}, *=any) -> (id=*, applicability=null, permanentLimit=*, temporaryLimits=null) + * operationalLimitsGroup(currentLimits={PermanentLimit=_non_NaN_, TemporaryLimits=[], *=any}, *=any) -> (id=*, applicability=null, permanentLimit=*, temporaryLimits=null) + * operationalLimitsGroup(currentLimits={PermanentLimit=_non_NaN_, TemporaryLimits=[any], *=any}, *=any) -> (id=*, applicability=null, permanentLimit=*, temporaryLimits=[any]) + */ + + @SafeVarargs + private CurrentLimitsData testResult(final String id, @Nullable final Double permanentLimit, @Nullable final Triple... temporaryLimits) { + final var dtoMocks = MockDto.buildOperationalLimitsGroup(true, id, permanentLimit, temporaryLimits); + final TemporaryLimitDtoTest tlMock = CollectionUtils.isEmpty(dtoMocks.getRight()) ? null : dtoMocks.getRight().getFirst(); + if (tlMock != null) { + mocks.add(tlMock); + } + final CurrentLimitsDtoTest clMock = dtoMocks.getMiddle(); + if (clMock != null) { + mocks.add(clMock); + } + final OperationalLimitsGroupDtoTest olgMock = dtoMocks.getLeft(); + if (olgMock != null) { + mocks.add(olgMock); + } + final CurrentLimitsData result = ElementUtils.operationalLimitsGroupToMapDataCurrentLimits(olgMock); + if (id != null) { + Mockito.verify(olgMock, Mockito.times(permanentLimit == null ? 1 : 2)).getCurrentLimits(); + if (permanentLimit != null) { + Mockito.verify(olgMock).getId(); + Mockito.verify(clMock, Mockito.times(Double.isNaN(permanentLimit) ? 1 : 2)).getPermanentLimit(); + Mockito.verify(clMock, Mockito.times(ArrayUtils.isEmpty(temporaryLimits) ? 1 : 2)).getTemporaryLimits(); + if (ArrayUtils.isNotEmpty(temporaryLimits)) { + Mockito.verify(tlMock).getName(); + Mockito.verify(tlMock, Mockito.times(2)).getValue(); + Mockito.verify(tlMock, Mockito.times(2)).getAcceptableDuration(); + } + } + } + return result; + } + + @Test + @Order(1) + void nullInput() { + // null -> null + assertThat(testResult(null, null, (Triple[]) null)).isNull(); + } + + @Test + @Order(2) + void emptyCurrentLimits() { + // OLG("id", null) -> null + assertThat(testResult("id", null /*,new Triple[0]*/)).isNull(); + } + + @Test + @Order(3) + void nanPermLimitAndNullTempLimit() { + // OLG("id", CL(NaN, null)) -> null + assertThat(testResult("id", Double.NaN, (Triple[]) null)).isNull(); + } + + @Test + @Order(4) + void nanPermLimitAndEmptyTempLimit() { + // OLG("id", CL(NaN, [])) -> null + assertThat(testResult("id", Double.NaN /*,new Triple[0]*/)).isNull(); + } + + @Test + @Order(5) + void nanPermLimitAndNonEmptyTempLimit() { + // OLG("my id", CL(Nan, [TL("testLimit", 456.789, 123)])) -> CLD("my id", null, [TLD("testLimit", 456.789, 123)], null) + assertThat(testResult("my id", Double.NaN, Triple.of("testLimit", 456.789, 123))) + .isEqualTo(CurrentLimitsData.builder().id("my id").applicability(null).permanentLimit(null).temporaryLimits( + List.of(TemporaryLimitData.builder().acceptableDuration(123).name("testLimit").value(456.789).build())).build()); + } + + @Test + @Order(6) + void nonNanPermLimitAndNullTempLimit() { + // OLG("my id", CL(0.123, null)) -> CLD("my id", 0.123, null, null) + assertThat(testResult("my id", 0.123, (Triple[]) null)) + .isEqualTo(CurrentLimitsData.builder().id("my id").applicability(null).permanentLimit(0.123).temporaryLimits(null).build()); + } + + @Test + @Order(7) + void nonNanPermLimitAndEmptyTempLimit() { + // OLG("my id", CL(0.123, [])) -> CLD("my id", 0.123, [], null) + assertThat(testResult("my id", 0.123 /*,new Triple[0]*/)) + .isEqualTo(CurrentLimitsData.builder().id("my id").applicability(null).permanentLimit(0.123).temporaryLimits(null).build()); + } + + @Test + @Order(8) + void nonNanPermLimitAndNonEmptyTempLimit() { + // OLG("my id", CL(0.0, [TL("testLimit", 456.789, 123)])) -> CLD("my id", 0.0, [TLD("testLimit", 456.789, 123)], null) + assertThat(testResult("my id", 0.0, Triple.of("testLimit", 456.789, 123))) + .isEqualTo(CurrentLimitsData.builder().id("my id").applicability(null).permanentLimit(0.0).temporaryLimits( + List.of(TemporaryLimitData.builder().acceptableDuration(123).name("testLimit").value(456.789).build())).build()); + } + } + + /** Tests for {@link ElementUtils#mergeCurrentLimits(Collection, Collection, Consumer)} */ + @Nested + @DisplayName("fn mergeCurrentLimits(…, …, …)") + class MergeCurrentLimitsTest { + private static OperationalLimitsGroupDtoTest buildParam(final boolean withPL, final boolean withTL) { + if (!withTL) { + return MockDto.buildOperationalLimitsGroup(null, "group1", withPL ? 220.0 : Double.NaN); + } + return MockDto.buildOperationalLimitsGroup(null, "group1", withPL ? 220.0 : Double.NaN, Triple.of("temporary1", 50.0, 100), Triple.of("temporary2", 70.0, 150)); + } + + private static CurrentLimitsData buildResult(final boolean withPL, final boolean withTL, @Nullable final Boolean isSide1or2) { + return CurrentLimitsData.builder().id("group1").permanentLimit(withPL ? 220.0 : null).temporaryLimits(!withTL ? null : List.of( + TemporaryLimitData.builder().acceptableDuration(100).name("temporary1").value(50.0).build(), + TemporaryLimitData.builder().acceptableDuration(150).name("temporary2").value(70.0).build() + )).applicability(isSide1or2 == null ? Applicability.EQUIPMENT : (isSide1or2 ? Applicability.SIDE1 : Applicability.SIDE2)) + .build(); + } + + @ParameterizedTest(name = ParameterizedTest.INDEX_PLACEHOLDER) + @MethodSource({"mergeCurrentLimitsTestData", "mergeCurrentLimitsTestDataSwappable", "mergeCurrentLimitsTestDataNotMergeable"}) // test al the combinations possible for the inputs + void shouldNotThrow(final Collection olg1, final Collection olg2, final List expected) { + System.out.print("L1: "); + System.out.println(olg1); + System.out.print("L2: "); + System.out.println(olg2); + System.out.print("Expect: "); + System.out.println(expected); + AtomicReference> results = new AtomicReference<>(); + ElementUtils.mergeCurrentLimits(olg1, olg2, results::set); + assertThat(results.get()).as("Result").isEqualTo(expected); + } + + private static Stream mergeCurrentLimitsTestData() { + // particular cases (p1&p2 the same if swapped) + return Stream.of( + // 1 - same limits on both sides for an id + Arguments.of(List.of(buildParam(true, true)), List.of(buildParam(true, true)), List.of(buildResult(true, true, null))), + // 2 - with no limits on either side for an id + Arguments.of(List.of(buildParam(false, false)), List.of(buildParam(false, false)), null), + // 3 + Arguments.of(List.of(buildParam(true, false)), List.of(buildParam(true, false)), List.of(buildResult(true, false, null))), + // 4 + Arguments.of(List.of(buildParam(false, true)), List.of(buildParam(false, true)), List.of(buildResult(false, true, null))) + ); + } + + private static Stream mergeCurrentLimitsTestDataSwappable() { + // cases with param1 and param2 swappable + // will map [l;r]->[(l,r)=s1, (r,l)=s2], so the pair is implicitly for case with side1 as result + return Stream.>>of( + // 5 & 6 & 7 & 8 - id present only on one side, because OLG() with no limit is converted to null + Triple.of(buildParam(true, true), null, s2 -> buildResult(true, true, !s2)), + Triple.of(buildParam(true, true), buildParam(false, false), s2 -> buildResult(true, true, !s2)), + // 9 & 10 & 11 & 12 - id present only on one side, because OLG() with no limit is converted to null + Triple.of(buildParam(true, false), null, s2 -> buildResult(true, false, !s2)), + Triple.of(buildParam(true, false), buildParam(false, false), s2 -> buildResult(true, false, !s2)), + // 9 & 10 - id present only on one side, because OLG() with no limit is converted to null + Triple.of(buildParam(false, true), null, s2 -> buildResult(false, true, !s2)), + Triple.of(buildParam(false, true), buildParam(false, false), s2 -> buildResult(false, true, !s2)), + // 11 & 12 - after dto conversion, the same as test n°2 + Triple.of(buildParam(false, false), null, s2 -> null) + ).mapMulti((args, argsTests) -> { + final var arg1 = args.getLeft() == null ? List.of() : List.of(args.getLeft()); + final var arg2 = args.getMiddle() == null ? List.of() : List.of(args.getMiddle()); + argsTests.accept(Arguments.of(arg1, arg2, Optional.ofNullable(args.getRight().apply(false)).map(List::of).orElse(null))); + argsTests.accept(Arguments.of(arg2, arg1, Optional.ofNullable(args.getRight().apply(true)).map(List::of).orElse(null))); + }); + } + + private static Stream mergeCurrentLimitsTestDataNotMergeable() { + return Stream.of( + // 13 & 14 + Arguments.of(List.of(buildParam(true, true)), List.of(buildParam(true, false)), + List.of(buildResult(true, true, true), buildResult(true, false, false))), + // 15 & 16 + Arguments.of(List.of(buildParam(true, true)), List.of(buildParam(false, true)), + List.of(buildResult(true, true, true), buildResult(false, true, false))), + // 17 & 18 + Arguments.of(List.of(buildParam(true, false)), List.of(buildParam(false, true)), + List.of(buildResult(true, false, true), buildResult(false, true, false))) + ); + } + } +} diff --git a/src/test/java/org/gridsuite/network/map/utils/MockDto.java b/src/test/java/org/gridsuite/network/map/utils/MockDto.java new file mode 100644 index 00000000..c022dc37 --- /dev/null +++ b/src/test/java/org/gridsuite/network/map/utils/MockDto.java @@ -0,0 +1,260 @@ +package org.gridsuite.network.map.utils; + +import com.powsybl.iidm.network.*; +import com.powsybl.iidm.network.LoadingLimits.TemporaryLimit; +import jakarta.annotation.Nonnull; +import jakarta.annotation.Nullable; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.experimental.Accessors; +import org.apache.commons.lang3.NotImplementedException; +import org.apache.commons.lang3.function.TriConsumer; +import org.apache.commons.lang3.tuple.Triple; +import org.mockito.Mockito; + +import java.util.Collection; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.atomic.AtomicReference; + +public final class MockDto { + private MockDto() { + throw new InstantiationError("Utility Class cannot be instantiated."); + } + + /** @see #buildOperationalLimitsGroup(TriConsumer, String, Double, List) */ + @Nonnull + @SafeVarargs + public static Triple> buildOperationalLimitsGroup( + final boolean mockAndPeek, + @Nullable final String id, + @Nullable final Double permanentLimit, + @Nullable final Triple... temporaryLimits) { + final AtomicReference> tlMock = new AtomicReference<>(); + final AtomicReference clMock = new AtomicReference<>(); + final OperationalLimitsGroupDtoTest dto = buildOperationalLimitsGroup(!mockAndPeek ? null : (olg, cl, tls) -> { + tlMock.set(tls); + clMock.set(cl); + }, id, permanentLimit, temporaryLimits); + return Triple.of(dto, clMock.get(), tlMock.get()); + } + + /** @see #buildOperationalLimitsGroup(TriConsumer, String, Double, List) */ + @Nullable + @SafeVarargs + public static OperationalLimitsGroupDtoTest buildOperationalLimitsGroup( + @Nullable final TriConsumer> mockAndPeek, + @Nullable final String id, + @Nullable final Double permanentLimit, + @Nullable final Triple... temporaryLimits) { + return buildOperationalLimitsGroup(mockAndPeek, id, permanentLimit, temporaryLimits == null ? null : List.of(temporaryLimits)); + } + + /** + * Build the different cases of {@link OperationalLimitsGroup}: + * + * + * + * + * + * + *
id permanentLimittemporaryLimitsReturn
null * * null
<string>null * new OLG(id, null)
<string><double>null new OLG(id, new CL(permanentLimits, null))
<string><double>[*] new OLG(id, new CL(permanentLimits, temporaryLimits::map(new TL(...)))
+ * @param mockAndPeek If is not {@code null}, the dto will be {@link Mockito#spy(Object) mocked} and the consumer will be called, else just return the dto. + * @return The DTO, possibly mocked. + * @see TemporaryLimitDtoTest + * @see CurrentLimitsDtoTest + * @see OperationalLimitsGroupDtoTest + */ + @Nullable + public static OperationalLimitsGroupDtoTest buildOperationalLimitsGroup( + @Nullable final TriConsumer> mockAndPeek, + @Nullable final String id, + @Nullable final Double permanentLimit, + @Nullable final List> temporaryLimits) { + OperationalLimitsGroupDtoTest oDto = null; + CurrentLimitsDtoTest cDto = null; + List tDtos = null; + if (id != null) { + if (permanentLimit != null) { + tDtos = temporaryLimits == null ? null : temporaryLimits.stream() + .map(t -> new TemporaryLimitDtoTest(t.getLeft(), t.getMiddle(), t.getRight())) + .map(tl -> mockAndPeek == null ? tl : Mockito.spy(tl)) + .toList(); + cDto = CurrentLimitsDtoTest.build(permanentLimit, tDtos); + if (mockAndPeek != null) { + cDto = Mockito.spy(cDto); + } + } + oDto = new OperationalLimitsGroupDtoTest(id, cDto); + if (mockAndPeek != null) { + oDto = Mockito.spy(oDto); + } + } + if (mockAndPeek != null) { + mockAndPeek.accept(oDto, cDto, tDtos); + } + return oDto; + } + + @Data + @AllArgsConstructor + public static class TemporaryLimitDtoTest implements TemporaryLimit { + private String name; + private double value; + private int acceptableDuration; + + @Override + public boolean isFictitious() { + throw new NotImplementedException("Not supported yet."); + } + } + + @Data + @AllArgsConstructor + public static class CurrentLimitsDtoTest implements CurrentLimits { + @Accessors(chain = true) + private double permanentLimit; + private Collection temporaryLimits; + + public static CurrentLimitsDtoTest build(double permanentLimit, @Nullable Collection temporaryLimits) { + return new CurrentLimitsDtoTest(permanentLimit, temporaryLimits == null ? null : List.copyOf(temporaryLimits)); // generic collections are invariant + } + + @Override + public TemporaryLimit getTemporaryLimit(int acceptableDuration) { + throw new NotImplementedException("Not supported yet."); + } + + @Override + public double getTemporaryLimitValue(int acceptableDuration) { + throw new NotImplementedException("Not supported yet."); + } + + @Override + public LoadingLimits setTemporaryLimitValue(int acceptableDuration, double temporaryLimitValue) { + throw new NotImplementedException("Not supported yet."); + } + + @Override + public void remove() { + throw new NotImplementedException("Not supported yet."); + } + + @Override + public LimitType getLimitType() { + throw new NotImplementedException("Not supported yet."); + } + } + + @Data + @AllArgsConstructor + public static class OperationalLimitsGroupDtoTest implements OperationalLimitsGroup { + private String id; + private Optional currentLimits; + + public OperationalLimitsGroupDtoTest(String id, CurrentLimits currentLimits) { + this(id, Optional.ofNullable(currentLimits)); + } + + @Override + public Optional getActivePowerLimits() { + throw new NotImplementedException("Not supported yet."); + } + + @Override + public Optional getApparentPowerLimits() { + throw new NotImplementedException("Not supported yet."); + } + + @Override + public CurrentLimitsAdder newCurrentLimits() { + throw new NotImplementedException("Not supported yet."); + } + + @Override + public ActivePowerLimitsAdder newActivePowerLimits() { + throw new NotImplementedException("Not supported yet."); + } + + @Override + public ApparentPowerLimitsAdder newApparentPowerLimits() { + throw new NotImplementedException("Not supported yet."); + } + + @Override + public CurrentLimitsAdder newCurrentLimits(CurrentLimits currentLimits) { + throw new NotImplementedException("Not supported yet."); + } + + @Override + public ActivePowerLimitsAdder newActivePowerLimits(ActivePowerLimits activePowerLimits) { + throw new NotImplementedException("Not supported yet."); + } + + @Override + public ApparentPowerLimitsAdder newApparentPowerLimits(ApparentPowerLimits apparentPowerLimits) { + throw new NotImplementedException("Not supported yet."); + } + + @Override + public void removeCurrentLimits() { + throw new NotImplementedException("Not supported yet."); + } + + @Override + public void removeActivePowerLimits() { + throw new NotImplementedException("Not supported yet."); + } + + @Override + public void removeApparentPowerLimits() { + throw new NotImplementedException("Not supported yet."); + } + + @Override + public boolean isEmpty() { + throw new NotImplementedException("Not supported yet."); + } + + @Override + public boolean hasProperty() { + throw new NotImplementedException("Not supported yet."); + } + + @Override + public boolean hasProperty(String key) { + throw new NotImplementedException("Not supported yet."); + } + + @Override + public String getProperty(String key) { + throw new NotImplementedException("Not supported yet."); + } + + @Override + public String getProperty(String key, String defaultValue) { + throw new NotImplementedException("Not supported yet."); + } + + @Override + public String setProperty(String key, String value) { + throw new NotImplementedException("Not supported yet."); + } + + @Override + public boolean removeProperty(String key) { + throw new NotImplementedException("Not supported yet."); + } + + @Override + public Set getPropertyNames() { + throw new NotImplementedException("Not supported yet."); + } + + @Override + public Network getNetwork() { + throw new NotImplementedException("Not supported yet."); + } + } +}