From a95b8f1c2588ce1276ac79ebf70832b1e27292fa Mon Sep 17 00:00:00 2001 From: LE SAULNIER Kevin Date: Tue, 13 Jan 2026 16:23:02 +0100 Subject: [PATCH 1/3] feat: move equipment type filters evalutation to filter lib Signed-off-by: LE SAULNIER Kevin --- pom.xml | 2 +- .../filter/server/FilterController.java | 4 +- .../filter/server/FilterLoaderImpl.java | 3 +- .../filter/server/FilterService.java | 76 +++++-------------- .../filter/server/GlobalFilterService.java | 8 ++ .../filter/server/RepositoryService.java | 2 +- .../server/dto/EquipmentTypesByFilterId.java | 21 ----- .../filter/server/dto/FilterAttributes.java | 41 ---------- .../server/dto/FiltersWithEquipmentTypes.java | 19 ----- .../server/repositories/FilterMetadata.java | 17 ----- .../server/repositories/FilterRepository.java | 1 + .../AbstractFilterRepositoryProxy.java | 4 +- .../server/FilterEntityControllerTest.java | 8 +- 13 files changed, 39 insertions(+), 167 deletions(-) delete mode 100644 src/main/java/org/gridsuite/filter/server/dto/EquipmentTypesByFilterId.java delete mode 100644 src/main/java/org/gridsuite/filter/server/dto/FilterAttributes.java delete mode 100644 src/main/java/org/gridsuite/filter/server/dto/FiltersWithEquipmentTypes.java delete mode 100644 src/main/java/org/gridsuite/filter/server/repositories/FilterMetadata.java diff --git a/pom.xml b/pom.xml index 9b7468ba..3cf408e0 100644 --- a/pom.xml +++ b/pom.xml @@ -44,7 +44,7 @@ 46.0.0 - 1.18.0 + 1.19.0-SNAPSHOT 4.3.1 org.gridsuite.filter.server **/migrations/**/* diff --git a/src/main/java/org/gridsuite/filter/server/FilterController.java b/src/main/java/org/gridsuite/filter/server/FilterController.java index 15b665ac..aa600f2e 100644 --- a/src/main/java/org/gridsuite/filter/server/FilterController.java +++ b/src/main/java/org/gridsuite/filter/server/FilterController.java @@ -16,9 +16,9 @@ import org.gridsuite.filter.identifierlistfilter.FilterEquipments; import org.gridsuite.filter.identifierlistfilter.FilteredIdentifiables; import org.gridsuite.filter.identifierlistfilter.IdentifiableAttributes; -import org.gridsuite.filter.server.dto.FilterAttributes; -import org.gridsuite.filter.server.dto.FiltersWithEquipmentTypes; +import org.gridsuite.filter.identifierlistfilter.FilterAttributes; import org.gridsuite.filter.server.dto.IdsByGroup; +import org.gridsuite.filter.utils.FiltersWithEquipmentTypes; import org.springframework.context.annotation.ComponentScan; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; diff --git a/src/main/java/org/gridsuite/filter/server/FilterLoaderImpl.java b/src/main/java/org/gridsuite/filter/server/FilterLoaderImpl.java index 008f2464..d7aa9ac4 100644 --- a/src/main/java/org/gridsuite/filter/server/FilterLoaderImpl.java +++ b/src/main/java/org/gridsuite/filter/server/FilterLoaderImpl.java @@ -26,7 +26,8 @@ public FilterLoaderImpl(Map> filterR this.filterRepositories = filterRepositories; } - private Optional getFilter(UUID id) { + @Override + public Optional getFilter(UUID id) { Objects.requireNonNull(id); for (AbstractFilterRepositoryProxy repository : filterRepositories.values()) { Optional res = repository.getFilter(id); diff --git a/src/main/java/org/gridsuite/filter/server/FilterService.java b/src/main/java/org/gridsuite/filter/server/FilterService.java index f330ba5a..b9c54b9c 100644 --- a/src/main/java/org/gridsuite/filter/server/FilterService.java +++ b/src/main/java/org/gridsuite/filter/server/FilterService.java @@ -7,7 +7,6 @@ package org.gridsuite.filter.server; import com.powsybl.commons.PowsyblException; -import com.powsybl.iidm.network.IdentifiableType; import com.powsybl.iidm.network.Network; import com.powsybl.network.store.client.NetworkStoreService; import com.powsybl.network.store.client.PreloadingStrategy; @@ -17,22 +16,18 @@ import org.gridsuite.filter.FilterLoader; import org.gridsuite.filter.IFilterAttributes; import org.gridsuite.filter.exception.FilterCycleException; -import org.gridsuite.filter.expertfilter.ExpertFilter; import org.gridsuite.filter.identifierlistfilter.FilterEquipments; import org.gridsuite.filter.identifierlistfilter.FilteredIdentifiables; import org.gridsuite.filter.identifierlistfilter.IdentifiableAttributes; -import org.gridsuite.filter.server.dto.EquipmentTypesByFilterId; -import org.gridsuite.filter.server.dto.FilterAttributes; -import org.gridsuite.filter.server.dto.FiltersWithEquipmentTypes; +import org.gridsuite.filter.identifierlistfilter.FilterAttributes; import org.gridsuite.filter.server.dto.IdsByGroup; import org.gridsuite.filter.server.error.FilterBusinessErrorCode; import org.gridsuite.filter.server.error.FilterException; import org.gridsuite.filter.server.repositories.proxies.AbstractFilterRepositoryProxy; import org.gridsuite.filter.server.service.DirectoryService; -import org.gridsuite.filter.server.utils.FilterWithEquipmentTypesUtils; -import org.gridsuite.filter.utils.EquipmentType; import org.gridsuite.filter.utils.FilterServiceUtils; import org.gridsuite.filter.utils.FilterType; +import org.gridsuite.filter.utils.FiltersWithEquipmentTypes; import org.gridsuite.filter.utils.expertfilter.FilterCycleDetector; import org.springframework.context.annotation.ComponentScan; import org.springframework.http.HttpStatus; @@ -41,7 +36,6 @@ import org.springframework.web.server.ResponseStatusException; import java.util.*; -import java.util.Comparator; import java.util.stream.Collectors; /** @@ -170,9 +164,22 @@ private AbstractFilter doUpdateFilter(UUID id, AbstractFilter newFilter, String if (filterOpt.isPresent()) { newFilter.setId(id); - FilterLoader filterLoader = uuids -> uuids.stream() - .map(uuid -> uuid.equals(id) ? newFilter : this.repositoriesService.getFilter(uuid).orElse(null)) - .toList(); + FilterLoader filterLoader = new FilterLoader() { + @Override + public List getFilters(List uuids) { + return uuids.stream() + .map(uuid -> uuid.equals(id) ? newFilter : repositoriesService.getFilter(uuid).orElse(null)) + .toList(); + } + + @Override + public Optional getFilter(UUID uuid) { + return uuid.equals(id) + ? Optional.of(newFilter) + : repositoriesService.getFilter(uuid); + } + }; + try { FilterCycleDetector.checkNoCycle(newFilter, filterLoader); } catch (FilterCycleException exception) { @@ -251,55 +258,10 @@ public List evaluateFilter(AbstractFilter filter, UUID n @Transactional(readOnly = true) public FilteredIdentifiables evaluateFiltersWithEquipmentTypes(FiltersWithEquipmentTypes filtersWithEquipmentTypes, UUID networkUuid, String variantId) { - Map result = new TreeMap<>(); - Map notFound = new TreeMap<>(); Network network = getNetwork(networkUuid, variantId); FilterLoader filterLoader = this.repositoriesService.getFilterLoader(); - filtersWithEquipmentTypes.filters().forEach((FilterAttributes filterAttributes) -> { - UUID filterUuid = filterAttributes.getId(); - Optional optFilter = this.repositoriesService.getFilter(filterUuid); - if (optFilter.isEmpty()) { - return; - } - AbstractFilter filter = optFilter.get(); - Objects.requireNonNull(filter); - EquipmentType filterEquipmentType = filter.getEquipmentType(); - FilteredIdentifiables filteredIdentifiables = filter.toFilteredIdentifiables(FilterServiceUtils.getIdentifiableAttributes(filter, network, filterLoader)); - - // unduplicate equipments and merge in common lists - if (filteredIdentifiables.notFoundIds() != null) { - filteredIdentifiables.notFoundIds().forEach(element -> notFound.put(element.getId(), element)); - } - - if (filteredIdentifiables.equipmentIds() != null) { - if (filterEquipmentType != EquipmentType.SUBSTATION && filterEquipmentType != EquipmentType.VOLTAGE_LEVEL) { - filteredIdentifiables.equipmentIds().forEach(element -> result.put(element.getId(), element)); - } else { - Set selectedEquipmentTypes = filtersWithEquipmentTypes.selectedEquipmentTypesByFilter() - .stream() - .filter(equipmentTypesByFilterId -> equipmentTypesByFilterId.filterId().equals(filterUuid)) - .findFirst() - .map(EquipmentTypesByFilterId::equipmentTypes) - .orElseThrow( - () -> new IllegalStateException("No selected equipment types for filter " + filterUuid - + " : substation and voltage level filters should contain an equipment types list") - ); - - // This list is the result of the original filter and so necessarily contains a list of IDs of substations or voltage levels - Set filteredEquipmentIds = filteredIdentifiables.equipmentIds().stream().map(IdentifiableAttributes::getId).collect(Collectors.toSet()); - List filters = FilterWithEquipmentTypesUtils.createFiltersForSubEquipments(filterEquipmentType, - filteredEquipmentIds, - selectedEquipmentTypes); - filters.stream().flatMap(expertFilter -> getIdentifiableAttributes(expertFilter, networkUuid, variantId, filterLoader).stream()) - .forEach(element -> result.put(element.getId(), element)); - } - } - } - ); - return new FilteredIdentifiables( - result.values().stream().sorted(Comparator.comparing(e -> e.getType().ordinal())).toList(), - notFound.values().stream().sorted(Comparator.comparing(e -> e.getType().ordinal())).toList()); + return FilterServiceUtils.evaluateFiltersWithEquipmentTypes(filtersWithEquipmentTypes, network, filterLoader); } @Transactional(readOnly = true) diff --git a/src/main/java/org/gridsuite/filter/server/GlobalFilterService.java b/src/main/java/org/gridsuite/filter/server/GlobalFilterService.java index 3a926897..2c90263d 100644 --- a/src/main/java/org/gridsuite/filter/server/GlobalFilterService.java +++ b/src/main/java/org/gridsuite/filter/server/GlobalFilterService.java @@ -16,6 +16,7 @@ import org.springframework.web.server.ResponseStatusException; import java.util.List; +import java.util.Optional; import java.util.UUID; @Service @@ -43,6 +44,13 @@ public List getFilters(@NonNull final List filtersUuids) { return this.repositoriesService.getFilters(filtersUuids); } + /** {@inheritDoc} */ + @Override + @Transactional(readOnly = true) + public Optional getFilter(UUID uuid) { + return this.repositoriesService.getFilter(uuid); + } + /* Expose it publicly */ /** {@inheritDoc} */ @Override diff --git a/src/main/java/org/gridsuite/filter/server/RepositoryService.java b/src/main/java/org/gridsuite/filter/server/RepositoryService.java index 1a31b13d..fa784f5c 100644 --- a/src/main/java/org/gridsuite/filter/server/RepositoryService.java +++ b/src/main/java/org/gridsuite/filter/server/RepositoryService.java @@ -5,7 +5,7 @@ import org.apache.commons.collections4.ListUtils; import org.gridsuite.filter.AbstractFilter; import org.gridsuite.filter.FilterLoader; -import org.gridsuite.filter.server.dto.FilterAttributes; +import org.gridsuite.filter.identifierlistfilter.FilterAttributes; import org.gridsuite.filter.server.repositories.expertfilter.ExpertFilterRepository; import org.gridsuite.filter.server.repositories.identifierlistfilter.IdentifierListFilterRepository; import org.gridsuite.filter.server.repositories.proxies.AbstractFilterRepositoryProxy; diff --git a/src/main/java/org/gridsuite/filter/server/dto/EquipmentTypesByFilterId.java b/src/main/java/org/gridsuite/filter/server/dto/EquipmentTypesByFilterId.java deleted file mode 100644 index fd6c2f5d..00000000 --- a/src/main/java/org/gridsuite/filter/server/dto/EquipmentTypesByFilterId.java +++ /dev/null @@ -1,21 +0,0 @@ -/** - * Copyright (c) 2025, RTE (http://www.rte-france.com) - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -package org.gridsuite.filter.server.dto; - -import com.powsybl.iidm.network.IdentifiableType; - -import java.util.Set; -import java.util.UUID; - -/** - * Store a list of equipment types for a given filter ID - * - * @author Florent MILLOT - */ -public record EquipmentTypesByFilterId(UUID filterId, Set equipmentTypes) { -} diff --git a/src/main/java/org/gridsuite/filter/server/dto/FilterAttributes.java b/src/main/java/org/gridsuite/filter/server/dto/FilterAttributes.java deleted file mode 100644 index a7fb46b2..00000000 --- a/src/main/java/org/gridsuite/filter/server/dto/FilterAttributes.java +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Copyright (c) 2021, RTE (http://www.rte-france.com) - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -package org.gridsuite.filter.server.dto; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import org.gridsuite.filter.IFilterAttributes; -import org.gridsuite.filter.server.repositories.FilterMetadata; -import org.gridsuite.filter.utils.EquipmentType; -import org.gridsuite.filter.utils.FilterType; - -import java.util.Date; -import java.util.UUID; - -/** - * @author Jacques Borsenberger - */ - -@Getter -@Setter -@NoArgsConstructor -public class FilterAttributes implements IFilterAttributes { - UUID id; - Date modificationDate; - FilterType type; - EquipmentType equipmentType; - String name; - - public FilterAttributes(FilterMetadata filterMetadata, FilterType type, EquipmentType equipmentType) { - id = filterMetadata.getId(); - modificationDate = filterMetadata.getModificationDate(); - this.type = type; - this.equipmentType = equipmentType; - } -} diff --git a/src/main/java/org/gridsuite/filter/server/dto/FiltersWithEquipmentTypes.java b/src/main/java/org/gridsuite/filter/server/dto/FiltersWithEquipmentTypes.java deleted file mode 100644 index d1c6087d..00000000 --- a/src/main/java/org/gridsuite/filter/server/dto/FiltersWithEquipmentTypes.java +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Copyright (c) 2025, RTE (http://www.rte-france.com) - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -package org.gridsuite.filter.server.dto; - -import java.util.List; - -/** - * Store a list of filters and the equipment types that are associated with. - * - * @author Florent MILLOT - */ -public record FiltersWithEquipmentTypes(List filters, - List selectedEquipmentTypesByFilter) { -} diff --git a/src/main/java/org/gridsuite/filter/server/repositories/FilterMetadata.java b/src/main/java/org/gridsuite/filter/server/repositories/FilterMetadata.java deleted file mode 100644 index 64bcca4c..00000000 --- a/src/main/java/org/gridsuite/filter/server/repositories/FilterMetadata.java +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright (c) 2021, RTE (http://www.rte-france.com) - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -package org.gridsuite.filter.server.repositories; - -/** - * @author Jacques Borsenberger - */ -public interface FilterMetadata { - java.util.UUID getId(); - - java.util.Date getModificationDate(); -} diff --git a/src/main/java/org/gridsuite/filter/server/repositories/FilterRepository.java b/src/main/java/org/gridsuite/filter/server/repositories/FilterRepository.java index 923a8840..3507323b 100644 --- a/src/main/java/org/gridsuite/filter/server/repositories/FilterRepository.java +++ b/src/main/java/org/gridsuite/filter/server/repositories/FilterRepository.java @@ -7,6 +7,7 @@ package org.gridsuite.filter.server.repositories; +import org.gridsuite.filter.identifierlistfilter.FilterMetadata; import org.gridsuite.filter.server.entities.AbstractFilterEntity; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; diff --git a/src/main/java/org/gridsuite/filter/server/repositories/proxies/AbstractFilterRepositoryProxy.java b/src/main/java/org/gridsuite/filter/server/repositories/proxies/AbstractFilterRepositoryProxy.java index 53e89c1e..fdb046c0 100644 --- a/src/main/java/org/gridsuite/filter/server/repositories/proxies/AbstractFilterRepositoryProxy.java +++ b/src/main/java/org/gridsuite/filter/server/repositories/proxies/AbstractFilterRepositoryProxy.java @@ -8,9 +8,9 @@ package org.gridsuite.filter.server.repositories.proxies; import org.gridsuite.filter.AbstractFilter; -import org.gridsuite.filter.server.dto.FilterAttributes; +import org.gridsuite.filter.identifierlistfilter.FilterAttributes; import org.gridsuite.filter.server.entities.AbstractFilterEntity; -import org.gridsuite.filter.server.repositories.FilterMetadata; +import org.gridsuite.filter.identifierlistfilter.FilterMetadata; import org.gridsuite.filter.server.repositories.FilterRepository; import org.gridsuite.filter.utils.EquipmentType; import org.gridsuite.filter.utils.FilterType; diff --git a/src/test/java/org/gridsuite/filter/server/FilterEntityControllerTest.java b/src/test/java/org/gridsuite/filter/server/FilterEntityControllerTest.java index e4f43ca0..e2ebf94a 100644 --- a/src/test/java/org/gridsuite/filter/server/FilterEntityControllerTest.java +++ b/src/test/java/org/gridsuite/filter/server/FilterEntityControllerTest.java @@ -27,17 +27,15 @@ import org.gridsuite.filter.IFilterAttributes; import org.gridsuite.filter.expertfilter.ExpertFilter; import org.gridsuite.filter.expertfilter.expertrule.*; -import org.gridsuite.filter.identifierlistfilter.FilterEquipments; -import org.gridsuite.filter.identifierlistfilter.FilteredIdentifiables; -import org.gridsuite.filter.identifierlistfilter.IdentifiableAttributes; -import org.gridsuite.filter.identifierlistfilter.IdentifierListFilter; -import org.gridsuite.filter.identifierlistfilter.IdentifierListFilterEquipmentAttributes; +import org.gridsuite.filter.identifierlistfilter.*; import org.gridsuite.filter.server.dto.*; import org.gridsuite.filter.server.service.DirectoryService; import org.gridsuite.filter.server.utils.MatcherJson; import org.gridsuite.filter.server.utils.assertions.Assertions; import org.gridsuite.filter.utils.EquipmentType; +import org.gridsuite.filter.utils.EquipmentTypesByFilterId; import org.gridsuite.filter.utils.FilterType; +import org.gridsuite.filter.utils.FiltersWithEquipmentTypes; import org.gridsuite.filter.utils.expertfilter.CombinatorType; import org.gridsuite.filter.utils.expertfilter.FieldType; import org.gridsuite.filter.utils.expertfilter.OperatorType; From 402c495ea44834555bcd41e12c0c3072407b7f4f Mon Sep 17 00:00:00 2001 From: LE SAULNIER Kevin Date: Mon, 2 Feb 2026 14:08:37 +0100 Subject: [PATCH 2/3] move test to lib Signed-off-by: LE SAULNIER Kevin --- .../FilterWithEquipmentTypesUtilsTest.java | 193 ------------------ 1 file changed, 193 deletions(-) delete mode 100644 src/test/java/org/gridsuite/filter/server/utils/FilterWithEquipmentTypesUtilsTest.java diff --git a/src/test/java/org/gridsuite/filter/server/utils/FilterWithEquipmentTypesUtilsTest.java b/src/test/java/org/gridsuite/filter/server/utils/FilterWithEquipmentTypesUtilsTest.java deleted file mode 100644 index 7d6277ab..00000000 --- a/src/test/java/org/gridsuite/filter/server/utils/FilterWithEquipmentTypesUtilsTest.java +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright (c) 2025, RTE - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -package org.gridsuite.filter.server.utils; - -import com.powsybl.iidm.network.IdentifiableType; -import org.gridsuite.filter.expertfilter.ExpertFilter; -import org.gridsuite.filter.expertfilter.expertrule.AbstractExpertRule; -import org.gridsuite.filter.expertfilter.expertrule.CombinatorExpertRule; -import org.gridsuite.filter.expertfilter.expertrule.StringExpertRule; -import org.gridsuite.filter.utils.EquipmentType; -import org.gridsuite.filter.utils.expertfilter.CombinatorType; -import org.gridsuite.filter.utils.expertfilter.FieldType; -import org.gridsuite.filter.utils.expertfilter.OperatorType; -import org.junit.Test; - -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Set; - -import static org.junit.Assert.*; - -/** - * Unit tests for FilterWithEquipmentTypesUtils - * @author Florent MILLOT - */ -public class FilterWithEquipmentTypesUtilsTest { - - @Test - public void testCreateRuleWithOneField() { - Set ids = new LinkedHashSet<>(Set.of("S1", "S2")); - AbstractExpertRule rule = FilterWithEquipmentTypesUtils.createRuleWithOneField(ids, FieldType.SUBSTATION_ID); - assertTrue(rule instanceof StringExpertRule); - StringExpertRule stringRule = (StringExpertRule) rule; - assertEquals(OperatorType.IN, stringRule.getOperator()); - assertEquals(FieldType.SUBSTATION_ID, stringRule.getField()); - assertEquals(ids, stringRule.getValues()); - } - - @Test - public void testCreateRuleWithTwoFields() { - Set ids = new LinkedHashSet<>(Set.of("S1")); - AbstractExpertRule rule = FilterWithEquipmentTypesUtils.createRuleWithTwoFields(ids, FieldType.SUBSTATION_ID_1, FieldType.SUBSTATION_ID_2); - assertTrue(rule instanceof CombinatorExpertRule); - CombinatorExpertRule comb = (CombinatorExpertRule) rule; - assertEquals(CombinatorType.OR, comb.getCombinator()); - List rules = comb.getRules(); - assertEquals(2, rules.size()); - assertTrue(rules.get(0) instanceof StringExpertRule); - assertTrue(rules.get(1) instanceof StringExpertRule); - StringExpertRule r1 = (StringExpertRule) rules.get(0); - StringExpertRule r2 = (StringExpertRule) rules.get(1); - assertEquals(OperatorType.IN, r1.getOperator()); - assertEquals(OperatorType.IN, r2.getOperator()); - assertEquals(FieldType.SUBSTATION_ID_1, r1.getField()); - assertEquals(FieldType.SUBSTATION_ID_2, r2.getField()); - assertEquals(ids, r1.getValues()); - assertEquals(ids, r2.getValues()); - } - - @Test - public void testCreateRuleWithThreeFields() { - Set ids = new LinkedHashSet<>(Set.of("VL1")); - AbstractExpertRule rule = FilterWithEquipmentTypesUtils.createRuleWithThreeFields(ids, FieldType.VOLTAGE_LEVEL_ID_1, FieldType.VOLTAGE_LEVEL_ID_2, FieldType.VOLTAGE_LEVEL_ID_3); - assertTrue(rule instanceof CombinatorExpertRule); - CombinatorExpertRule comb = (CombinatorExpertRule) rule; - assertEquals(CombinatorType.OR, comb.getCombinator()); - List rules = comb.getRules(); - assertEquals(3, rules.size()); - StringExpertRule r1 = (StringExpertRule) rules.get(0); - StringExpertRule r2 = (StringExpertRule) rules.get(1); - StringExpertRule r3 = (StringExpertRule) rules.get(2); - assertEquals(FieldType.VOLTAGE_LEVEL_ID_1, r1.getField()); - assertEquals(FieldType.VOLTAGE_LEVEL_ID_2, r2.getField()); - assertEquals(FieldType.VOLTAGE_LEVEL_ID_3, r3.getField()); - assertEquals(ids, r1.getValues()); - assertEquals(ids, r2.getValues()); - assertEquals(ids, r3.getValues()); - } - - @Test - public void testCreateSubstationRuleByEquipmentType() { - Set subs = new LinkedHashSet<>(Set.of("S1")); - // LOAD -> one field (SUBSTATION_ID) - AbstractExpertRule loadRule = FilterWithEquipmentTypesUtils.createSubstationRuleByEquipmentType(IdentifiableType.LOAD, subs); - assertTrue(loadRule instanceof StringExpertRule); - assertEquals(FieldType.SUBSTATION_ID, loadRule.getField()); - assertEquals(subs, ((StringExpertRule) loadRule).getValues()); - // LINE -> two fields (SUBSTATION_ID_1, _2) - AbstractExpertRule lineRule = FilterWithEquipmentTypesUtils.createSubstationRuleByEquipmentType(IdentifiableType.LINE, subs); - assertTrue(lineRule instanceof CombinatorExpertRule); - CombinatorExpertRule comb = (CombinatorExpertRule) lineRule; - assertEquals(2, comb.getRules().size()); - StringExpertRule r1 = (StringExpertRule) comb.getRules().get(0); - StringExpertRule r2 = (StringExpertRule) comb.getRules().get(1); - assertEquals(FieldType.SUBSTATION_ID_1, r1.getField()); - assertEquals(FieldType.SUBSTATION_ID_2, r2.getField()); - assertEquals(subs, r1.getValues()); - assertEquals(subs, r2.getValues()); - } - - @Test - public void testCreateVoltageLevelRuleByEquipmentType() { - Set vls = new LinkedHashSet<>(Set.of("VL1", "VL2")); - // LOAD -> one field (VOLTAGE_LEVEL_ID) - AbstractExpertRule loadRule = FilterWithEquipmentTypesUtils.createVoltageLevelRuleByEquipmentType(IdentifiableType.LOAD, vls); - assertTrue(loadRule instanceof StringExpertRule); - assertEquals(FieldType.VOLTAGE_LEVEL_ID, loadRule.getField()); - assertEquals(vls, ((StringExpertRule) loadRule).getValues()); - // LINE -> two fields - AbstractExpertRule lineRule = FilterWithEquipmentTypesUtils.createVoltageLevelRuleByEquipmentType(IdentifiableType.LINE, vls); - assertTrue(lineRule instanceof CombinatorExpertRule); - CombinatorExpertRule comb2 = (CombinatorExpertRule) lineRule; - assertEquals(2, comb2.getRules().size()); - assertEquals(FieldType.VOLTAGE_LEVEL_ID_1, comb2.getRules().get(0).getField()); - assertEquals(FieldType.VOLTAGE_LEVEL_ID_2, comb2.getRules().get(1).getField()); - assertEquals(vls, ((StringExpertRule) comb2.getRules().get(0)).getValues()); - assertEquals(vls, ((StringExpertRule) comb2.getRules().get(1)).getValues()); - // THREE_WINDINGS_TRANSFORMER -> three fields - AbstractExpertRule twtRule = FilterWithEquipmentTypesUtils.createVoltageLevelRuleByEquipmentType(IdentifiableType.THREE_WINDINGS_TRANSFORMER, vls); - assertTrue(twtRule instanceof CombinatorExpertRule); - CombinatorExpertRule comb3 = (CombinatorExpertRule) twtRule; - assertEquals(3, comb3.getRules().size()); - assertEquals(FieldType.VOLTAGE_LEVEL_ID_1, comb3.getRules().get(0).getField()); - assertEquals(FieldType.VOLTAGE_LEVEL_ID_2, comb3.getRules().get(1).getField()); - assertEquals(FieldType.VOLTAGE_LEVEL_ID_3, comb3.getRules().get(2).getField()); - assertEquals(vls, ((StringExpertRule) comb3.getRules().get(0)).getValues()); - assertEquals(vls, ((StringExpertRule) comb3.getRules().get(1)).getValues()); - assertEquals(vls, ((StringExpertRule) comb3.getRules().get(2)).getValues()); - } - - @Test - public void testCreateFiltersForSubEquipmentsFromSubstation() { - Set parentIds = new LinkedHashSet<>(Set.of("S1", "S2")); - Set subTypes = Set.of(IdentifiableType.LOAD, IdentifiableType.LINE); - List filters = FilterWithEquipmentTypesUtils.createFiltersForSubEquipments(EquipmentType.SUBSTATION, parentIds, subTypes); - assertEquals(2, filters.size()); - for (ExpertFilter f : filters) { - if (f.getEquipmentType() == EquipmentType.LOAD) { - assertTrue(f.getRules() instanceof StringExpertRule); - assertEquals(FieldType.SUBSTATION_ID, ((StringExpertRule) f.getRules()).getField()); - assertEquals(parentIds, ((StringExpertRule) f.getRules()).getValues()); - } else if (f.getEquipmentType() == EquipmentType.LINE) { - assertTrue(f.getRules() instanceof CombinatorExpertRule); - CombinatorExpertRule comb = (CombinatorExpertRule) f.getRules(); - assertEquals(CombinatorType.OR, comb.getCombinator()); - assertEquals(2, comb.getRules().size()); - assertEquals(FieldType.SUBSTATION_ID_1, ((StringExpertRule) comb.getRules().get(0)).getField()); - assertEquals(FieldType.SUBSTATION_ID_2, ((StringExpertRule) comb.getRules().get(1)).getField()); - assertEquals(parentIds, ((StringExpertRule) comb.getRules().get(0)).getValues()); - assertEquals(parentIds, ((StringExpertRule) comb.getRules().get(1)).getValues()); - } else { - fail("Unexpected equipment type: " + f.getEquipmentType()); - } - } - } - - @Test - public void testCreateFiltersForSubEquipmentsFromVoltageLevel() { - Set parentIds = new LinkedHashSet<>(Set.of("VL1")); - Set subTypes = Set.of(IdentifiableType.GENERATOR, IdentifiableType.THREE_WINDINGS_TRANSFORMER); - List filters = FilterWithEquipmentTypesUtils.createFiltersForSubEquipments(EquipmentType.VOLTAGE_LEVEL, parentIds, subTypes); - assertEquals(2, filters.size()); - for (ExpertFilter f : filters) { - if (f.getEquipmentType() == EquipmentType.GENERATOR) { - assertTrue(f.getRules() instanceof StringExpertRule); - assertEquals(FieldType.VOLTAGE_LEVEL_ID, ((StringExpertRule) f.getRules()).getField()); - assertEquals(parentIds, ((StringExpertRule) f.getRules()).getValues()); - } else if (f.getEquipmentType() == EquipmentType.THREE_WINDINGS_TRANSFORMER) { - assertTrue(f.getRules() instanceof CombinatorExpertRule); - CombinatorExpertRule comb = (CombinatorExpertRule) f.getRules(); - assertEquals(3, comb.getRules().size()); - assertEquals(FieldType.VOLTAGE_LEVEL_ID_1, ((StringExpertRule) comb.getRules().get(0)).getField()); - assertEquals(FieldType.VOLTAGE_LEVEL_ID_2, ((StringExpertRule) comb.getRules().get(1)).getField()); - assertEquals(FieldType.VOLTAGE_LEVEL_ID_3, ((StringExpertRule) comb.getRules().get(2)).getField()); - assertEquals(parentIds, ((StringExpertRule) comb.getRules().get(0)).getValues()); - assertEquals(parentIds, ((StringExpertRule) comb.getRules().get(1)).getValues()); - assertEquals(parentIds, ((StringExpertRule) comb.getRules().get(2)).getValues()); - } else { - fail("Unexpected equipment type: " + f.getEquipmentType()); - } - } - } - - @Test(expected = UnsupportedOperationException.class) - public void testCreateFiltersForSubEquipmentsUnsupported() { - FilterWithEquipmentTypesUtils.createFiltersForSubEquipments(EquipmentType.LINE, Set.of("X"), Set.of(IdentifiableType.LOAD)); - } -} From d7eb5de6510f77fa4e50d9ba8ad1b696e128a606 Mon Sep 17 00:00:00 2001 From: Thang PHAM Date: Mon, 9 Feb 2026 09:25:05 +0100 Subject: [PATCH 3/3] use filter lib via an exposed interface (Thang's proposition) Signed-off-by: Thang PHAM --- ...aderImpl.java => DefaultFilterLoader.java} | 30 +++++++++---------- .../filter/server/FilterController.java | 4 +-- .../filter/server/FilterService.java | 29 +++++------------- .../filter/server/GlobalFilterService.java | 8 ----- .../filter/server/RepositoryService.java | 4 +-- .../filter/server/configs/FilterConfig.java | 15 ++++++++++ .../server/repositories/FilterRepository.java | 2 +- .../AbstractFilterRepositoryProxy.java | 4 +-- .../server/FilterEntityControllerTest.java | 8 +++-- .../filter/server/FilterServiceTest.java | 9 +++--- 10 files changed, 55 insertions(+), 58 deletions(-) rename src/main/java/org/gridsuite/filter/server/{FilterLoaderImpl.java => DefaultFilterLoader.java} (57%) create mode 100644 src/main/java/org/gridsuite/filter/server/configs/FilterConfig.java diff --git a/src/main/java/org/gridsuite/filter/server/FilterLoaderImpl.java b/src/main/java/org/gridsuite/filter/server/DefaultFilterLoader.java similarity index 57% rename from src/main/java/org/gridsuite/filter/server/FilterLoaderImpl.java rename to src/main/java/org/gridsuite/filter/server/DefaultFilterLoader.java index d7aa9ac4..2d81053f 100644 --- a/src/main/java/org/gridsuite/filter/server/FilterLoaderImpl.java +++ b/src/main/java/org/gridsuite/filter/server/DefaultFilterLoader.java @@ -10,37 +10,37 @@ import org.gridsuite.filter.FilterLoader; import org.gridsuite.filter.server.repositories.proxies.AbstractFilterRepositoryProxy; +import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.util.Objects; -import java.util.Optional; import java.util.UUID; /** * @author Franck Lecuyer */ -public class FilterLoaderImpl implements FilterLoader { +public class DefaultFilterLoader implements FilterLoader { private final Map> filterRepositories; - public FilterLoaderImpl(Map> filterRepositories) { + public DefaultFilterLoader(Map> filterRepositories) { this.filterRepositories = filterRepositories; } @Override - public Optional getFilter(UUID id) { - Objects.requireNonNull(id); + public List getFilters(List uuids) { + List uuidsLoading = new ArrayList<>(uuids); + List result = new ArrayList<>(); for (AbstractFilterRepositoryProxy repository : filterRepositories.values()) { - Optional res = repository.getFilter(id); - if (res.isPresent()) { - return res; + List partialResult = repository.getFilters(uuidsLoading); + result.addAll(partialResult); + + // prepare next iteration + List foundUuids = partialResult.stream().map(AbstractFilter::getId).toList(); + uuidsLoading.removeAll(foundUuids); + if (uuidsLoading.isEmpty()) { + break; } } - return Optional.empty(); - } - @Override - public List getFilters(List uuids) { - return uuids.stream() - .map(id -> getFilter(id).orElse(null)).toList(); + return result; } } diff --git a/src/main/java/org/gridsuite/filter/server/FilterController.java b/src/main/java/org/gridsuite/filter/server/FilterController.java index aa600f2e..22dd68ce 100644 --- a/src/main/java/org/gridsuite/filter/server/FilterController.java +++ b/src/main/java/org/gridsuite/filter/server/FilterController.java @@ -16,9 +16,9 @@ import org.gridsuite.filter.identifierlistfilter.FilterEquipments; import org.gridsuite.filter.identifierlistfilter.FilteredIdentifiables; import org.gridsuite.filter.identifierlistfilter.IdentifiableAttributes; -import org.gridsuite.filter.identifierlistfilter.FilterAttributes; +import org.gridsuite.filter.api.dto.FilterAttributes; import org.gridsuite.filter.server.dto.IdsByGroup; -import org.gridsuite.filter.utils.FiltersWithEquipmentTypes; +import org.gridsuite.filter.api.dto.FiltersWithEquipmentTypes; import org.springframework.context.annotation.ComponentScan; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; diff --git a/src/main/java/org/gridsuite/filter/server/FilterService.java b/src/main/java/org/gridsuite/filter/server/FilterService.java index b9c54b9c..0175e7af 100644 --- a/src/main/java/org/gridsuite/filter/server/FilterService.java +++ b/src/main/java/org/gridsuite/filter/server/FilterService.java @@ -15,11 +15,13 @@ import org.gridsuite.filter.AbstractFilter; import org.gridsuite.filter.FilterLoader; import org.gridsuite.filter.IFilterAttributes; +import org.gridsuite.filter.api.FilterEvaluator; +import org.gridsuite.filter.api.dto.FilterAttributes; +import org.gridsuite.filter.api.dto.FiltersWithEquipmentTypes; import org.gridsuite.filter.exception.FilterCycleException; import org.gridsuite.filter.identifierlistfilter.FilterEquipments; import org.gridsuite.filter.identifierlistfilter.FilteredIdentifiables; import org.gridsuite.filter.identifierlistfilter.IdentifiableAttributes; -import org.gridsuite.filter.identifierlistfilter.FilterAttributes; import org.gridsuite.filter.server.dto.IdsByGroup; import org.gridsuite.filter.server.error.FilterBusinessErrorCode; import org.gridsuite.filter.server.error.FilterException; @@ -27,7 +29,6 @@ import org.gridsuite.filter.server.service.DirectoryService; import org.gridsuite.filter.utils.FilterServiceUtils; import org.gridsuite.filter.utils.FilterType; -import org.gridsuite.filter.utils.FiltersWithEquipmentTypes; import org.gridsuite.filter.utils.expertfilter.FilterCycleDetector; import org.springframework.context.annotation.ComponentScan; import org.springframework.http.HttpStatus; @@ -55,6 +56,7 @@ public class FilterService { private final NetworkStoreService networkStoreService; private final NotificationService notificationService; private final DirectoryService directoryService; + private final FilterEvaluator filterEvaluator; public List getFilters() { return this.repositoriesService.getFiltersAttributes() @@ -164,22 +166,9 @@ private AbstractFilter doUpdateFilter(UUID id, AbstractFilter newFilter, String if (filterOpt.isPresent()) { newFilter.setId(id); - FilterLoader filterLoader = new FilterLoader() { - @Override - public List getFilters(List uuids) { - return uuids.stream() - .map(uuid -> uuid.equals(id) ? newFilter : repositoriesService.getFilter(uuid).orElse(null)) - .toList(); - } - - @Override - public Optional getFilter(UUID uuid) { - return uuid.equals(id) - ? Optional.of(newFilter) - : repositoriesService.getFilter(uuid); - } - }; - + FilterLoader filterLoader = uuids -> uuids.stream() + .map(uuid -> uuid.equals(id) ? newFilter : this.repositoriesService.getFilter(uuid).orElse(null)) + .toList(); try { FilterCycleDetector.checkNoCycle(newFilter, filterLoader); } catch (FilterCycleException exception) { @@ -259,9 +248,7 @@ public List evaluateFilter(AbstractFilter filter, UUID n @Transactional(readOnly = true) public FilteredIdentifiables evaluateFiltersWithEquipmentTypes(FiltersWithEquipmentTypes filtersWithEquipmentTypes, UUID networkUuid, String variantId) { Network network = getNetwork(networkUuid, variantId); - FilterLoader filterLoader = this.repositoriesService.getFilterLoader(); - - return FilterServiceUtils.evaluateFiltersWithEquipmentTypes(filtersWithEquipmentTypes, network, filterLoader); + return filterEvaluator.evaluateFilters(filtersWithEquipmentTypes, network); } @Transactional(readOnly = true) diff --git a/src/main/java/org/gridsuite/filter/server/GlobalFilterService.java b/src/main/java/org/gridsuite/filter/server/GlobalFilterService.java index 2c90263d..3a926897 100644 --- a/src/main/java/org/gridsuite/filter/server/GlobalFilterService.java +++ b/src/main/java/org/gridsuite/filter/server/GlobalFilterService.java @@ -16,7 +16,6 @@ import org.springframework.web.server.ResponseStatusException; import java.util.List; -import java.util.Optional; import java.util.UUID; @Service @@ -44,13 +43,6 @@ public List getFilters(@NonNull final List filtersUuids) { return this.repositoriesService.getFilters(filtersUuids); } - /** {@inheritDoc} */ - @Override - @Transactional(readOnly = true) - public Optional getFilter(UUID uuid) { - return this.repositoriesService.getFilter(uuid); - } - /* Expose it publicly */ /** {@inheritDoc} */ @Override diff --git a/src/main/java/org/gridsuite/filter/server/RepositoryService.java b/src/main/java/org/gridsuite/filter/server/RepositoryService.java index fa784f5c..629c700d 100644 --- a/src/main/java/org/gridsuite/filter/server/RepositoryService.java +++ b/src/main/java/org/gridsuite/filter/server/RepositoryService.java @@ -5,7 +5,7 @@ import org.apache.commons.collections4.ListUtils; import org.gridsuite.filter.AbstractFilter; import org.gridsuite.filter.FilterLoader; -import org.gridsuite.filter.identifierlistfilter.FilterAttributes; +import org.gridsuite.filter.api.dto.FilterAttributes; import org.gridsuite.filter.server.repositories.expertfilter.ExpertFilterRepository; import org.gridsuite.filter.server.repositories.identifierlistfilter.IdentifierListFilterRepository; import org.gridsuite.filter.server.repositories.proxies.AbstractFilterRepositoryProxy; @@ -35,7 +35,7 @@ public RepositoryService(final IdentifierListFilterRepository identifierListFilt final ExpertFilterRepository expertFilterRepository) { this.identifierListFilterProxy = new IdentifierListFilterRepositoryProxy(identifierListFilterRepository); this.expertFilterProxy = new ExpertFilterRepositoryProxy(expertFilterRepository); - this.filterLoader = new FilterLoaderImpl(Map.of( + this.filterLoader = new DefaultFilterLoader(Map.of( FilterType.IDENTIFIER_LIST.name(), this.identifierListFilterProxy, FilterType.EXPERT.name(), this.expertFilterProxy )); diff --git a/src/main/java/org/gridsuite/filter/server/configs/FilterConfig.java b/src/main/java/org/gridsuite/filter/server/configs/FilterConfig.java new file mode 100644 index 00000000..f77eed7a --- /dev/null +++ b/src/main/java/org/gridsuite/filter/server/configs/FilterConfig.java @@ -0,0 +1,15 @@ +package org.gridsuite.filter.server.configs; + +import org.gridsuite.filter.api.FilterEvaluator; +import org.gridsuite.filter.api.FilterEvaluatorFactory; +import org.gridsuite.filter.server.RepositoryService; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class FilterConfig { + @Bean + public FilterEvaluator filterEvaluator(RepositoryService repositoriesService) { + return FilterEvaluatorFactory.create(repositoriesService.getFilterLoader()); + } +} diff --git a/src/main/java/org/gridsuite/filter/server/repositories/FilterRepository.java b/src/main/java/org/gridsuite/filter/server/repositories/FilterRepository.java index 3507323b..4e93c914 100644 --- a/src/main/java/org/gridsuite/filter/server/repositories/FilterRepository.java +++ b/src/main/java/org/gridsuite/filter/server/repositories/FilterRepository.java @@ -7,7 +7,7 @@ package org.gridsuite.filter.server.repositories; -import org.gridsuite.filter.identifierlistfilter.FilterMetadata; +import org.gridsuite.filter.api.dto.FilterMetadata; import org.gridsuite.filter.server.entities.AbstractFilterEntity; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; diff --git a/src/main/java/org/gridsuite/filter/server/repositories/proxies/AbstractFilterRepositoryProxy.java b/src/main/java/org/gridsuite/filter/server/repositories/proxies/AbstractFilterRepositoryProxy.java index fdb046c0..9d98d5f7 100644 --- a/src/main/java/org/gridsuite/filter/server/repositories/proxies/AbstractFilterRepositoryProxy.java +++ b/src/main/java/org/gridsuite/filter/server/repositories/proxies/AbstractFilterRepositoryProxy.java @@ -8,9 +8,9 @@ package org.gridsuite.filter.server.repositories.proxies; import org.gridsuite.filter.AbstractFilter; -import org.gridsuite.filter.identifierlistfilter.FilterAttributes; +import org.gridsuite.filter.api.dto.FilterAttributes; import org.gridsuite.filter.server.entities.AbstractFilterEntity; -import org.gridsuite.filter.identifierlistfilter.FilterMetadata; +import org.gridsuite.filter.api.dto.FilterMetadata; import org.gridsuite.filter.server.repositories.FilterRepository; import org.gridsuite.filter.utils.EquipmentType; import org.gridsuite.filter.utils.FilterType; diff --git a/src/test/java/org/gridsuite/filter/server/FilterEntityControllerTest.java b/src/test/java/org/gridsuite/filter/server/FilterEntityControllerTest.java index e2ebf94a..31421045 100644 --- a/src/test/java/org/gridsuite/filter/server/FilterEntityControllerTest.java +++ b/src/test/java/org/gridsuite/filter/server/FilterEntityControllerTest.java @@ -25,17 +25,19 @@ import com.powsybl.network.store.iidm.impl.NetworkFactoryImpl; import org.gridsuite.filter.AbstractFilter; import org.gridsuite.filter.IFilterAttributes; +import org.gridsuite.filter.api.dto.EquipmentTypesByFilterId; +import org.gridsuite.filter.api.dto.FilterAttributes; +import org.gridsuite.filter.api.dto.FiltersWithEquipmentTypes; import org.gridsuite.filter.expertfilter.ExpertFilter; import org.gridsuite.filter.expertfilter.expertrule.*; import org.gridsuite.filter.identifierlistfilter.*; -import org.gridsuite.filter.server.dto.*; +import org.gridsuite.filter.server.dto.ElementAttributes; +import org.gridsuite.filter.server.dto.IdsByGroup; import org.gridsuite.filter.server.service.DirectoryService; import org.gridsuite.filter.server.utils.MatcherJson; import org.gridsuite.filter.server.utils.assertions.Assertions; import org.gridsuite.filter.utils.EquipmentType; -import org.gridsuite.filter.utils.EquipmentTypesByFilterId; import org.gridsuite.filter.utils.FilterType; -import org.gridsuite.filter.utils.FiltersWithEquipmentTypes; import org.gridsuite.filter.utils.expertfilter.CombinatorType; import org.gridsuite.filter.utils.expertfilter.FieldType; import org.gridsuite.filter.utils.expertfilter.OperatorType; diff --git a/src/test/java/org/gridsuite/filter/server/FilterServiceTest.java b/src/test/java/org/gridsuite/filter/server/FilterServiceTest.java index 9d70006f..77e34c5c 100644 --- a/src/test/java/org/gridsuite/filter/server/FilterServiceTest.java +++ b/src/test/java/org/gridsuite/filter/server/FilterServiceTest.java @@ -7,6 +7,7 @@ package org.gridsuite.filter.server; import com.powsybl.network.store.client.NetworkStoreService; +import org.gridsuite.filter.api.FilterEvaluator; import org.gridsuite.filter.exception.FilterCycleException; import org.gridsuite.filter.server.error.FilterException; import org.gridsuite.filter.server.service.DirectoryService; @@ -26,9 +27,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.ArgumentMatchers.anyList; import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; +import static org.mockito.Mockito.*; /** * @author Mohamed Ben-rejeb {@literal } @@ -44,13 +43,15 @@ class FilterServiceTest { private NotificationService notificationService; @Mock private DirectoryService directoryService; + @Mock + private FilterEvaluator filterEvaluator; @Autowired private FilterService filterService; @BeforeEach void setUp() { - filterService = new FilterService(repositoryService, networkStoreService, notificationService, directoryService); + filterService = new FilterService(repositoryService, networkStoreService, notificationService, directoryService, filterEvaluator); } @Test