Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,13 @@

<dependencyManagement>
<dependencies>
<!-- TODO remove when gridsuite-dependencies is released with this version -->
<dependency>
<groupId>com.powsybl</groupId>
<artifactId>powsybl-ws-commons</artifactId>
<version>1.30.0</version>
</dependency>

<!-- imports -->
<dependency>
<groupId>org.gridsuite</groupId>
Expand Down
29 changes: 18 additions & 11 deletions src/main/java/org/gridsuite/filter/server/FilterService.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,16 @@
import org.gridsuite.filter.FilterLoader;
import org.gridsuite.filter.IFilterAttributes;
import org.gridsuite.filter.expertfilter.ExpertFilter;
import org.gridsuite.filter.exceptions.FilterCycleException;
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.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;
Expand Down Expand Up @@ -61,7 +64,7 @@ public class FilterService {

public List<IFilterAttributes> getFilters() {
return this.repositoriesService.getFiltersAttributes()
.map(IFilterAttributes.class::cast) // cast because generics are invariants
.map(IFilterAttributes.class::cast) // cast because generics are invariants
.toList();
}

Expand Down Expand Up @@ -109,7 +112,7 @@ public List<AbstractFilter> createFilters(List<AbstractFilter> filters) {
}

Map<AbstractFilterRepositoryProxy<?, ?>, List<AbstractFilter>> repositoryFiltersMap = filters.stream()
.collect(Collectors.groupingBy(this.repositoriesService::getRepositoryFromType));
.collect(Collectors.groupingBy(this.repositoriesService::getRepositoryFromType));

List<AbstractFilter> createdFilters = new ArrayList<>();
repositoryFiltersMap.forEach((repository, subFilters) -> createdFilters.addAll(repository.insertAll(subFilters)));
Expand Down Expand Up @@ -150,7 +153,7 @@ public Map<UUID, UUID> duplicateFilters(List<UUID> filterUuids) {
});

Map<AbstractFilterRepositoryProxy<?, ?>, List<AbstractFilter>> repositoryFiltersMap = sourceFilters.stream()
.collect(Collectors.groupingBy(this.repositoriesService::getRepositoryFromType));
.collect(Collectors.groupingBy(this.repositoriesService::getRepositoryFromType));

repositoryFiltersMap.forEach(AbstractFilterRepositoryProxy::insertAll);

