Skip to content

Commit 640009e

Browse files
Implement new endpoints
1 parent cac9e11 commit 640009e

File tree

5 files changed

+215
-53
lines changed

5 files changed

+215
-53
lines changed

pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
<liquibase-hibernate-package>org.gridsuite.shortcircuit.server</liquibase-hibernate-package>
4747
<mockito-inline.version>3.11.1</mockito-inline.version>
4848
<db-util.version>1.0.5</db-util.version>
49+
<json-patch.version>1.13</json-patch.version>
4950
</properties>
5051

5152
<build>
@@ -175,6 +176,11 @@
175176
<groupId>org.springframework.boot</groupId>
176177
<artifactId>spring-boot-starter-actuator</artifactId>
177178
</dependency>
179+
<dependency>
180+
<groupId>com.github.java-json-tools</groupId>
181+
<artifactId>json-patch</artifactId>
182+
<version>${json-patch.version}</version>
183+
</dependency>
178184

179185
<!-- Test dependencies -->
180186
<dependency>

src/main/java/org/gridsuite/shortcircuit/server/ShortCircuitController.java

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,14 @@
2525
import org.springframework.http.ResponseEntity;
2626
import org.springframework.web.bind.annotation.*;
2727

28-
import java.util.*;
28+
import java.util.List;
29+
import java.util.Objects;
30+
import java.util.UUID;
2931

3032
import static com.powsybl.shortcircuit.Fault.FaultType;
3133
import static org.gridsuite.shortcircuit.server.service.NotificationService.HEADER_USER_ID;
34+
import static org.gridsuite.shortcircuit.server.util.Utils.APPLICATION_JSON_PATCH_VALUE;
35+
import static org.springframework.http.HttpHeaders.CONTENT_TYPE;
3236
import static org.springframework.http.MediaType.*;
3337

