diff --git a/pom.xml b/pom.xml index 89c7811..e9257ff 100644 --- a/pom.xml +++ b/pom.xml @@ -45,7 +45,7 @@ 2.23.0 1.28.1 - 1.6.0 + 1.10.0-SNAPSHOT 4.4 2.2 diff --git a/src/main/java/org/gridsuite/computation/dto/GlobalFilter.java b/src/main/java/org/gridsuite/computation/dto/GlobalFilter.java index d3dab5b..4f398c8 100644 --- a/src/main/java/org/gridsuite/computation/dto/GlobalFilter.java +++ b/src/main/java/org/gridsuite/computation/dto/GlobalFilter.java @@ -6,34 +6,22 @@ */ package org.gridsuite.computation.dto; -import com.powsybl.iidm.network.Country; import com.powsybl.security.LimitViolationType; import lombok.AllArgsConstructor; -import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import lombok.experimental.FieldNameConstants; +import lombok.experimental.SuperBuilder; import java.util.List; -import java.util.Map; -import java.util.UUID; /** * @author maissa Souissi */ @Getter -@Builder +@SuperBuilder @AllArgsConstructor @NoArgsConstructor -@FieldNameConstants -public class GlobalFilter { - List nominalV; - - List countryCode; - - List genericFilter; - - List limitViolationsTypes; - - Map> substationProperty; +public class GlobalFilter extends org.gridsuite.filter.globalfilter.GlobalFilter { + // TODO move it to filterparameters in loadflow-server or manage it in server endpoint + private List limitViolationsTypes; } diff --git a/src/main/java/org/gridsuite/computation/service/AbstractFilterService.java b/src/main/java/org/gridsuite/computation/service/AbstractFilterService.java index 6558774..a68a6a7 100644 --- a/src/main/java/org/gridsuite/computation/service/AbstractFilterService.java +++ b/src/main/java/org/gridsuite/computation/service/AbstractFilterService.java @@ -7,9 +7,7 @@ package org.gridsuite.computation.service; import com.powsybl.commons.PowsyblException; -import com.powsybl.iidm.network.Country; import com.powsybl.iidm.network.Network; -import com.powsybl.iidm.network.TwoSides; import com.powsybl.network.store.client.NetworkStoreService; import com.powsybl.network.store.client.PreloadingStrategy; import lombok.NonNull; @@ -17,15 +15,9 @@ import org.gridsuite.computation.dto.GlobalFilter; import org.gridsuite.computation.dto.ResourceFilterDTO; import org.gridsuite.filter.AbstractFilter; -import org.gridsuite.filter.FilterLoader; -import org.gridsuite.filter.expertfilter.ExpertFilter; -import org.gridsuite.filter.expertfilter.expertrule.*; -import org.gridsuite.filter.identifierlistfilter.IdentifiableAttributes; +import org.gridsuite.filter.globalfilter.AbstractGlobalFilterService; import org.gridsuite.filter.utils.EquipmentType; -import org.gridsuite.filter.utils.FilterServiceUtils; -import org.gridsuite.filter.utils.expertfilter.CombinatorType; -import org.gridsuite.filter.utils.expertfilter.FieldType; -import org.gridsuite.filter.utils.expertfilter.OperatorType; +import org.jetbrains.annotations.NotNull; import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; @@ -34,13 +26,15 @@ import org.springframework.web.server.ResponseStatusException; import org.springframework.web.util.UriComponentsBuilder; -import java.util.*; +import java.util.List; +import java.util.Optional; +import java.util.UUID; import java.util.stream.Collectors; /** * @author Rehili Ghazwa */ -public abstract class AbstractFilterService implements FilterLoader { +public abstract class AbstractFilterService extends AbstractGlobalFilterService { protected static final String FILTERS_NOT_FOUND = "Filters not found"; protected static final String FILTER_API_VERSION = "v1"; protected static final String DELIMITER = "/"; @@ -85,314 +79,25 @@ public List getFilters(List filtersUuids) { } } - protected Network getNetwork(UUID networkUuid, String variantId) { + @Override + protected Network getNetwork(@NotNull final UUID networkUuid, @NotNull final String variantId) { try { Network network = networkStoreService.getNetwork(networkUuid, PreloadingStrategy.COLLECTION); network.getVariantManager().setWorkingVariant(variantId); return network; - } catch (PowsyblException e) { + } catch (final PowsyblException e) { throw new ResponseStatusException(HttpStatus.NOT_FOUND, e.getMessage()); } } - protected List filterNetwork(AbstractFilter filter, Network network) { - return FilterServiceUtils.getIdentifiableAttributes(filter, network, this) - .stream() - .map(IdentifiableAttributes::getId) - .toList(); - } - - public Optional getResourceFilter(@NonNull UUID networkUuid, @NonNull String variantId, @NonNull GlobalFilter globalFilter, - List equipmentTypes, String columnName) { - - Network network = getNetwork(networkUuid, variantId); - List genericFilters = getFilters(globalFilter.getGenericFilter()); - - // Filter equipments by type - Map> subjectIdsByEquipmentType = filterEquipmentsByType( - network, globalFilter, genericFilters, equipmentTypes - ); - - // Combine all results into one list - List subjectIds = subjectIdsByEquipmentType.values().stream() - .filter(Objects::nonNull) - .flatMap(List::stream) - .toList(); - - return subjectIds.isEmpty() ? Optional.empty() : - Optional.of(new ResourceFilterDTO( - ResourceFilterDTO.DataType.TEXT, - ResourceFilterDTO.Type.IN, - subjectIds, - columnName - )); - } - - protected List createNumberExpertRules(List values, FieldType fieldType) { - List rules = new ArrayList<>(); - if (values != null) { - for (String value : values) { - rules.add(NumberExpertRule.builder() - .value(Double.valueOf(value)) - .field(fieldType) - .operator(OperatorType.EQUALS) - .build()); - } - } - return rules; - } - - protected AbstractExpertRule createPropertiesRule(String property, List propertiesValues, FieldType fieldType) { - return PropertiesExpertRule.builder() - .combinator(CombinatorType.OR) - .operator(OperatorType.IN) - .field(fieldType) - .propertyName(property) - .propertyValues(propertiesValues) - .build(); - } - - protected List createEnumExpertRules(List values, FieldType fieldType) { - List rules = new ArrayList<>(); - if (values != null) { - for (Country value : values) { - rules.add(EnumExpertRule.builder() - .value(value.toString()) - .field(fieldType) - .operator(OperatorType.EQUALS) - .build()); - } - } - return rules; - } - - protected AbstractExpertRule createCombination(CombinatorType combinatorType, List rules) { - return CombinatorExpertRule.builder().combinator(combinatorType).rules(rules).build(); - } - - protected Optional createOrCombination(List rules) { - if (rules.isEmpty()) { - return Optional.empty(); - } - return Optional.of(rules.size() > 1 ? createCombination(CombinatorType.OR, rules) : rules.getFirst()); - } - - /** - * Extracts equipment IDs from a generic filter based on equipment type - */ - protected List extractEquipmentIdsFromGenericFilter( - AbstractFilter filter, - EquipmentType targetEquipmentType, - Network network) { - - if (filter.getEquipmentType() == targetEquipmentType) { - return filterNetwork(filter, network); - } else if (filter.getEquipmentType() == EquipmentType.VOLTAGE_LEVEL) { - ExpertFilter voltageFilter = buildExpertFilterWithVoltageLevelIdsCriteria( - filter.getId(), targetEquipmentType); - return filterNetwork(voltageFilter, network); - } - return List.of(); - } - - /** - * Combines multiple filter results using AND or OR logic - */ - protected List combineFilterResults(List> filterResults, boolean useAndLogic) { - if (filterResults.isEmpty()) { - return List.of(); - } - - if (filterResults.size() == 1) { - return filterResults.getFirst(); - } - - if (useAndLogic) { - // Intersection of all results - Set result = new HashSet<>(filterResults.getFirst()); - for (int i = 1; i < filterResults.size(); i++) { - result.retainAll(filterResults.get(i)); - } - return new ArrayList<>(result); - } else { - // Union of all results - Set result = new HashSet<>(); - filterResults.forEach(result::addAll); - return new ArrayList<>(result); - } - } - - /** - * Extracts filtered equipment IDs by applying expert and generic filters - */ - protected List extractFilteredEquipmentIds( - Network network, - GlobalFilter globalFilter, - List genericFilters, - EquipmentType equipmentType) { - - List> allFilterResults = new ArrayList<>(); - - // Extract IDs from expert filter - ExpertFilter expertFilter = buildExpertFilter(globalFilter, equipmentType); - if (expertFilter != null) { - allFilterResults.add(filterNetwork(expertFilter, network)); - } - - // Extract IDs from generic filters - for (AbstractFilter filter : genericFilters) { - List filterResult = extractEquipmentIdsFromGenericFilter(filter, equipmentType, network); - if (!filterResult.isEmpty()) { - allFilterResults.add(filterResult); - } - } - - // Combine results with appropriate logic - // Expert filters use OR between them, generic filters use AND - return combineFilterResults(allFilterResults, !genericFilters.isEmpty()); - } - - /** - * Builds expert filter with voltage level IDs criteria - */ - protected ExpertFilter buildExpertFilterWithVoltageLevelIdsCriteria(UUID filterUuid, EquipmentType equipmentType) { - AbstractExpertRule voltageLevelId1Rule = createVoltageLevelIdRule(filterUuid, TwoSides.ONE); - AbstractExpertRule voltageLevelId2Rule = createVoltageLevelIdRule(filterUuid, TwoSides.TWO); - AbstractExpertRule orCombination = createCombination(CombinatorType.OR, - List.of(voltageLevelId1Rule, voltageLevelId2Rule)); - return new ExpertFilter(UUID.randomUUID(), new Date(), equipmentType, orCombination); - } - - /** - * Creates voltage level ID rule for filtering - */ - protected AbstractExpertRule createVoltageLevelIdRule(UUID filterUuid, TwoSides side) { - return FilterUuidExpertRule.builder() - .operator(OperatorType.IS_PART_OF) - .field(side == TwoSides.ONE ? FieldType.VOLTAGE_LEVEL_ID_1 : FieldType.VOLTAGE_LEVEL_ID_2) - .values(Set.of(filterUuid.toString())) - .build(); - } - - /** - * Builds all expert rules for a global filter and equipment type - */ - protected List buildAllExpertRules(GlobalFilter globalFilter, EquipmentType equipmentType) { - List andRules = new ArrayList<>(); - - // Nominal voltage rules - buildNominalVoltageRules(globalFilter.getNominalV(), equipmentType) - .ifPresent(andRules::add); - - // Country code rules - buildCountryCodeRules(globalFilter.getCountryCode(), equipmentType) - .ifPresent(andRules::add); - - // Substation property rules - if (globalFilter.getSubstationProperty() != null) { - buildSubstationPropertyRules(globalFilter.getSubstationProperty(), equipmentType) - .ifPresent(andRules::add); - } - - return andRules; - } - - /** - * Builds nominal voltage rules combining all relevant field types - */ - protected Optional buildNominalVoltageRules( - List nominalVoltages, EquipmentType equipmentType) { - - List fieldTypes = getNominalVoltageFieldType(equipmentType); - List rules = fieldTypes.stream() - .flatMap(fieldType -> createNumberExpertRules(nominalVoltages, fieldType).stream()) - .toList(); - - return createOrCombination(rules); - } - - /** - * Builds country code rules combining all relevant field types - */ - protected Optional buildCountryCodeRules( - List countryCodes, EquipmentType equipmentType) { - - List fieldTypes = getCountryCodeFieldType(equipmentType); - List rules = fieldTypes.stream() - .flatMap(fieldType -> createEnumExpertRules(countryCodes, fieldType).stream()) - .toList(); - - return createOrCombination(rules); - } - - /** - * Builds substation property rules combining all relevant field types - */ - protected Optional buildSubstationPropertyRules( - Map> properties, EquipmentType equipmentType) { - - List fieldTypes = getSubstationPropertiesFieldTypes(equipmentType); - List rules = properties.entrySet().stream() - .flatMap(entry -> fieldTypes.stream() - .map(fieldType -> createPropertiesRule( - entry.getKey(), entry.getValue(), fieldType))) - .toList(); - - return createOrCombination(rules); - } - - /** - * Filters equipments by type and returns map of IDs grouped by equipment type - */ - protected Map> filterEquipmentsByType( - Network network, - GlobalFilter globalFilter, - List genericFilters, - List equipmentTypes) { - - Map> result = new EnumMap<>(EquipmentType.class); - - for (EquipmentType equipmentType : equipmentTypes) { - List filteredIds = extractFilteredEquipmentIds(network, globalFilter, genericFilters, equipmentType); - if (!filteredIds.isEmpty()) { - result.put(equipmentType, filteredIds); - } - } - - return result; - } - - /** - * Builds expert filter from global filter and equipment type - */ - protected ExpertFilter buildExpertFilter(GlobalFilter globalFilter, EquipmentType equipmentType) { - List andRules = buildAllExpertRules(globalFilter, equipmentType); - - return andRules.isEmpty() ? null : - new ExpertFilter(UUID.randomUUID(), new Date(), equipmentType, - createCombination(CombinatorType.AND, andRules)); - } - - protected List getNominalVoltageFieldType(EquipmentType equipmentType) { - return switch (equipmentType) { - case LINE, TWO_WINDINGS_TRANSFORMER -> List.of(FieldType.NOMINAL_VOLTAGE_1, FieldType.NOMINAL_VOLTAGE_2); - case VOLTAGE_LEVEL -> List.of(FieldType.NOMINAL_VOLTAGE); - default -> List.of(); - }; - } - - protected List getCountryCodeFieldType(EquipmentType equipmentType) { - return switch (equipmentType) { - case VOLTAGE_LEVEL, TWO_WINDINGS_TRANSFORMER -> List.of(FieldType.COUNTRY); - case LINE -> List.of(FieldType.COUNTRY_1, FieldType.COUNTRY_2); - default -> List.of(); - }; - } - - protected List getSubstationPropertiesFieldTypes(EquipmentType equipmentType) { - return equipmentType == EquipmentType.LINE ? - List.of(FieldType.SUBSTATION_PROPERTIES_1, FieldType.SUBSTATION_PROPERTIES_2) : - List.of(FieldType.SUBSTATION_PROPERTIES); + public Optional getResourceFilter(@NonNull final UUID networkUuid, @NonNull final String variantId, + @NonNull final GlobalFilter globalFilter, + @NonNull final List equipmentTypes, + final String columnName) { + final List subjectIds = this.getFilteredIds(networkUuid, variantId, globalFilter, equipmentTypes); + return subjectIds.isEmpty() + ? Optional.empty() + : Optional.of(new ResourceFilterDTO(ResourceFilterDTO.DataType.TEXT, ResourceFilterDTO.Type.IN, subjectIds, columnName)); } } diff --git a/src/main/java/org/gridsuite/computation/utils/FilterUtils.java b/src/main/java/org/gridsuite/computation/utils/FilterUtils.java index b503df5..3f35c49 100644 --- a/src/main/java/org/gridsuite/computation/utils/FilterUtils.java +++ b/src/main/java/org/gridsuite/computation/utils/FilterUtils.java @@ -20,9 +20,9 @@ * @author maissa Souissi */ public final class FilterUtils { - // Utility class, so no constructor private FilterUtils() { + throw new IllegalCallerException("Utility class"); } private static T fromStringToDTO(String jsonString, ObjectMapper objectMapper, TypeReference typeReference, T defaultValue) { @@ -37,13 +37,11 @@ private static T fromStringToDTO(String jsonString, ObjectMapper objectMappe } public static List fromStringFiltersToDTO(String stringFilters, ObjectMapper objectMapper) { - return fromStringToDTO(stringFilters, objectMapper, new TypeReference<>() { - }, List.of()); + return fromStringToDTO(stringFilters, objectMapper, new TypeReference<>() { }, List.of()); } public static GlobalFilter fromStringGlobalFiltersToDTO(String stringGlobalFilters, ObjectMapper objectMapper) { - return fromStringToDTO(stringGlobalFilters, objectMapper, new TypeReference<>() { - }, null); + return fromStringToDTO(stringGlobalFilters, objectMapper, new TypeReference<>() { }, null); } } diff --git a/src/test/java/org/gridsuite/computation/service/FilterServiceTest.java b/src/test/java/org/gridsuite/computation/service/FilterServiceTest.java index e3386fb..4d91119 100644 --- a/src/test/java/org/gridsuite/computation/service/FilterServiceTest.java +++ b/src/test/java/org/gridsuite/computation/service/FilterServiceTest.java @@ -8,31 +8,15 @@ package org.gridsuite.computation.service; import com.powsybl.commons.PowsyblException; -import com.powsybl.iidm.network.Country; import com.powsybl.iidm.network.Network; -import com.powsybl.iidm.network.TwoSides; import com.powsybl.iidm.network.VariantManager; import com.powsybl.network.store.client.NetworkStoreService; import com.powsybl.network.store.client.PreloadingStrategy; -import org.gridsuite.computation.dto.GlobalFilter; -import org.gridsuite.computation.dto.ResourceFilterDTO; import org.gridsuite.filter.AbstractFilter; -import org.gridsuite.filter.expertfilter.ExpertFilter; -import org.gridsuite.filter.expertfilter.expertrule.*; -import org.gridsuite.filter.identifierlistfilter.IdentifiableAttributes; -import org.gridsuite.filter.utils.EquipmentType; -import org.gridsuite.filter.utils.FilterServiceUtils; -import org.gridsuite.filter.utils.expertfilter.CombinatorType; -import org.gridsuite.filter.utils.expertfilter.FieldType; -import org.gridsuite.filter.utils.expertfilter.OperatorType; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; 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.Mock; -import org.mockito.MockedStatic; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.HttpMethod; @@ -43,8 +27,9 @@ import org.springframework.web.client.RestTemplate; import org.springframework.web.server.ResponseStatusException; -import java.util.*; -import java.util.stream.Stream; +import java.util.Collections; +import java.util.List; +import java.util.UUID; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.any; @@ -137,402 +122,4 @@ void shouldThrowResponseStatusExceptionWhenPowsyblException() { assertEquals(HttpStatus.NOT_FOUND, exception.getStatusCode()); assertEquals("Network not found", exception.getReason()); } - - @ParameterizedTest - @MethodSource("expertRulesData") - void shouldCreateExpertRules(List values, FieldType fieldType, Class expectedRuleType, boolean shouldBeEmpty) { - when(filterService.createNumberExpertRules(any(), any())).thenCallRealMethod(); - List result = filterService.createNumberExpertRules(values, fieldType); - if (shouldBeEmpty) { - assertNotNull(result); - assertTrue(result.isEmpty()); - } else { - assertNotNull(result); - assertEquals(values.size(), result.size()); - for (AbstractExpertRule rule : result) { - assertInstanceOf(expectedRuleType, rule); - NumberExpertRule numberRule = (NumberExpertRule) rule; - assertEquals(fieldType, numberRule.getField()); - assertEquals(OperatorType.EQUALS, numberRule.getOperator()); - } - } - } - - private static Stream expertRulesData() { - return Stream.of( - Arguments.of(null, FieldType.NOMINAL_VOLTAGE, NumberExpertRule.class, true), - Arguments.of(Arrays.asList("400.0", "225.0"), FieldType.NOMINAL_VOLTAGE, NumberExpertRule.class, false) - ); - } - - @ParameterizedTest - @MethodSource("enumRulesData") - void shouldCreateEnumRules(List values, FieldType fieldType, Class expectedRuleType, boolean shouldBeEmpty) { - when(filterService.createEnumExpertRules(any(), any())).thenCallRealMethod(); - - List result = filterService.createEnumExpertRules(values, fieldType); - - if (shouldBeEmpty) { - assertNotNull(result); - assertTrue(result.isEmpty()); - } else { - assertNotNull(result); - assertEquals(values.size(), result.size()); - for (AbstractExpertRule rule : result) { - assertInstanceOf(expectedRuleType, rule); - EnumExpertRule enumRule = (EnumExpertRule) rule; - assertEquals(fieldType, enumRule.getField()); - assertEquals(OperatorType.EQUALS, enumRule.getOperator()); - } - } - } - - private static Stream enumRulesData() { - return Stream.of( - Arguments.of(null, FieldType.COUNTRY, EnumExpertRule.class, true), - Arguments.of(Arrays.asList(Country.FR, Country.DE), FieldType.COUNTRY, EnumExpertRule.class, false) - ); - } - - @Test - void shouldCreateCorrectPropertiesRule() { - when(filterService.createPropertiesRule(any(), any(), any())).thenCallRealMethod(); - String property = "testProperty"; - List values = Arrays.asList("value1", "value2"); - AbstractExpertRule result = filterService.createPropertiesRule(property, values, FieldType.SUBSTATION_PROPERTIES); - assertNotNull(result); - assertInstanceOf(PropertiesExpertRule.class, result); - PropertiesExpertRule propertiesRule = (PropertiesExpertRule) result; - assertEquals(CombinatorType.OR, propertiesRule.getCombinator()); - assertEquals(OperatorType.IN, propertiesRule.getOperator()); - assertEquals(FieldType.SUBSTATION_PROPERTIES, propertiesRule.getField()); - assertEquals(property, propertiesRule.getPropertyName()); - assertEquals(values, propertiesRule.getPropertyValues()); - } - - @Test - void shouldCreateCombinatorRule() { - when(filterService.createCombination(any(), any())).thenCallRealMethod(); - List rules = Collections.singletonList(mock(AbstractExpertRule.class)); - AbstractExpertRule result = filterService.createCombination(CombinatorType.AND, rules); - assertNotNull(result); - assertInstanceOf(CombinatorExpertRule.class, result); - CombinatorExpertRule combinatorRule = (CombinatorExpertRule) result; - assertEquals(CombinatorType.AND, combinatorRule.getCombinator()); - assertEquals(rules, combinatorRule.getRules()); - } - - @ParameterizedTest - @MethodSource("orCombinationData") - void shouldCreateOrCombination(List rules, boolean expectEmpty, boolean expectSingle) { - when(filterService.createOrCombination(any())).thenCallRealMethod(); - if (!expectEmpty && !expectSingle) { - when(filterService.createCombination(any(), any())).thenCallRealMethod(); - } - Optional result = filterService.createOrCombination(rules); - if (expectEmpty) { - assertFalse(result.isPresent()); - } else if (expectSingle) { - assertTrue(result.isPresent()); - assertEquals(rules.getFirst(), result.get()); - } else { - assertTrue(result.isPresent()); - assertInstanceOf(CombinatorExpertRule.class, result.get()); - CombinatorExpertRule combinatorRule = (CombinatorExpertRule) result.get(); - assertEquals(CombinatorType.OR, combinatorRule.getCombinator()); - } - } - - private static Stream orCombinationData() { - return Stream.of( - Arguments.of(Collections.emptyList(), true, false), - Arguments.of(Collections.singletonList(mock(AbstractExpertRule.class)), false, true), - Arguments.of(Arrays.asList(mock(AbstractExpertRule.class), mock(AbstractExpertRule.class)), false, false) - ); - } - - @Test - void shouldReturnEmptyWhenCombineFilterResultsInputIsEmpty() { - when(filterService.combineFilterResults(any(), anyBoolean())).thenCallRealMethod(); - List> filterResults = Collections.emptyList(); - List result = filterService.combineFilterResults(filterResults, true); - assertNotNull(result); - assertTrue(result.isEmpty()); - } - - @Test - void shouldReturnIntersectionWhenUsingAndLogic() { - when(filterService.combineFilterResults(any(), anyBoolean())).thenCallRealMethod(); - List> filterResults = Arrays.asList( - Arrays.asList("item1", "item2", "item3"), - Arrays.asList("item2", "item3", "item4"), - Arrays.asList("item2", "item5") - ); - List result = filterService.combineFilterResults(filterResults, true); - assertEquals(1, result.size()); - assertTrue(result.contains("item2")); - } - - @Test - void shouldReturnUnionWhenUsingOrLogic() { - when(filterService.combineFilterResults(any(), anyBoolean())).thenCallRealMethod(); - List> filterResults = Arrays.asList( - Arrays.asList("item1", "item2"), - Arrays.asList("item3", "item4"), - List.of("item5") - ); - List result = filterService.combineFilterResults(filterResults, false); - assertEquals(5, result.size()); - assertTrue(result.containsAll(Arrays.asList("item1", "item2", "item3", "item4", "item5"))); - } - - @Test - void shouldReturnIdsFromFilteredNetwork() { - when(filterService.filterNetwork(any(), any())).thenCallRealMethod(); - AbstractFilter filter = mock(AbstractFilter.class); - try (MockedStatic mockStatic = mockStatic(FilterServiceUtils.class)) { - List attributes = Arrays.asList( - createIdentifiableAttributes("id1"), - createIdentifiableAttributes("id2") - ); - mockStatic.when(() -> FilterServiceUtils.getIdentifiableAttributes(filter, network, filterService)).thenReturn(attributes); - List result = filterService.filterNetwork(filter, network); - assertEquals(Arrays.asList("id1", "id2"), result); - } - } - - @ParameterizedTest - @MethodSource("voltageLevelRuleData") - void shouldCreateVoltageLevelIdRule(TwoSides side, FieldType expectedFieldType) { - when(filterService.createVoltageLevelIdRule(any(), any())).thenCallRealMethod(); - UUID filterUuid = UUID.randomUUID(); - AbstractExpertRule result = filterService.createVoltageLevelIdRule(filterUuid, side); - assertNotNull(result); - assertInstanceOf(FilterUuidExpertRule.class, result); - FilterUuidExpertRule rule = (FilterUuidExpertRule) result; - assertEquals(OperatorType.IS_PART_OF, rule.getOperator()); - assertEquals(expectedFieldType, rule.getField()); - assertTrue(rule.getValues().contains(filterUuid.toString())); - } - - private static Stream voltageLevelRuleData() { - return Stream.of( - Arguments.of(TwoSides.ONE, FieldType.VOLTAGE_LEVEL_ID_1), - Arguments.of(TwoSides.TWO, FieldType.VOLTAGE_LEVEL_ID_2) - ); - } - - @ParameterizedTest - @MethodSource("fieldTypeData") - void shouldReturnCorrectFieldTypes(String category, EquipmentType equipmentType, List expectedFields) { - switch (category) { - case GlobalFilter.Fields.nominalV -> when(filterService.getNominalVoltageFieldType(any())).thenCallRealMethod(); - case GlobalFilter.Fields.countryCode -> when(filterService.getCountryCodeFieldType(any())).thenCallRealMethod(); - case GlobalFilter.Fields.substationProperty -> when(filterService.getSubstationPropertiesFieldTypes(any())).thenCallRealMethod(); - default -> throw new IllegalArgumentException("Unknown category: " + category); - } - List result = switch (category) { - case GlobalFilter.Fields.nominalV -> filterService.getNominalVoltageFieldType(equipmentType); - case GlobalFilter.Fields.countryCode -> filterService.getCountryCodeFieldType(equipmentType); - case GlobalFilter.Fields.substationProperty -> filterService.getSubstationPropertiesFieldTypes(equipmentType); - default -> Collections.emptyList(); - }; - assertEquals(expectedFields, result); - } - - private static Stream fieldTypeData() { - return Stream.of( - // Nominal voltage - Arguments.of(GlobalFilter.Fields.nominalV, EquipmentType.LINE, List.of(FieldType.NOMINAL_VOLTAGE_1, FieldType.NOMINAL_VOLTAGE_2)), - Arguments.of(GlobalFilter.Fields.nominalV, EquipmentType.TWO_WINDINGS_TRANSFORMER, List.of(FieldType.NOMINAL_VOLTAGE_1, FieldType.NOMINAL_VOLTAGE_2)), - Arguments.of(GlobalFilter.Fields.nominalV, EquipmentType.VOLTAGE_LEVEL, List.of(FieldType.NOMINAL_VOLTAGE)), - Arguments.of(GlobalFilter.Fields.nominalV, EquipmentType.GENERATOR, Collections.emptyList()), - - // Country code - Arguments.of(GlobalFilter.Fields.countryCode, EquipmentType.VOLTAGE_LEVEL, List.of(FieldType.COUNTRY)), - Arguments.of(GlobalFilter.Fields.countryCode, EquipmentType.TWO_WINDINGS_TRANSFORMER, List.of(FieldType.COUNTRY)), - Arguments.of(GlobalFilter.Fields.countryCode, EquipmentType.LINE, List.of(FieldType.COUNTRY_1, FieldType.COUNTRY_2)), - Arguments.of(GlobalFilter.Fields.countryCode, EquipmentType.GENERATOR, Collections.emptyList()), - - // Substation properties - Arguments.of(GlobalFilter.Fields.substationProperty, EquipmentType.LINE, List.of(FieldType.SUBSTATION_PROPERTIES_1, FieldType.SUBSTATION_PROPERTIES_2)), - Arguments.of(GlobalFilter.Fields.substationProperty, EquipmentType.GENERATOR, List.of(FieldType.SUBSTATION_PROPERTIES)) - ); - } - - @Test - void shouldReturnEmptyWhenNoExpertFiltersProvided() { - when(filterService.buildAllExpertRules(any(), any())).thenCallRealMethod(); - when(filterService.buildNominalVoltageRules(any(), any())).thenCallRealMethod(); - GlobalFilter globalFilter = mock(GlobalFilter.class); - when(globalFilter.getNominalV()).thenReturn(null); - when(globalFilter.getCountryCode()).thenReturn(null); - when(globalFilter.getSubstationProperty()).thenReturn(null); - List result = filterService.buildAllExpertRules(globalFilter, EquipmentType.GENERATOR); - assertNotNull(result); - assertTrue(result.isEmpty()); - } - - @Test - void shouldReturnRulesWhenFilterExpertRulesProvided() { - when(filterService.buildAllExpertRules(any(), any())).thenCallRealMethod(); - when(filterService.buildNominalVoltageRules(any(), any())).thenCallRealMethod(); - when(filterService.buildCountryCodeRules(any(), any())).thenCallRealMethod(); - when(filterService.buildSubstationPropertyRules(any(), any())).thenCallRealMethod(); - when(filterService.getNominalVoltageFieldType(any())).thenReturn(List.of(FieldType.NOMINAL_VOLTAGE)); - when(filterService.getCountryCodeFieldType(any())).thenReturn(List.of(FieldType.COUNTRY)); - when(filterService.getSubstationPropertiesFieldTypes(any())).thenReturn(List.of(FieldType.SUBSTATION_PROPERTIES)); - when(filterService.createNumberExpertRules(any(), any())).thenCallRealMethod(); - when(filterService.createEnumExpertRules(any(), any())).thenCallRealMethod(); - when(filterService.createPropertiesRule(any(), any(), any())).thenCallRealMethod(); - when(filterService.createOrCombination(any())).thenCallRealMethod(); - GlobalFilter globalFilter = mock(GlobalFilter.class); - when(globalFilter.getNominalV()).thenReturn(List.of("400.0")); - when(globalFilter.getCountryCode()).thenReturn(List.of(Country.FR)); - when(globalFilter.getSubstationProperty()).thenReturn(Map.of("prop1", List.of("value1"))); - List result = filterService.buildAllExpertRules(globalFilter, EquipmentType.GENERATOR); - assertNotNull(result); - assertEquals(3, result.size()); - } - - @Test - void shouldReturnNullWhenNoRules() { - when(filterService.buildExpertFilter(any(), any())).thenCallRealMethod(); - when(filterService.buildAllExpertRules(any(), any())).thenCallRealMethod(); - when(filterService.buildNominalVoltageRules(any(), any())).thenCallRealMethod(); - GlobalFilter globalFilter = mock(GlobalFilter.class); - when(globalFilter.getNominalV()).thenReturn(null); - when(globalFilter.getCountryCode()).thenReturn(null); - when(globalFilter.getSubstationProperty()).thenReturn(null); - ExpertFilter result = filterService.buildExpertFilter(globalFilter, EquipmentType.GENERATOR); - assertNull(result); - } - - @Test - void shouldCreateFilterWhenRulesExist() { - when(filterService.buildExpertFilter(any(), any())).thenCallRealMethod(); - when(filterService.buildAllExpertRules(any(), any())).thenCallRealMethod(); - when(filterService.buildNominalVoltageRules(any(), any())).thenCallRealMethod(); - when(filterService.createCombination(any(), any())).thenCallRealMethod(); - when(filterService.getNominalVoltageFieldType(any())).thenReturn(List.of(FieldType.NOMINAL_VOLTAGE)); - when(filterService.createNumberExpertRules(any(), any())).thenCallRealMethod(); - when(filterService.createOrCombination(any())).thenCallRealMethod(); - GlobalFilter globalFilter = mock(GlobalFilter.class); - when(globalFilter.getNominalV()).thenReturn(List.of("400.0")); - when(globalFilter.getCountryCode()).thenReturn(null); - when(globalFilter.getSubstationProperty()).thenReturn(null); - ExpertFilter result = filterService.buildExpertFilter(globalFilter, EquipmentType.GENERATOR); - assertNotNull(result); - assertEquals(EquipmentType.GENERATOR, result.getEquipmentType()); - assertNotNull(result.getRules()); - assertInstanceOf(CombinatorExpertRule.class, result.getRules()); - } - - @Test - void shouldReturnFilteredNetworkWhenSameEquipmentType() { - when(filterService.extractEquipmentIdsFromGenericFilter(any(), any(), any())).thenCallRealMethod(); - when(filterService.filterNetwork(any(), any())).thenCallRealMethod(); - AbstractFilter filter = mock(AbstractFilter.class); - when(filter.getEquipmentType()).thenReturn(EquipmentType.GENERATOR); - try (MockedStatic mockStatic = mockStatic(FilterServiceUtils.class)) { - List attributes = Arrays.asList( - createIdentifiableAttributes("gen1"), - createIdentifiableAttributes("gen2") - ); - mockStatic.when(() -> FilterServiceUtils.getIdentifiableAttributes(filter, network, filterService)).thenReturn(attributes); - List result = filterService.extractEquipmentIdsFromGenericFilter(filter, EquipmentType.GENERATOR, network); - assertEquals(Arrays.asList("gen1", "gen2"), result); - } - } - - @Test - void shouldBuildVoltageLevelFilterWhenVoltageLevelType() { - when(filterService.extractEquipmentIdsFromGenericFilter(any(), any(), any())).thenCallRealMethod(); - when(filterService.buildExpertFilterWithVoltageLevelIdsCriteria(any(), any())).thenCallRealMethod(); - when(filterService.createVoltageLevelIdRule(any(), any())).thenCallRealMethod(); - when(filterService.createCombination(any(), any())).thenCallRealMethod(); - when(filterService.filterNetwork(any(), any())).thenCallRealMethod(); - AbstractFilter filter = mock(AbstractFilter.class); - when(filter.getEquipmentType()).thenReturn(EquipmentType.VOLTAGE_LEVEL); - when(filter.getId()).thenReturn(FILTER_UUID); - try (MockedStatic mockStatic = mockStatic(FilterServiceUtils.class)) { - List attributes = Arrays.asList( - createIdentifiableAttributes("line1"), - createIdentifiableAttributes("line2") - ); - mockStatic.when(() -> FilterServiceUtils.getIdentifiableAttributes(any(ExpertFilter.class), eq(network), eq(filterService))).thenReturn(attributes); - List result = filterService.extractEquipmentIdsFromGenericFilter(filter, EquipmentType.LINE, network); - assertEquals(Arrays.asList("line1", "line2"), result); - } - } - - @Test - void shouldReturnEmptyWhenDifferentEquipmentType() { - when(filterService.extractEquipmentIdsFromGenericFilter(any(), any(), any())).thenCallRealMethod(); - AbstractFilter filter = mock(AbstractFilter.class); - when(filter.getEquipmentType()).thenReturn(EquipmentType.LOAD); - List result = filterService.extractEquipmentIdsFromGenericFilter(filter, EquipmentType.GENERATOR, network); - assertTrue(result.isEmpty()); - } - - @Test - void shouldCreateExpertFilterWithVoltageLevelIdsCriteria() { - when(filterService.buildExpertFilterWithVoltageLevelIdsCriteria(any(), any())).thenCallRealMethod(); - when(filterService.createVoltageLevelIdRule(any(), any())).thenCallRealMethod(); - when(filterService.createCombination(any(), any())).thenCallRealMethod(); - UUID filterUuid = UUID.randomUUID(); - EquipmentType equipmentType = EquipmentType.LINE; - ExpertFilter result = filterService.buildExpertFilterWithVoltageLevelIdsCriteria(filterUuid, equipmentType); - assertNotNull(result); - assertEquals(equipmentType, result.getEquipmentType()); - assertNotNull(result.getRules()); - assertInstanceOf(CombinatorExpertRule.class, result.getRules()); - CombinatorExpertRule combinatorRule = (CombinatorExpertRule) result.getRules(); - assertEquals(CombinatorType.OR, combinatorRule.getCombinator()); - assertEquals(2, combinatorRule.getRules().size()); - } - - @Test - void shouldReturnEmptyWhenNoFilterResults() { - when(filterService.getResourceFilter(any(), any(), any(), any(), any())).thenCallRealMethod(); - when(filterService.getNetwork(any(), any())).thenReturn(network); - when(filterService.getFilters(any())).thenReturn(Collections.emptyList()); - when(filterService.filterEquipmentsByType(any(), any(), any(), any())).thenReturn(Collections.emptyMap()); - GlobalFilter globalFilter = mock(GlobalFilter.class); - when(globalFilter.getGenericFilter()).thenReturn(Collections.emptyList()); - List equipmentTypes = List.of(EquipmentType.LINE); - String columnName = "functionId"; - Optional result = filterService.getResourceFilter(NETWORK_UUID, VARIANT_ID, globalFilter, equipmentTypes, columnName); - assertNotNull(result); - assertFalse(result.isPresent()); - } - - @Test - void shouldReturnResourceFilterWithResults() { - when(filterService.getResourceFilter(any(), any(), any(), any(), any())).thenCallRealMethod(); - when(filterService.getNetwork(any(), any())).thenReturn(network); - when(filterService.getFilters(any())).thenReturn(Collections.emptyList()); - Map> equipmentResults = new EnumMap<>(EquipmentType.class); - equipmentResults.put(EquipmentType.LINE, Arrays.asList("line1", "line2")); - equipmentResults.put(EquipmentType.GENERATOR, List.of("gen1")); - when(filterService.filterEquipmentsByType(any(), any(), any(), any())).thenReturn(equipmentResults); - GlobalFilter globalFilter = mock(GlobalFilter.class); - when(globalFilter.getGenericFilter()).thenReturn(Collections.emptyList()); - List equipmentTypes = Arrays.asList(EquipmentType.LINE, EquipmentType.GENERATOR); - String columnName = "functionId"; - Optional result = filterService.getResourceFilter(NETWORK_UUID, VARIANT_ID, globalFilter, equipmentTypes, columnName); - assertNotNull(result); - assertTrue(result.isPresent()); - ResourceFilterDTO dto = result.get(); - assertEquals(ResourceFilterDTO.DataType.TEXT, dto.dataType()); - assertEquals(ResourceFilterDTO.Type.IN, dto.type()); - assertEquals(columnName, dto.column()); - assertEquals(3, ((List) dto.value()).size()); - } - - private IdentifiableAttributes createIdentifiableAttributes(String id) { - IdentifiableAttributes attributes = mock(IdentifiableAttributes.class); - when(attributes.getId()).thenReturn(id); - return attributes; - } }