-
Notifications
You must be signed in to change notification settings - Fork 0
Add Filter Based Contingency List #136
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 22 commits
9f3fe7d
6dacdd9
383a3ef
0f6aeba
d7a3915
e775fd4
081cadb
4ef14c4
faea470
ac2a7ee
47f22ed
11df483
7690d93
981ee07
b519ccd
0cd4045
2d1d51b
c82ce8f
dd05b3d
21f1bec
01775ac
e9018fa
d62481d
12faf76
ea66686
89200de
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -149,6 +149,53 @@ public ResponseEntity<Void> modifyIdentifierContingencyList( | |||||
} | ||||||
} | ||||||
|
||||||
@PostMapping(value = "/filters-contingency-lists", consumes = MediaType.APPLICATION_JSON_VALUE) | ||||||
@Operation(summary = "Create an filter base contingency list") | ||||||
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "The filter based contingency list has been created successfully")}) | ||||||
public ResponseEntity<PersistentContingencyList> createFilterBasedContingencyList(@RequestParam(required = false, value = "id") UUID id, | ||||||
@RequestBody FilterBasedContingencyList filterBasedContingencyList) { | ||||||
return ResponseEntity.ok() | ||||||
.contentType(MediaType.APPLICATION_JSON) | ||||||
.body(service.createFilterBasedContingencyList(id, filterBasedContingencyList)); | ||||||
} | ||||||
|
||||||
@PutMapping(value = "/filters-contingency-lists/{id}", consumes = MediaType.APPLICATION_JSON_VALUE) | ||||||
@Operation(summary = "Modify a filter based contingency list") | ||||||
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "The filter based contingency list have been modified successfully")}) | ||||||
public ResponseEntity<Void> modifyFilterBasedContingencyList( | ||||||
@PathVariable UUID id, | ||||||
@RequestBody FilterBasedContingencyList contingencyList, | ||||||
@RequestHeader("userId") String userId) { | ||||||
try { | ||||||
service.modifyFilterBasedContingencyList(id, contingencyList, userId); | ||||||
return ResponseEntity.ok().build(); | ||||||
} catch (EntityNotFoundException ignored) { | ||||||
return ResponseEntity.notFound().build(); | ||||||
} | ||||||
} | ||||||
|
||||||
@PostMapping(value = "/filters-contingency-lists", params = "duplicateFrom") | ||||||
@Operation(summary = "Create a filter based contingency list from another existing one") | ||||||
|
||||||
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "The filter based contingency list have been duplicated successfully"), | ||||||
@ApiResponse(responseCode = "404", description = "Source form contingency list not found")}) | ||||||
|
@ApiResponse(responseCode = "404", description = "Source form contingency list not found")}) | |
@ApiResponse(responseCode = "404", description = "Source from contingency list not found")}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess it's a mistake
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes i should replace by filter based contingency list
basseche marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
/** | ||
* 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.actions.server.dto; | ||
|
||
import com.powsybl.contingency.contingency.list.ContingencyList; | ||
import com.powsybl.iidm.network.Network; | ||
import io.swagger.v3.oas.annotations.media.Schema; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
import org.gridsuite.actions.server.utils.ContingencyListType; | ||
|
||
import java.time.Instant; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.Set; | ||
import java.util.UUID; | ||
|
||
@Getter | ||
@NoArgsConstructor | ||
@Schema(description = "filter based contingency list") | ||
public class FilterBasedContingencyList extends AbstractContingencyList { | ||
|
||
@Schema(description = "filters list") | ||
private List<FilterMetaData> filters; | ||
|
||
public FilterBasedContingencyList(UUID uuid, Instant date, List<FilterMetaData> filterList) { | ||
super(new ContingencyListMetadataImpl(uuid, ContingencyListType.FILTERS, date)); | ||
this.filters = filterList; | ||
} | ||
|
||
@Override | ||
public ContingencyList toPowsyblContingencyList(Network network) { | ||
return null; | ||
} | ||
|
||
@Override | ||
public Map<String, Set<String>> getNotFoundElements(Network network) { | ||
return Map.of(); | ||
} | ||
} |
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.actions.server.dto; | ||
|
||
import io.swagger.v3.oas.annotations.media.Schema; | ||
import lombok.AllArgsConstructor; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
|
||
import java.util.UUID; | ||
|
||
@Getter | ||
@NoArgsConstructor | ||
@AllArgsConstructor | ||
@Schema(description = "Metadata on filters composing filter based contingency list") | ||
public class FilterMetaData { | ||
|
||
@Schema(description = "filter uuid in filter data base") | ||
private UUID id; | ||
|
||
@Schema(description = "filter name") | ||
private String name; | ||
|
||
@Schema(description = "equipment type") | ||
private String equipmentType; | ||
|
||
} |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,54 @@ | ||||||
/** | ||||||
* 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.actions.server.entities; | ||||||
|
||||||
import jakarta.persistence.CascadeType; | ||||||
import jakarta.persistence.Entity; | ||||||
import jakarta.persistence.OneToMany; | ||||||
import jakarta.persistence.Table; | ||||||
import lombok.Getter; | ||||||
import lombok.NoArgsConstructor; | ||||||
import lombok.Setter; | ||||||
import org.gridsuite.actions.server.dto.FilterBasedContingencyList; | ||||||
import org.springframework.util.CollectionUtils; | ||||||
|
||||||
import java.util.ArrayList; | ||||||
import java.util.List; | ||||||
import java.util.UUID; | ||||||
|
||||||
@NoArgsConstructor | ||||||
@Getter | ||||||
@Setter | ||||||
@Entity | ||||||
@Table(name = "filter_based_contingency_list") | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No contingency list is on element in this table. We should stay coherent with the other contingency list names. |
||||||
public class FilterBasedContingencyListEntity extends AbstractContingencyEntity { | ||||||
|
||||||
@OneToMany(cascade = CascadeType.ALL) | ||||||
basseche marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||
private List<FilterMetaDataEntity> filtersListEntities; | ||||||
|
||||||
|
||||||
public FilterBasedContingencyListEntity(FilterBasedContingencyList contingencyList) { | ||||||
super(); | ||||||
if (CollectionUtils.isEmpty(contingencyList.getFilters())) { | ||||||
return; | ||||||
} | ||||||
|
||||||
init(contingencyList); | ||||||
} | ||||||
|
||||||
private void init(FilterBasedContingencyList contingencyList) { | ||||||
filtersListEntities = new ArrayList<>(); | ||||||
contingencyList.getFilters().forEach(f -> | ||||||
filtersListEntities.add( | ||||||
new FilterMetaDataEntity(UUID.randomUUID(), f.getId(), f.getName(), f.getEquipmentType())) | ||||||
); | ||||||
} | ||||||
|
||||||
public FilterBasedContingencyListEntity update(FilterBasedContingencyList contingencyList) { | ||||||
init(contingencyList); | ||||||
return this; | ||||||
} | ||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
/** | ||
* 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.actions.server.entities; | ||
|
||
import jakarta.persistence.Column; | ||
import jakarta.persistence.Entity; | ||
import jakarta.persistence.GeneratedValue; | ||
import jakarta.persistence.GenerationType; | ||
import jakarta.persistence.Id; | ||
import jakarta.persistence.Table; | ||
import lombok.AllArgsConstructor; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
import lombok.Setter; | ||
|
||
import java.util.UUID; | ||
|
||
@NoArgsConstructor | ||
@AllArgsConstructor | ||
@Getter | ||
@Setter | ||
@Entity | ||
@Table(name = "filter_metadata") | ||
public class FilterMetaDataEntity { | ||
@Id | ||
@Column(name = "id") | ||
@GeneratedValue(strategy = GenerationType.AUTO) | ||
private UUID id; | ||
|
||
@Column(name = "filter_id") | ||
private UUID filterId; | ||
|
||
@Column(name = "name") | ||
private String name; | ||
|
||
@Column(name = "equipment_type") | ||
private String equipmentType; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
/** | ||
* 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.actions.server.repositories; | ||
|
||
import org.gridsuite.actions.server.entities.FilterBasedContingencyListEntity; | ||
import org.springframework.data.jpa.repository.JpaRepository; | ||
import org.springframework.stereotype.Repository; | ||
|
||
import java.util.UUID; | ||
|
||
@Repository | ||
public interface FilterBasedContingencyListRepository extends JpaRepository<FilterBasedContingencyListEntity, UUID> { | ||
Integer deleteFilterBasedContingencyListEntityById(UUID id); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
/* | ||
* Copyright (c) 2023, 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.actions.server.service; | ||
import lombok.Getter; | ||
import org.gridsuite.filter.identifierlistfilter.FilteredIdentifiables; | ||
import org.gridsuite.filter.identifierlistfilter.IdentifiableAttributes; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.beans.factory.annotation.Value; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.web.client.RestTemplate; | ||
import org.springframework.web.util.UriComponentsBuilder; | ||
|
||
import java.util.List; | ||
import java.util.Objects; | ||
import java.util.UUID; | ||
|
||
@Service | ||
public class FilterService { | ||
public static final String FILTER_END_POINT_EVALUATE_IDS = "/filters/evaluate/identifiables"; | ||
public static final String DELIMITER = "/"; | ||
public static final String FILTER_API_VERSION = "v1"; | ||
|
||
@Getter | ||
private final String baseUri; | ||
private final RestTemplate restTemplate; | ||
|
||
@Autowired | ||
public FilterService(@Value("${gridsuite.services.filter-server.base-uri:http://filter-server/}") String baseUri, | ||
RestTemplate restTemplate) { | ||
this.baseUri = baseUri; | ||
this.restTemplate = restTemplate; | ||
} | ||
|
||
public List<IdentifiableAttributes> evaluateFilters(UUID networkUuid, String variantUuid, List<UUID> filtersUuid) { | ||
Objects.requireNonNull(networkUuid); | ||
Objects.requireNonNull(filtersUuid); | ||
String endPointUrl = getBaseUri() + DELIMITER + FILTER_API_VERSION + FILTER_END_POINT_EVALUATE_IDS; | ||
|
||
UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromHttpUrl(endPointUrl); | ||
uriComponentsBuilder.queryParam("networkUuid", networkUuid); | ||
uriComponentsBuilder.queryParam("variantUuid", variantUuid); | ||
uriComponentsBuilder.queryParam("ids", filtersUuid); | ||
var uriComponent = uriComponentsBuilder.buildAndExpand(); | ||
|
||
ResponseEntity<FilteredIdentifiables> response = restTemplate.getForEntity(uriComponent.toUriString(), FilteredIdentifiables.class); | ||
return response.getBody() != null ? response.getBody().getEquipmentIds() : List.of(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,5 +12,6 @@ | |
|
||
public enum ContingencyListType { | ||
FORM, | ||
IDENTIFIERS | ||
IDENTIFIERS, | ||
FILTERS | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
package org.gridsuite.actions.server.utils; | ||
|
||
/* | ||
* 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/. | ||
*/ | ||
|
||
import com.fasterxml.jackson.databind.InjectableValues; | ||
import com.fasterxml.jackson.databind.MapperFeature; | ||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import com.powsybl.commons.report.ReportNodeDeserializer; | ||
import com.powsybl.commons.report.ReportNodeJsonModule; | ||
import com.powsybl.contingency.json.ContingencyJsonModule; | ||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.Configuration; | ||
import org.springframework.http.converter.HttpMessageConverter; | ||
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; | ||
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; | ||
import org.springframework.web.client.RestTemplate; | ||
|
||
@Configuration | ||
public class RestTemplateConfig { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess you took it from another service, maybe we can mutualize this bean? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes done |
||
|
||
@Bean | ||
public RestTemplate restTemplate() { | ||
final RestTemplate restTemplate = new RestTemplate(); | ||
|
||
//find and replace Jackson message converter with our own | ||
for (int i = 0; i < restTemplate.getMessageConverters().size(); i++) { | ||
final HttpMessageConverter<?> httpMessageConverter = restTemplate.getMessageConverters().get(i); | ||
if (httpMessageConverter instanceof MappingJackson2HttpMessageConverter) { | ||
restTemplate.getMessageConverters().set(i, mappingJackson2HttpMessageConverter()); | ||
} | ||
} | ||
|
||
return restTemplate; | ||
} | ||
|
||
public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() { | ||
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); | ||
converter.setObjectMapper(objectMapper()); | ||
return converter; | ||
} | ||
|
||
private ObjectMapper createObjectMapper() { | ||
ObjectMapper objectMapper = Jackson2ObjectMapperBuilder.json() | ||
.featuresToEnable(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS).build(); | ||
objectMapper.registerModule(new ContingencyJsonModule()); | ||
objectMapper.registerModule(new ReportNodeJsonModule()); | ||
objectMapper.setInjectableValues(new InjectableValues.Std().addValue(ReportNodeDeserializer.DICTIONARY_VALUE_ID, null)); | ||
return objectMapper; | ||
} | ||
|
||
@Bean | ||
public ObjectMapper objectMapper() { | ||
return createObjectMapper(); | ||
} | ||
|
||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PUT insert new lines in filter_metadata but not clean old lines, to verify annotation orphanRemoval option of OneToMany.
However, I see lines in relation table are removed