3438
/**
@@ -44,10 +48,6 @@ public ShortCircuitController(ShortCircuitService shortCircuitService) {
4448
this.shortCircuitService = shortCircuitService;
4549
}
4650

47-
private static ShortCircuitParameters getNonNullParameters(ShortCircuitParameters parameters) {
48-
return parameters != null ? parameters : new ShortCircuitParameters();
49-
}
50-
5151
@PostMapping(value = "/networks/{networkUuid}/run-and-save", produces = APPLICATION_JSON_VALUE, consumes = APPLICATION_JSON_VALUE)
5252
@Operation(summary = "Run a short circuit analysis on a network")
5353
@ApiResponses(value = {@ApiResponse(responseCode = "200",
@@ -63,9 +63,8 @@ public ResponseEntity<UUID> runAndSave(@Parameter(description = "Network UUID")
6363
@Parameter(description = "Bus Id - Used for analysis targeting one bus") @RequestParam(name = "busId", required = false) String busId,
6464
@RequestBody(required = false) ShortCircuitParameters parameters,
6565
@RequestHeader(HEADER_USER_ID) String userId) {
66-
ShortCircuitParameters nonNullParameters = getNonNullParameters(parameters);
67-
UUID resultUuid = shortCircuitService.runAndSaveResult(new ShortCircuitRunContext(networkUuid, variantId, receiver, nonNullParameters, reportUuid, reporterId, reportType, userId, busId));
68-
return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(resultUuid);
66+
final ShortCircuitParameters nonNullParameters = Objects.requireNonNullElseGet(parameters, ShortCircuitParameters::new);
67+
return ResponseEntity.ok(shortCircuitService.runAndSaveResult(new ShortCircuitRunContext(networkUuid, variantId, receiver, nonNullParameters, reportUuid, reporterId, reportType, userId, busId)));
6968
}
7069

7170
@GetMapping(value = "/results/{resultUuid}", produces = APPLICATION_JSON_VALUE)
@@ -179,4 +178,41 @@ public ResponseEntity<List<LimitViolationType>> getLimitTypes(@Parameter(descrip
179178
return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(shortCircuitService.getLimitTypes(resultUuid));
180179
}
181180

181+
@GetMapping(value = "/parameters/{parametersUuid}", produces = APPLICATION_JSON_VALUE)
182+
@Operation(summary = "Get the parameters for an analysis")
183+
@ApiResponse(responseCode = "200", description = "The parameters asked")
184+
public ResponseEntity<ShortCircuitParametersInfos> getParameters(@Parameter(description = "UUID of parameters") @PathVariable("parametersUuid") UUID parametersUuid) {
185+
return ResponseEntity.of(shortCircuitService.getParameters(parametersUuid));
186+
}
187+
188+
@PostMapping(value = "/parameters", produces = TEXT_PLAIN_VALUE, consumes = {APPLICATION_JSON_VALUE, APPLICATION_JSON_PATCH_VALUE})
189+
@Operation(summary = "Create a new set of parameters for an analysis using default parameters as base")
190+
public ResponseEntity<UUID> createParameters(@RequestHeader(value = CONTENT_TYPE, required = false) MediaType contentType,
191+
@RequestBody(required = false) String parametersPatch) {
192+
return ResponseEntity.ok(shortCircuitService.createParameters(contentType, parametersPatch));
193+
}
194+
195+
@PostMapping(value = "/parameters", produces = TEXT_PLAIN_VALUE)
196+
@Operation(summary = "Duplicate the parameters of an analysis")
197+
public ResponseEntity<UUID> duplicateParameters(@Parameter(description = "UUID of parameters to duplicate") @RequestParam(name = "duplicateFrom") UUID sourceParametersUuid) {
198+
return ResponseEntity.of(shortCircuitService.duplicateParameters(sourceParametersUuid));
199+
}
200+
201+
@DeleteMapping(value = "/parameters/{parametersUuid}")
202+
@Operation(summary = "Delete a set of parameters")
203+
public ResponseEntity<Void> deleteParameters(@Parameter(description = "UUID of parameters") @PathVariable("parametersUuid") UUID parametersUuid) {
204+
shortCircuitService.deleteParameters(parametersUuid);
205+
return ResponseEntity.ok().build();
206+
}
207+
208+
@PutMapping(value = "/parameters/{parametersUuid}", consumes = {APPLICATION_JSON_VALUE, APPLICATION_JSON_PATCH_VALUE})
209+
@Operation(summary = "Update a set of parameters for an analysis or reset them to default ones")
210+
public ResponseEntity<Void> updateParameters(@Parameter(description = "UUID of parameters") @PathVariable("parametersUuid") UUID parametersUuid,
211+
@RequestHeader(value = CONTENT_TYPE, required = false) MediaType contentType, @RequestBody(required = false) String parametersPatch) throws JsonProcessingException {
212+
if (shortCircuitService.updateParameters(parametersUuid, contentType, parametersPatch)) {
213+
return ResponseEntity.noContent().build();
214+
} else {
215+
return ResponseEntity.notFound().build();
216+
}
217+
}
182218
}

src/main/java/org/gridsuite/shortcircuit/server/service/ShortCircuitService.java

Lines changed: 137 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
package org.gridsuite.shortcircuit.server.service;
88

99
import com.fasterxml.jackson.databind.ObjectMapper;
10+
import com.fasterxml.jackson.databind.node.ArrayNode;
11+
import com.github.fge.jsonpatch.JsonPatch;
12+
import com.github.fge.jsonpatch.JsonPatchException;
1013
import com.powsybl.security.LimitViolationType;
1114
import com.powsybl.shortcircuit.InitialVoltageProfileMode;
1215
import com.powsybl.shortcircuit.ShortCircuitParameters;
@@ -15,19 +18,25 @@
1518
import com.powsybl.ws.commons.LogUtils;
1619
import com.univocity.parsers.csv.CsvWriter;
1720
import com.univocity.parsers.csv.CsvWriterSettings;
21+
import jakarta.persistence.EntityManager;
22+
import lombok.SneakyThrows;
1823
import org.gridsuite.shortcircuit.server.ShortCircuitException;
1924
import org.gridsuite.shortcircuit.server.dto.*;
2025
import org.gridsuite.shortcircuit.server.entities.*;
26+
import org.gridsuite.shortcircuit.server.repositories.ParametersRepository;
2127
import org.gridsuite.shortcircuit.server.repositories.ShortCircuitAnalysisResultRepository;
28+
import org.gridsuite.shortcircuit.server.util.Utils;
2229
import org.slf4j.Logger;
2330
import org.slf4j.LoggerFactory;
24-
import org.springframework.beans.factory.annotation.Autowired;
2531
import org.springframework.data.domain.Page;
2632
import org.springframework.data.domain.Pageable;
33+
import org.springframework.http.MediaType;
34+
import org.springframework.lang.Nullable;
2735
import org.springframework.stereotype.Service;
2836
import org.springframework.transaction.annotation.Transactional;
2937

30-
import java.io.*;
38+
import java.io.ByteArrayOutputStream;
39+
import java.io.IOException;
3140
import java.nio.charset.StandardCharsets;
3241
import java.util.*;
3342
import java.util.concurrent.TimeUnit;
@@ -48,25 +57,29 @@ public class ShortCircuitService {
4857

4958
//TODO tmp migration
5059
private static final List<VoltageRange> CEI909_VOLTAGE_PROFILE = List.of(
51-
new VoltageRange(10.0, 199.99, 1.1),
52-
new VoltageRange(200.0, 299.99, 1.09),
53-
new VoltageRange(300.0, 500.0, 1.05)
60+
new VoltageRange(10.0, 199.99, 1.1),
61+
new VoltageRange(200.0, 299.99, 1.09),
62+
new VoltageRange(300.0, 500.0, 1.05)
5463
);
5564

56-
@Autowired
57-
NotificationService notificationService;
58-
59-
private UuidGeneratorService uuidGeneratorService;
60-
61-
private ShortCircuitAnalysisResultRepository resultRepository;
62-
63-
private ObjectMapper objectMapper;
64-
65-
public ShortCircuitService(NotificationService notificationService, UuidGeneratorService uuidGeneratorService, ShortCircuitAnalysisResultRepository resultRepository, ObjectMapper objectMapper) {
65+
private final NotificationService notificationService;
66+
private final UuidGeneratorService uuidGeneratorService;
67+
private final ShortCircuitAnalysisResultRepository resultRepository;
68+
private final ParametersRepository parametersRepository;
69+
private final ObjectMapper objectMapper;
70+
private final EntityManager entityManager;
71+
72+
public ShortCircuitService(NotificationService notificationService,
73+
UuidGeneratorService uuidGeneratorService,
74+
ShortCircuitAnalysisResultRepository resultRepository,
75+
ParametersRepository parametersRepository,
76+
ObjectMapper objectMapper, EntityManager entityManager) {
6677
this.notificationService = Objects.requireNonNull(notificationService);
6778
this.uuidGeneratorService = Objects.requireNonNull(uuidGeneratorService);
6879
this.resultRepository = Objects.requireNonNull(resultRepository);
6980
this.objectMapper = Objects.requireNonNull(objectMapper);
81+
this.parametersRepository = parametersRepository;
82+
this.entityManager = entityManager;
7083
}
7184

7285
public UUID runAndSaveResult(ShortCircuitRunContext runContext) {
@@ -124,28 +137,29 @@ private static FeederResult fromEntity(FeederResultEntity feederResultEntity) {
124137
return new FeederResult(feederResultEntity.getConnectableId(), feederResultEntity.getCurrent(), feederResultEntity.getPositiveMagnitude());
125138
}
126139

127-
//TODO tmp migration
128-
public static AnalysisParametersEntity toEntity(ShortCircuitParameters parameters, ShortCircuitPredefinedConfiguration shortCircuitPredefinedConfiguration) {
129-
Objects.requireNonNull(parameters);
130-
return new AnalysisParametersEntity(parameters.isWithLimitViolations(),
131-
parameters.isWithVoltageResult(),
132-
parameters.isWithFortescueResult(),
133-
parameters.isWithFeederResult(),
134-
parameters.getStudyType(),
135-
parameters.getMinVoltageDropProportionalThreshold(),
136-
parameters.isWithLoads(),
137-
parameters.isWithShuntCompensators(),
138-
parameters.isWithVSCConverterStations(),
139-
parameters.isWithNeutralPosition(),
140-
parameters.getInitialVoltageProfileMode(),
141-
shortCircuitPredefinedConfiguration);
140+
private static AnalysisParametersEntity toEntity(ShortCircuitParametersInfos parametersInfos) {
141+
final ShortCircuitParameters parameters = parametersInfos.parameters();
142+
return new AnalysisParametersEntity(
143+
parameters.isWithLimitViolations(),
144+
parameters.isWithVoltageResult(),
145+
parameters.isWithFortescueResult(),
146+
parameters.isWithFeederResult(),
147+
parameters.getStudyType(),
148+
parameters.getMinVoltageDropProportionalThreshold(),
149+
parameters.isWithLoads(),
150+
parameters.isWithShuntCompensators(),
151+
parameters.isWithVSCConverterStations(),
152+
parameters.isWithNeutralPosition(),
153+
parameters.getInitialVoltageProfileMode(),
154+
parametersInfos.predefinedParameters()
155+
);
142156
}
143157

144-
//TODO tmp migration
145-
public static ShortCircuitParameters fromEntity(AnalysisParametersEntity entity) {
158+
private static ShortCircuitParametersInfos fromEntity(AnalysisParametersEntity entity) {
146159
Objects.requireNonNull(entity);
147-
List<VoltageRange> voltageRanges = InitialVoltageProfileMode.CONFIGURED.equals(entity.getInitialVoltageProfileMode()) ? CEI909_VOLTAGE_PROFILE : null;
148-
return new ShortCircuitParameters()
160+
return new ShortCircuitParametersInfos(
161+
entity.getPredefinedParameters(),
162+
new ShortCircuitParameters()
149163
.setStudyType(entity.getStudyType())
150164
.setMinVoltageDropProportionalThreshold(entity.getMinVoltageDropProportionalThreshold())
151165
.setWithFeederResult(entity.isWithFeederResult())
@@ -157,11 +171,20 @@ public static ShortCircuitParameters fromEntity(AnalysisParametersEntity entity)
157171
.setWithVSCConverterStations(entity.isWithVscConverterStations())
158172
.setWithNeutralPosition(entity.isWithNeutralPosition())
159173
.setInitialVoltageProfileMode(entity.getInitialVoltageProfileMode())
160-
.setVoltageRanges(voltageRanges);
174+
.setVoltageRanges(InitialVoltageProfileMode.CONFIGURED.equals(entity.getInitialVoltageProfileMode()) ? CEI909_VOLTAGE_PROFILE : null),
175+
CEI909_VOLTAGE_PROFILE
176+
);
161177
}
162178

163-
//TODO tmp migration
164-
public static ShortCircuitParameters getDefaultShortCircuitParameters() {
179+
private static ShortCircuitParametersInfos getDefaultDtoParameters() {
180+
return new ShortCircuitParametersInfos(
181+
ShortCircuitPredefinedConfiguration.ICC_MAX_WITH_CEI909,
182+
getDefaultShortCircuitParameters(),
183+
CEI909_VOLTAGE_PROFILE
184+
);
185+
}
186+
187+
private static ShortCircuitParameters getDefaultShortCircuitParameters() {
165188
return new ShortCircuitParameters()
166189
.setStudyType(StudyType.TRANSIENT)
167190
.setMinVoltageDropProportionalThreshold(20)
@@ -178,14 +201,23 @@ public static ShortCircuitParameters getDefaultShortCircuitParameters() {
178201
.setVoltageRanges(null);
179202
}
180203

181-
//TODO tmp migration
182-
public static ShortCircuitParametersInfos toShortCircuitParametersInfo(AnalysisParametersEntity entity) {
183-
Objects.requireNonNull(entity);
184-
return ShortCircuitParametersInfos.builder()
185-
.predefinedParameters(entity.getPredefinedParameters())
186-
.parameters(fromEntity(entity))
187-
.cei909VoltageRanges(CEI909_VOLTAGE_PROFILE)
188-
.build();
204+
private static void updateEntity(AnalysisParametersEntity parametersEntity, final ShortCircuitParametersInfos parametersInfos) {
205+
parametersEntity.setPredefinedParameters(parametersInfos.predefinedParameters());
206+
final ShortCircuitParameters scParameters = parametersInfos.parameters();
207+
parametersEntity.setWithLimitViolations(scParameters.isWithLimitViolations());
208+
parametersEntity.setWithVoltageResult(scParameters.isWithVoltageResult());
209+
parametersEntity.setWithFortescueResult(scParameters.isWithFortescueResult());
210+
parametersEntity.setWithFeederResult(scParameters.isWithFeederResult());
211+
parametersEntity.setStudyType(scParameters.getStudyType());
212+
parametersEntity.setMinVoltageDropProportionalThreshold(scParameters.getMinVoltageDropProportionalThreshold());
213+
parametersEntity.setWithLoads(scParameters.isWithLoads());
214+
parametersEntity.setWithShuntCompensators(scParameters.isWithShuntCompensators());
215+
parametersEntity.setWithVscConverterStations(scParameters.isWithVSCConverterStations());
216+
parametersEntity.setWithNeutralPosition(scParameters.isWithNeutralPosition());
217+
parametersEntity.setInitialVoltageProfileMode(scParameters.getInitialVoltageProfileMode());
218+
//scParameters.isDetailedReport()
219+
//scParameters.getVoltageRanges()
220+
//scParameters.getSubTransientCoefficient()
189221
}
190222

191223
private static ShortCircuitAnalysisResultEntity sortByElementId(ShortCircuitAnalysisResultEntity result) {
@@ -396,4 +428,64 @@ public List<LimitViolationType> getLimitTypes(UUID resultUuid) {
396428
public List<com.powsybl.shortcircuit.Fault.FaultType> getFaultTypes(UUID resultUuid) {
397429
return resultRepository.findFaultTypes(resultUuid);
398430
}
431+
432+
public Optional<ShortCircuitParametersInfos> getParameters(final UUID parametersUuid) {
433+
return parametersRepository.findById(parametersUuid).map(ShortCircuitService::fromEntity);
434+
}
435+
436+
public void deleteParameters(final UUID parametersUuid) {
437+
parametersRepository.deleteById(parametersUuid);
438+
}
439+
440+
@Transactional
441+
public Optional<UUID> duplicateParameters(UUID sourceParametersUuid) {
442+
return parametersRepository.findById(sourceParametersUuid)
443+
.map(entity -> {
444+
entityManager.detach(entity);
445+
entity.setId(null);
446+
return entity;
447+
})
448+
.map(parametersRepository::save)
449+
.map(AnalysisParametersEntity::getId);
450+
}
451+
452+
private ShortCircuitParametersInfos updateDto(ShortCircuitParametersInfos parameters, @Nullable final MediaType contentType, final String parametersPatch)
453+
throws IllegalArgumentException, IOException, JsonPatchException {
454+
if (contentType == null) {
455+
throw new IllegalArgumentException("Content-Type is mandatory");
456+
} else if (Utils.APPLICATION_JSON_PATCH.equalsTypeAndSubtype(contentType)) {
457+
return objectMapper.treeToValue(JsonPatch.fromJson(objectMapper.readValue(parametersPatch, ArrayNode.class))
458+
.apply(objectMapper.valueToTree(parameters)), ShortCircuitParametersInfos.class);
459+
} else if (MediaType.APPLICATION_JSON.equalsTypeAndSubtype(contentType)) {
460+
return objectMapper.readerForUpdating(parameters).readValue(parametersPatch);
461+
} else {
462+
throw new IllegalArgumentException("Unsupported content type: " + contentType);
463+
}
464+
}
465+
466+
@SneakyThrows
467+
public UUID createParameters(@Nullable final MediaType contentType, @Nullable final String parametersPatch) {
468+
ShortCircuitParametersInfos parameters = getDefaultDtoParameters();
469+
if (parametersPatch != null) {
470+
parameters = updateDto(parameters, contentType, parametersPatch);
471+
}
472+
return parametersRepository.save(toEntity(parameters)).getId();
473+
}
474+
475+
@SneakyThrows
476+
public boolean updateParameters(final UUID parametersUuid, @Nullable final MediaType contentType, @Nullable final String parametersPatch) {
477+
AnalysisParametersEntity parameters = parametersRepository.findById(parametersUuid).orElse(null);
478+
if (parameters == null) {
479+
return false;
480+
} else {
481+
if (parametersPatch == null) {
482+
// we simply reset
483+
updateEntity(parameters, getDefaultDtoParameters());
484+
} else {
485+
updateEntity(parameters, updateDto(fromEntity(parameters), contentType, parametersPatch));
486+
}
487+
parametersRepository.save(parameters);
488+
return true;
489+
}
490+
}
399491
}

0 commit comments

Comments
 (0)