diff --git a/pom.xml b/pom.xml index 158700d..e33e03f 100644 --- a/pom.xml +++ b/pom.xml @@ -56,6 +56,13 @@ org.gridsuite.voltageinit.server gridsuite org.gridsuite:voltage-init-server + + + 1.12.0 + 1.6.0-SNAPSHOT @@ -177,10 +184,12 @@ org.gridsuite gridsuite-filter + ${gridsuite-filter.version} org.gridsuite gridsuite-computation + ${gridsuite-computation.version} com.powsybl diff --git a/src/main/java/org/gridsuite/voltageinit/server/service/parameters/FilterService.java b/src/main/java/org/gridsuite/voltageinit/server/service/parameters/FilterService.java index 262cbbd..01b0ae5 100644 --- a/src/main/java/org/gridsuite/voltageinit/server/service/parameters/FilterService.java +++ b/src/main/java/org/gridsuite/voltageinit/server/service/parameters/FilterService.java @@ -7,69 +7,47 @@ package org.gridsuite.voltageinit.server.service.parameters; import com.powsybl.commons.PowsyblException; -import com.powsybl.iidm.network.Country; -import com.powsybl.iidm.network.Network; import com.powsybl.network.store.client.NetworkStoreService; -import com.powsybl.network.store.client.PreloadingStrategy; -import org.gridsuite.computation.dto.GlobalFilter; import lombok.NonNull; -import org.apache.commons.collections4.CollectionUtils; +import org.gridsuite.computation.dto.GlobalFilter; +import org.gridsuite.computation.dto.ResourceFilterDTO; +import org.gridsuite.computation.service.AbstractFilterService; import org.gridsuite.filter.AbstractFilter; -import org.gridsuite.filter.FilterLoader; -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.EnumExpertRule; -import org.gridsuite.filter.expertfilter.expertrule.FilterUuidExpertRule; -import org.gridsuite.filter.expertfilter.expertrule.NumberExpertRule; -import org.gridsuite.filter.expertfilter.expertrule.PropertiesExpertRule; -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.gridsuite.voltageinit.server.dto.parameters.FilterEquipments; import org.gridsuite.voltageinit.server.error.VoltageInitException; import org.springframework.beans.factory.annotation.Value; import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.HttpMethod; -import org.springframework.http.HttpStatus; import org.springframework.stereotype.Service; -import org.springframework.web.client.HttpStatusCodeException; -import org.springframework.web.client.RestTemplate; -import org.springframework.web.server.ResponseStatusException; import org.springframework.web.util.UriComponentsBuilder; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.UUID; import java.util.stream.Collectors; /** * @author Ayoub LABIDI */ @Service -public class FilterService implements FilterLoader { +public class FilterService extends AbstractFilterService { private static final String FILTER_SERVER_API_VERSION = "v1"; private static final String DELIMITER = "/"; - private static String filterServerBaseUri; - - private final RestTemplate restTemplate = new RestTemplate(); - - private final NetworkStoreService networkStoreService; - public static final String FILTERS_NOT_FOUND = "Filters not found"; public FilterService(NetworkStoreService networkStoreService, @Value("${gridsuite.services.filter-server.base-uri:http://filter-server/}") String filterServerBaseUri) { - this.networkStoreService = networkStoreService; - setFilterServerBaseUri(filterServerBaseUri); - } - - public static void setFilterServerBaseUri(String filterServerBaseUri) { - FilterService.filterServerBaseUri = filterServerBaseUri; + super(networkStoreService, filterServerBaseUri); } public List exportFilters(List filtersUuids, UUID networkUuid, String variantId) { @@ -82,31 +60,6 @@ public List exportFilters(List filtersUuids, UUID networ .getBody(); } - private Network getNetwork(UUID networkUuid, String variantId) { - try { - Network network = networkStoreService.getNetwork(networkUuid, PreloadingStrategy.COLLECTION); - network.getVariantManager().setWorkingVariant(variantId); - return network; - } catch (PowsyblException e) { - throw new ResponseStatusException(HttpStatus.NOT_FOUND, e.getMessage()); - } - } - - public List getFilters(List filtersUuids) { - if (CollectionUtils.isEmpty(filtersUuids)) { - return List.of(); - } - var ids = "?ids=" + filtersUuids.stream().map(UUID::toString).collect(Collectors.joining(",")); - String path = UriComponentsBuilder.fromPath(DELIMITER + FILTER_SERVER_API_VERSION + "/filters/metadata" + ids) - .buildAndExpand() - .toUriString(); - try { - return restTemplate.exchange(filterServerBaseUri + path, HttpMethod.GET, null, new ParameterizedTypeReference>() { }).getBody(); - } catch (HttpStatusCodeException e) { - throw new PowsyblException(FILTERS_NOT_FOUND + " [" + filtersUuids + "]"); - } - } - public Set getFiltersExistence(Collection filtersUuids) { List filterIds = filtersUuids.stream() .distinct() @@ -121,7 +74,6 @@ public Set getFiltersExistence(Collection filtersUuids) { .map(AbstractFilter::getId) .filter(Objects::nonNull) .collect(Collectors.toCollection(LinkedHashSet::new)); - } public void ensureFiltersExist(Map filterNamesByUuid) { @@ -145,153 +97,14 @@ private String buildMissingFiltersMessage(Collection filtersUuids, Map 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; - } - - private 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; - } - - private List createNominalVoltageRules(List nominalVoltageList, List nominalFieldTypes) { - List nominalVoltageRules = new ArrayList<>(); - for (FieldType fieldType : nominalFieldTypes) { - nominalVoltageRules.addAll(createNumberExpertRules(nominalVoltageList, fieldType)); - } - return nominalVoltageRules; - } - - private List createCountryCodeRules(List countryCodeList, List countryCodeFieldTypes) { - List countryCodeRules = new ArrayList<>(); - for (FieldType fieldType : countryCodeFieldTypes) { - countryCodeRules.addAll(createEnumExpertRules(countryCodeList, fieldType)); - } - return countryCodeRules; - } - - private AbstractExpertRule createPropertiesRule(String property, List propertiesValues, FieldType fieldType) { - return PropertiesExpertRule.builder() - .combinator(CombinatorType.OR) - .operator(OperatorType.IN) - .field(fieldType) - .propertyName(property) - .propertyValues(propertiesValues) - .build(); - } - - private List createPropertiesRules(String property, List propertiesValues, List propertiesFieldTypes) { - List propertiesRules = new ArrayList<>(); - for (FieldType fieldType : propertiesFieldTypes) { - propertiesRules.add(createPropertiesRule(property, propertiesValues, fieldType)); - } - return propertiesRules; - } - - private AbstractExpertRule createCombination(CombinatorType combinatorType, List rules) { - return CombinatorExpertRule.builder().combinator(combinatorType).rules(rules).build(); - } - - private Optional createOrCombination(List rules) { - if (rules.isEmpty()) { - return Optional.empty(); - } - return Optional.of(rules.size() > 1 ? createCombination(CombinatorType.OR, rules) : rules.getFirst()); - } - - private ExpertFilter buildExpertFilter(GlobalFilter globalFilter) { - List andRules = new ArrayList<>(); - - // among themselves the various global filter rules are OR combinated - List nominalVRules = createNominalVoltageRules(globalFilter.getNominalV(), List.of(FieldType.NOMINAL_VOLTAGE)); - createOrCombination(nominalVRules).ifPresent(andRules::add); - - List countryCodeRules = createCountryCodeRules(globalFilter.getCountryCode(), List.of(FieldType.COUNTRY)); - createOrCombination(countryCodeRules).ifPresent(andRules::add); - - if (globalFilter.getSubstationProperty() != null) { - List propertiesRules = new ArrayList<>(); - globalFilter.getSubstationProperty().forEach((propertyName, propertiesValues) -> - propertiesRules.addAll(createPropertiesRules( - propertyName, - propertiesValues, - List.of(FieldType.SUBSTATION_PROPERTIES) - ))); - createOrCombination(propertiesRules).ifPresent(andRules::add); - } - - // between them the various global filter rules are AND combinated - AbstractExpertRule andCombination = createCombination(CombinatorType.AND, andRules); - - return new ExpertFilter(UUID.randomUUID(), new Date(), EquipmentType.VOLTAGE_LEVEL, andCombination); - } - - private static List filterNetwork(AbstractFilter filter, Network network, FilterLoader filterLoader) { - return FilterServiceUtils.getIdentifiableAttributes(filter, network, filterLoader) - .stream() - .map(IdentifiableAttributes::getId) - .toList(); - } - - private AbstractExpertRule createVoltageLevelIdRule(UUID filterUuid) { - return FilterUuidExpertRule.builder() - .operator(OperatorType.IS_PART_OF) - .field(FieldType.ID) - .values(Set.of(filterUuid.toString())) - .build(); - } - + @SuppressWarnings("unchecked") public List getResourceFilters(@NonNull UUID networkUuid, @NonNull String variantId, @NonNull GlobalFilter globalFilter) { - Network network = getNetwork(networkUuid, variantId); - - List> idsFilteredThroughEachFilter = new ArrayList<>(); - ExpertFilter expertFilter = buildExpertFilter(globalFilter); - idsFilteredThroughEachFilter.add(new ArrayList<>(filterNetwork(expertFilter, network, this))); - - final List genericFilters = getFilters(globalFilter.getGenericFilter()); - for (AbstractFilter filter : genericFilters) { - AbstractExpertRule voltageLevelIdRule = createVoltageLevelIdRule(filter.getId()); - ExpertFilter expertFilterWithIdsCriteria = new ExpertFilter(UUID.randomUUID(), new Date(), EquipmentType.VOLTAGE_LEVEL, voltageLevelIdRule); - idsFilteredThroughEachFilter.add(new ArrayList<>(filterNetwork(expertFilterWithIdsCriteria, network, this))); - } - - // combine the results - // attention : generic filters all use AND operand between them while other filters use OR between them - EnumMap> subjectIdsByEquipmentType = new EnumMap<>(EquipmentType.class); - for (List idsFiltered : idsFilteredThroughEachFilter) { - // if there was already a filtered list for this equipment type : AND filtering : - subjectIdsByEquipmentType.computeIfPresent(EquipmentType.VOLTAGE_LEVEL, (key, value) -> value.stream() - .filter(idsFiltered::contains).toList()); - // otherwise, initialisation : - subjectIdsByEquipmentType.computeIfAbsent(EquipmentType.VOLTAGE_LEVEL, key -> new ArrayList<>(idsFiltered)); + Optional res = super.getResourceFilter(networkUuid, variantId, globalFilter, List.of(EquipmentType.VOLTAGE_LEVEL), null); + if (res.isEmpty() || !(res.get().value() instanceof List list)) { + return List.of(); + } else { + return (List) list; } - - // combine all the results into one list - List idsFromEvalFilter = new ArrayList<>(); - subjectIdsByEquipmentType.values().forEach(idsList -> - Optional.ofNullable(idsList).ifPresent(idsFromEvalFilter::addAll) - ); - - return idsFromEvalFilter; } } diff --git a/src/test/java/org/gridsuite/voltageinit/server/VoltageInitControllerTest.java b/src/test/java/org/gridsuite/voltageinit/server/VoltageInitControllerTest.java index a9fc006..6de84dd 100644 --- a/src/test/java/org/gridsuite/voltageinit/server/VoltageInitControllerTest.java +++ b/src/test/java/org/gridsuite/voltageinit/server/VoltageInitControllerTest.java @@ -78,6 +78,7 @@ import org.springframework.test.context.ContextHierarchy; import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; +import org.springframework.test.util.ReflectionTestUtils; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MvcResult; import org.springframework.transaction.support.TransactionSynchronizationManager; @@ -253,7 +254,11 @@ private String createStringGlobalFilter( Map> substationProperty, List countryCodes, List genericFiltersUuid) throws JsonProcessingException { - GlobalFilter globalFilter = new GlobalFilter(nominalVs, countryCodes, genericFiltersUuid, null, substationProperty); + GlobalFilter globalFilter = new GlobalFilter(); + globalFilter.setNominalV(nominalVs); + globalFilter.setCountryCode(countryCodes); + globalFilter.setSubstationProperty(substationProperty); + globalFilter.setGenericFilter(genericFiltersUuid); return new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL).writeValueAsString(globalFilter); } @@ -264,7 +269,7 @@ void setUp(final MockWebServer server) throws JsonProcessingException { HttpUrl baseHttpUrl = server.url(""); String baseUrl = baseHttpUrl.toString().substring(0, baseHttpUrl.toString().length() - 1); networkModificationService.setNetworkModificationServerBaseUri(baseUrl); - filterService.setFilterServerBaseUri(baseUrl); + ReflectionTestUtils.setField(filterService, "filterServerBaseUri", baseUrl); doNothing().when(filterService).ensureFiltersExist(anyMap()); // network store service mocking