Expand All @@ -170,7 +173,11 @@ private AbstractFilter doUpdateFilter(UUID id, AbstractFilter newFilter, String
FilterLoader filterLoader = uuids -> uuids.stream()
.map(uuid -> uuid.equals(id) ? newFilter : this.repositoriesService.getFilter(uuid).orElse(null))
.toList();
FilterCycleDetector.checkNoCycle(newFilter, filterLoader);
try {
FilterCycleDetector.checkNoCycle(newFilter, filterLoader);
} catch (FilterCycleException exception) {
throw new FilterException(FilterBusinessErrorCode.FILTER_CYCLE_DETECTED, exception.getMessage());
}

AbstractFilter modifiedOrCreatedFilter;
if (filterOpt.get().getType() == newFilter.getType()) { // filter type has not changed
Expand Down Expand Up @@ -301,13 +308,13 @@ public Map<String, Long> getIdentifiablesCountByGroup(IdsByGroup idsByGroup, UUI
Objects.requireNonNull(idsByGroup);
final FilterLoader filterLoader = this.repositoriesService.getFilterLoader();
return idsByGroup.getIds().entrySet().stream()
.collect(Collectors.toMap(
Map.Entry::getKey,
entry -> this.repositoriesService.getFilters(entry.getValue()).stream()
.mapToLong(f -> getIdentifiableAttributes(f, networkUuid, variantId, filterLoader).size())
.sum()
)
);
.collect(Collectors.toMap(
Map.Entry::getKey,
entry -> this.repositoriesService.getFilters(entry.getValue()).stream()
.mapToLong(f -> getIdentifiableAttributes(f, networkUuid, variantId, filterLoader).size())
.sum()
)
);
}

@Transactional(readOnly = true)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/**
* 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;

import com.powsybl.ws.commons.error.ServerNameProvider;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
* @author Mohamed Ben-rejeb {@literal <mohamed.ben-rejeb at rte-france.com>}
*/
@Component
public class PropertyServerNameProvider implements ServerNameProvider {

private final String name;

public PropertyServerNameProvider(@Value("${spring.application.name:filter-server}") String name) {
this.name = name;
}

@Override
public String serverName() {
return name;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
* 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.error;

import com.powsybl.ws.commons.error.BusinessErrorCode;

/**
* @author Mohamed Ben-rejeb {@literal <mohamed.ben-rejeb at rte-france.com>}
*
* Business error codes emitted by the filter service.
*/
public enum FilterBusinessErrorCode implements BusinessErrorCode {
FILTER_CYCLE_DETECTED("filter.filterCycleDetected");
private final String code;

FilterBusinessErrorCode(String code) {
this.code = code;
}

public String value() {
return code;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/**
* 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.error;

import com.powsybl.ws.commons.error.AbstractBusinessException;
import org.jetbrains.annotations.NotNull;

import java.util.Objects;

/**
* /**
* @author Mohamed Ben-rejeb {@literal <mohamed.ben-rejeb at rte-france.com>}
*
* Filter server specific runtime exception enriched with a business error code.
*/
public class FilterException extends AbstractBusinessException {

private final FilterBusinessErrorCode errorCode;

public FilterException(FilterBusinessErrorCode errorCode, String message) {
super(Objects.requireNonNull(message, "message must not be null"));
this.errorCode = Objects.requireNonNull(errorCode, "errorCode must not be null");
}

@NotNull
@Override
public FilterBusinessErrorCode getBusinessErrorCode() {
return errorCode;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/**
* 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.error;

import com.powsybl.ws.commons.error.AbstractBaseRestExceptionHandler;
import com.powsybl.ws.commons.error.ServerNameProvider;
import org.jetbrains.annotations.NotNull;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;

/**
* @author Mohamed Ben-rejeb {@literal <mohamed.ben-rejeb at rte-france.com>}
*/
@ControllerAdvice
public class RestResponseEntityExceptionHandler
extends AbstractBaseRestExceptionHandler<FilterException, FilterBusinessErrorCode> {

public RestResponseEntityExceptionHandler(ServerNameProvider serverNameProvider) {
super(serverNameProvider);
}

@NotNull
@Override
protected FilterBusinessErrorCode getBusinessCode(FilterException ex) {
return ex.getBusinessErrorCode();
}

@Override
protected HttpStatus mapStatus(FilterBusinessErrorCode code) {
return switch (code) {
case FILTER_CYCLE_DETECTED -> HttpStatus.BAD_REQUEST;
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* 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;

import org.gridsuite.filter.server.error.FilterBusinessErrorCode;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;

import static org.assertj.core.api.Assertions.assertThat;

/**
* @author Mohamed Ben-rejeb {@literal <mohamed.ben-rejeb at rte-france.com>}
*/
class FilterBusinessErrorCodeTest {

@ParameterizedTest
@EnumSource(FilterBusinessErrorCode.class)
void valueStartsWithFilter(FilterBusinessErrorCode code) {
assertThat(code.value()).startsWith("filter.");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -870,7 +870,7 @@ private void updateFiltersWithNoneExistingId(Map<UUID, AbstractFilter> filtersTo
mvc.perform(put(URL_TEMPLATE + "/batch")
.content(objectMapper.writeValueAsString(filtersToUpdateMap))
.contentType(APPLICATION_JSON))
.andExpect(status().isNotFound());
.andExpect(status().isInternalServerError());
}

private void deleteFilter(UUID filterId) throws Exception {
Expand Down
25 changes: 25 additions & 0 deletions src/test/java/org/gridsuite/filter/server/FilterExceptionTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* 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;

import org.gridsuite.filter.server.error.FilterBusinessErrorCode;
import org.gridsuite.filter.server.error.FilterException;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;

/**
* @author Mohamed Ben-rejeb {@literal <mohamed.ben-rejeb at rte-france.com>}
*/
class FilterExceptionTest {

@Test
void defaultConstructorStoresMessage() {
FilterException exception = new FilterException(FilterBusinessErrorCode.FILTER_CYCLE_DETECTED, "cycle");
assertThat(exception.getMessage()).isEqualTo("cycle");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* 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;

import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;

/**
* @author Mohamed Ben-rejeb {@literal <mohamed.ben-rejeb at rte-france.com>}
*/
class PropertyServerNameProviderTest {

@Test
void returnsConfiguredName() {
PropertyServerNameProvider provider = new PropertyServerNameProvider("filter-overridden");
assertThat(provider.serverName()).isEqualTo("filter-overridden");
}
}
Loading