diff --git a/pom.xml b/pom.xml index 18d3852a..895a3d8f 100644 --- a/pom.xml +++ b/pom.xml @@ -49,6 +49,7 @@ 5.0.0-alpha.14 gridsuite org.gridsuite:security-analysis-server + 1.25.0 @@ -146,6 +147,7 @@ com.powsybl powsybl-ws-commons + ${powsybl-ws-commons.version} org.springframework.cloud diff --git a/src/main/java/org/gridsuite/securityanalysis/server/RestResponseEntityExceptionHandler.java b/src/main/java/org/gridsuite/securityanalysis/server/RestResponseEntityExceptionHandler.java index 34cd0ebf..d51b2c09 100644 --- a/src/main/java/org/gridsuite/securityanalysis/server/RestResponseEntityExceptionHandler.java +++ b/src/main/java/org/gridsuite/securityanalysis/server/RestResponseEntityExceptionHandler.java @@ -6,7 +6,7 @@ */ package org.gridsuite.securityanalysis.server; -import org.gridsuite.securityanalysis.server.util.SecurityAnalysisException; +import com.powsybl.ws.commons.computation.ComputationException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.HttpStatus; @@ -23,18 +23,18 @@ public class RestResponseEntityExceptionHandler { private static final Logger LOGGER = LoggerFactory.getLogger(RestResponseEntityExceptionHandler.class); - @ExceptionHandler(SecurityAnalysisException.class) - protected ResponseEntity handleStudyException(SecurityAnalysisException exception) { + @ExceptionHandler(ComputationException.class) + protected ResponseEntity handleStudyException(ComputationException exception) { if (LOGGER.isErrorEnabled()) { LOGGER.error(exception.getMessage()); } - switch (exception.getType()) { + switch (exception.getExceptionType()) { case RESULT_NOT_FOUND, PARAMETERS_NOT_FOUND: - return ResponseEntity.status(HttpStatus.NOT_FOUND).body(exception.getType()); + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(exception.getExceptionType()); case INVALID_FILTER_FORMAT, INVALID_FILTER, INVALID_SORT_FORMAT: - return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(exception.getType()); + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(exception.getExceptionType()); default: - return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(exception.getType()); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(exception.getExceptionType()); } } } diff --git a/src/main/java/org/gridsuite/securityanalysis/server/SecurityAnalysisController.java b/src/main/java/org/gridsuite/securityanalysis/server/SecurityAnalysisController.java index 669af0b3..20dc9b39 100644 --- a/src/main/java/org/gridsuite/securityanalysis/server/SecurityAnalysisController.java +++ b/src/main/java/org/gridsuite/securityanalysis/server/SecurityAnalysisController.java @@ -35,6 +35,7 @@ import java.util.UUID; import static com.powsybl.ws.commons.computation.service.NotificationService.HEADER_USER_ID; +import static com.powsybl.ws.commons.computation.utils.FilterUtils.fromStringFiltersToDTO; import static org.springframework.http.MediaType.*; /** @@ -124,7 +125,10 @@ public ResponseEntity> getNResult(@P @Parameter(description = "Filters") @RequestParam(name = "filters", required = false) String stringFilters, @Parameter(description = "Pageable parameters for pagination and sorting") Sort sort) { String decodedStringFilters = stringFilters != null ? URLDecoder.decode(stringFilters, StandardCharsets.UTF_8) : null; - List result = securityAnalysisResultService.findNResult(resultUuid, securityAnalysisResultService.fromStringFiltersToDTO(decodedStringFilters), sort); + List result = securityAnalysisResultService.findNResult( + resultUuid, + fromStringFiltersToDTO(decodedStringFilters, securityAnalysisResultService.getObjectMapper()), + sort); return result != null ? ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(result) diff --git a/src/main/java/org/gridsuite/securityanalysis/server/dto/ResourceFilterDTO.java b/src/main/java/org/gridsuite/securityanalysis/server/dto/ResourceFilterDTO.java deleted file mode 100644 index 2f48e209..00000000 --- a/src/main/java/org/gridsuite/securityanalysis/server/dto/ResourceFilterDTO.java +++ /dev/null @@ -1,45 +0,0 @@ -/** -* 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.securityanalysis.server.dto; - -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * An object that can be used to filter data with the JPA Criteria API (via Spring Specification) - * @param dataType the type of data we want to filter (text, number) - * @param type the type of filter (contains, startsWith...) - * @param value the value of the filter - * @param column the column / field on which the filter will be applied - * @param tolerance precision/tolerance used for the comparisons (simulates the rounding of the database values) Only useful for numbers. - * @author Kevin Le Saulnier - */ -public record ResourceFilterDTO(DataType dataType, Type type, Object value, String column, Double tolerance) { - public ResourceFilterDTO(DataType dataType, Type type, Object value, String column) { - this(dataType, type, value, column, null); - } - - public enum DataType { - @JsonProperty("text") - TEXT, - @JsonProperty("number") - NUMBER, - } - - public enum Type { - CONTAINS, - @JsonProperty("startsWith") - STARTS_WITH, - EQUALS, - @JsonProperty("notEqual") - NOT_EQUAL, - @JsonProperty("lessThanOrEqual") - LESS_THAN_OR_EQUAL, - @JsonProperty("greaterThanOrEqual") - GREATER_THAN_OR_EQUAL - } -} diff --git a/src/main/java/org/gridsuite/securityanalysis/server/repositories/specifications/AbstractCommonSpecificationBuilder.java b/src/main/java/org/gridsuite/securityanalysis/server/repositories/specifications/AbstractCommonSpecificationBuilder.java deleted file mode 100644 index 755e1d82..00000000 --- a/src/main/java/org/gridsuite/securityanalysis/server/repositories/specifications/AbstractCommonSpecificationBuilder.java +++ /dev/null @@ -1,64 +0,0 @@ -/** - * Copyright (c) 2024, 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.securityanalysis.server.repositories.specifications; - -import jakarta.persistence.criteria.Path; -import jakarta.persistence.criteria.Root; -import org.gridsuite.securityanalysis.server.dto.ResourceFilterDTO; -import org.springframework.data.jpa.domain.Specification; - -import java.util.List; -import java.util.UUID; - -/** - * @author Kevin LE SAULNIER - */ -public abstract class AbstractCommonSpecificationBuilder { - AbstractCommonSpecificationBuilder() { - } - - public Specification resultUuidEquals(UUID value) { - return (root, cq, cb) -> cb.equal(getResultIdPath(root), value); - } - - public Specification uuidIn(List uuids) { - return (root, cq, cb) -> root.get(getIdFieldName()).in(uuids); - } - - public Specification buildSpecification(UUID resultUuid, List resourceFilters) { - List childrenResourceFilter = resourceFilters.stream().filter(this::isNotParentFilter).toList(); - // since sql joins generates duplicate results, we need to use distinct here - Specification specification = SpecificationUtils.distinct(); - // filter by resultUuid - specification = specification.and(Specification.where(resultUuidEquals(resultUuid))); - if (childrenResourceFilter.isEmpty()) { - specification = specification.and(addSpecificFilterWhenNoChildrenFilter()); - } else { - // needed here to filter main entities that would have empty collection when filters are applied - specification = specification.and(childrenNotEmpty()); - } - - return SpecificationUtils.appendFiltersToSpecification(specification, resourceFilters); - } - - public Specification buildLimitViolationsSpecification(List uuids, List resourceFilters) { - List childrenResourceFilter = resourceFilters.stream().filter(this::isNotParentFilter).toList(); - Specification specification = Specification.where(uuidIn(uuids)); - - return SpecificationUtils.appendFiltersToSpecification(specification, childrenResourceFilter); - } - - public abstract Specification childrenNotEmpty(); - - public abstract boolean isNotParentFilter(ResourceFilterDTO filter); - - public abstract String getIdFieldName(); - - public abstract Path getResultIdPath(Root root); - - public abstract Specification addSpecificFilterWhenNoChildrenFilter(); -} diff --git a/src/main/java/org/gridsuite/securityanalysis/server/repositories/specifications/ContingencySpecificationBuilder.java b/src/main/java/org/gridsuite/securityanalysis/server/repositories/specifications/ContingencySpecificationBuilder.java index 02ee595a..c0905f20 100644 --- a/src/main/java/org/gridsuite/securityanalysis/server/repositories/specifications/ContingencySpecificationBuilder.java +++ b/src/main/java/org/gridsuite/securityanalysis/server/repositories/specifications/ContingencySpecificationBuilder.java @@ -7,9 +7,11 @@ package org.gridsuite.securityanalysis.server.repositories.specifications; import com.powsybl.loadflow.LoadFlowResult; +import com.powsybl.ws.commons.computation.dto.ResourceFilterDTO; +import com.powsybl.ws.commons.computation.specification.AbstractCommonSpecificationBuilder; +import com.powsybl.ws.commons.computation.utils.SpecificationUtils; import jakarta.persistence.criteria.Path; import jakarta.persistence.criteria.Root; -import org.gridsuite.securityanalysis.server.dto.ResourceFilterDTO; import org.gridsuite.securityanalysis.server.entities.ContingencyEntity; import org.gridsuite.securityanalysis.server.entities.SecurityAnalysisResultEntity; import org.springframework.data.jpa.domain.Specification; @@ -40,11 +42,11 @@ public Path getResultIdPath(Root root) { @Override public Specification addSpecificFilterWhenNoChildrenFilter() { - return this.childrenNotEmpty().or(SpecificationUtils.notEqual(ContingencyEntity.Fields.status, LoadFlowResult.ComponentResult.Status.CONVERGED.name())); + return this.addSpecificFilterWhenChildrenFilters().or(SpecificationUtils.notEqual(ContingencyEntity.Fields.status, LoadFlowResult.ComponentResult.Status.CONVERGED.name())); } @Override - public Specification childrenNotEmpty() { + public Specification addSpecificFilterWhenChildrenFilters() { return SpecificationUtils.isNotEmpty(ContingencyEntity.Fields.contingencyLimitViolations); } } diff --git a/src/main/java/org/gridsuite/securityanalysis/server/repositories/specifications/PreContingencyLimitViolationSpecificationBuilder.java b/src/main/java/org/gridsuite/securityanalysis/server/repositories/specifications/PreContingencyLimitViolationSpecificationBuilder.java index d9cb695d..b712a47f 100644 --- a/src/main/java/org/gridsuite/securityanalysis/server/repositories/specifications/PreContingencyLimitViolationSpecificationBuilder.java +++ b/src/main/java/org/gridsuite/securityanalysis/server/repositories/specifications/PreContingencyLimitViolationSpecificationBuilder.java @@ -6,7 +6,8 @@ */ package org.gridsuite.securityanalysis.server.repositories.specifications; -import org.gridsuite.securityanalysis.server.dto.ResourceFilterDTO; +import com.powsybl.ws.commons.computation.dto.ResourceFilterDTO; +import com.powsybl.ws.commons.computation.utils.SpecificationUtils; import org.gridsuite.securityanalysis.server.entities.PreContingencyLimitViolationEntity; import org.springframework.data.jpa.domain.Specification; import org.springframework.stereotype.Service; diff --git a/src/main/java/org/gridsuite/securityanalysis/server/repositories/specifications/SpecificationUtils.java b/src/main/java/org/gridsuite/securityanalysis/server/repositories/specifications/SpecificationUtils.java deleted file mode 100644 index 53722a58..00000000 --- a/src/main/java/org/gridsuite/securityanalysis/server/repositories/specifications/SpecificationUtils.java +++ /dev/null @@ -1,203 +0,0 @@ -/** - * Copyright (c) 2024, 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.securityanalysis.server.repositories.specifications; - -import jakarta.persistence.criteria.Expression; -import jakarta.persistence.criteria.Path; -import jakarta.persistence.criteria.Root; -import org.gridsuite.securityanalysis.server.dto.ResourceFilterDTO; -import org.jetbrains.annotations.NotNull; -import org.springframework.data.jpa.domain.Specification; -import org.springframework.data.jpa.repository.query.EscapeCharacter; - -import java.util.Collection; -import java.util.List; -import java.util.Objects; - -import static org.springframework.data.jpa.domain.Specification.anyOf; -import static org.springframework.data.jpa.domain.Specification.not; - -/** - * Utility class to create Spring Data JPA Specification (Spring interface for JPA Criteria API). - * - * @author Kevin Le Saulnier - */ -public final class SpecificationUtils { - - public static final String FIELD_SEPARATOR = "."; - - // Utility class, so no constructor - private SpecificationUtils() { - } - - // we use .as(String.class) to be able to works on enum fields - public static Specification equals(String field, String value) { - return (root, cq, cb) -> cb.equal(cb.upper(getColumnPath(root, field)).as(String.class), value.toUpperCase()); - } - - public static Specification notEqual(String field, String value) { - return (root, cq, cb) -> cb.notEqual(getColumnPath(root, field), value); - } - - public static Specification contains(String field, String value) { - return (root, cq, cb) -> cb.like(cb.upper(getColumnPath(root, field)), "%" + EscapeCharacter.DEFAULT.escape(value).toUpperCase() + "%", EscapeCharacter.DEFAULT.getEscapeCharacter()); - } - - public static Specification startsWith(String field, String value) { - return (root, cq, cb) -> cb.like(cb.upper(getColumnPath(root, field)), EscapeCharacter.DEFAULT.escape(value).toUpperCase() + "%", EscapeCharacter.DEFAULT.getEscapeCharacter()); - } - - /** - * Returns a specification where the field value is not equal within the given tolerance. - */ - public static Specification notEqual(String field, Double value, Double tolerance) { - return (root, cq, cb) -> { - Expression doubleExpression = getColumnPath(root, field).as(Double.class); - /** - * in order to be equal to doubleExpression, value has to fit : - * value - tolerance <= doubleExpression <= value + tolerance - * therefore in order to be different at least one of the opposite comparison needs to be true : - */ - return cb.or( - cb.greaterThan(doubleExpression, value + tolerance), - cb.lessThan(doubleExpression, value - tolerance) - ); - }; - } - - public static Specification lessThanOrEqual(String field, Double value, Double tolerance) { - return (root, cq, cb) -> { - Expression doubleExpression = getColumnPath(root, field).as(Double.class); - return cb.lessThanOrEqualTo(doubleExpression, value + tolerance); - }; - } - - public static Specification greaterThanOrEqual(String field, Double value, Double tolerance) { - return (root, cq, cb) -> { - Expression doubleExpression = getColumnPath(root, field).as(Double.class); - return cb.greaterThanOrEqualTo(doubleExpression, value - tolerance); - }; - } - - public static Specification isNotEmpty(String field) { - return (root, cq, cb) -> cb.isNotEmpty(getColumnPath(root, field)); - } - - public static Specification distinct() { - return (root, cq, cb) -> { - // to select distinct result, we need to set a "criteria query" param - // we don't need to return any predicate here - cq.distinct(true); - return null; - }; - } - - public static Specification appendFiltersToSpecification(Specification specification, List resourceFilters) { - Objects.requireNonNull(specification); - - if (resourceFilters == null || resourceFilters.isEmpty()) { - return specification; - } - - Specification completedSpecification = specification; - - for (ResourceFilterDTO resourceFilter : resourceFilters) { - if (resourceFilter.dataType() == ResourceFilterDTO.DataType.TEXT) { - completedSpecification = appendTextFilterToSpecification(completedSpecification, resourceFilter); - } else if (resourceFilter.dataType() == ResourceFilterDTO.DataType.NUMBER) { - completedSpecification = appendNumberFilterToSpecification(completedSpecification, resourceFilter); - } - } - - return completedSpecification; - } - - @NotNull - private static Specification appendTextFilterToSpecification(Specification specification, ResourceFilterDTO resourceFilter) { - Specification completedSpecification = specification; - - switch (resourceFilter.type()) { - case EQUALS -> { - // this type can manage one value or a list of values (with OR) - if (resourceFilter.value() instanceof Collection valueList) { - completedSpecification = completedSpecification.and(anyOf(valueList.stream().map(value -> SpecificationUtils.equals(resourceFilter.column(), value.toString())).toList())); - } else if (resourceFilter.value() == null) { - // if the value is null, we build an impossible specification (trick to remove later on ?) - completedSpecification = completedSpecification.and(not(completedSpecification)); - } else { - completedSpecification = completedSpecification.and(equals(resourceFilter.column(), resourceFilter.value().toString())); - } - } - case CONTAINS -> - completedSpecification = completedSpecification.and(contains(resourceFilter.column(), resourceFilter.value().toString())); - case STARTS_WITH -> - completedSpecification = completedSpecification.and(startsWith(resourceFilter.column(), resourceFilter.value().toString())); - default -> throw new IllegalArgumentException("The filter type " + resourceFilter.type() + " is not supported with the data type " + resourceFilter.dataType()); - } - - return completedSpecification; - } - - @NotNull - private static Specification appendNumberFilterToSpecification(Specification specification, ResourceFilterDTO resourceFilter) { - String value = resourceFilter.value().toString(); - return createNumberPredicate(specification, resourceFilter, value); - } - - private static Specification createNumberPredicate(Specification specification, ResourceFilterDTO resourceFilter, String filterValue) { - double tolerance; - if (resourceFilter.tolerance() != null) { - tolerance = resourceFilter.tolerance(); - } else { - // the reference for the comparison is the number of digits after the decimal point in filterValue - // extra digits are ignored, but the user may add '0's after the decimal point in order to get a better precision - String[] splitValue = filterValue.split("\\."); - int numberOfDecimalAfterDot = 0; - if (splitValue.length > 1) { - numberOfDecimalAfterDot = splitValue[1].length(); - } - // tolerance is multiplied by 0.5 to simulate the fact that the database value is rounded (in the front, from the user viewpoint) - // more than 13 decimal after dot will likely cause rounding errors due to double precision - tolerance = Math.pow(10, -numberOfDecimalAfterDot) * 0.5; - } - Double valueDouble = Double.valueOf(filterValue); - return switch (resourceFilter.type()) { - case NOT_EQUAL -> specification.and(notEqual(resourceFilter.column(), valueDouble, tolerance)); - case LESS_THAN_OR_EQUAL -> - specification.and(lessThanOrEqual(resourceFilter.column(), valueDouble, tolerance)); - case GREATER_THAN_OR_EQUAL -> - specification.and(greaterThanOrEqual(resourceFilter.column(), valueDouble, tolerance)); - default -> - throw new IllegalArgumentException("The filter type " + resourceFilter.type() + " is not supported with the data type " + resourceFilter.dataType()); - }; - } - - /** - * This method allow to query eventually dot separated fields with the Criteria API - * Ex : from 'fortescueCurrent.positiveMagnitude' we create the query path - * root.get("fortescueCurrent").get("positiveMagnitude") to access to the correct nested field - * - * @param root the root entity - * @param dotSeparatedFields dot separated fields (can be only one field without any dot) - * @param the entity type referenced by the root - * @param the type referenced by the path - * @return path for the query - */ - private static Path getColumnPath(Root root, String dotSeparatedFields) { - if (dotSeparatedFields.contains(SpecificationUtils.FIELD_SEPARATOR)) { - String[] fields = dotSeparatedFields.split("\\."); - Path path = root.get(fields[0]); - for (int i = 1; i < fields.length; i++) { - path = path.get(fields[i]); - } - return path; - } else { - return root.get(dotSeparatedFields); - } - } -} diff --git a/src/main/java/org/gridsuite/securityanalysis/server/repositories/specifications/SubjectLimitViolationSpecificationBuilder.java b/src/main/java/org/gridsuite/securityanalysis/server/repositories/specifications/SubjectLimitViolationSpecificationBuilder.java index 9003e274..acdc73a0 100644 --- a/src/main/java/org/gridsuite/securityanalysis/server/repositories/specifications/SubjectLimitViolationSpecificationBuilder.java +++ b/src/main/java/org/gridsuite/securityanalysis/server/repositories/specifications/SubjectLimitViolationSpecificationBuilder.java @@ -6,9 +6,11 @@ */ package org.gridsuite.securityanalysis.server.repositories.specifications; +import com.powsybl.ws.commons.computation.dto.ResourceFilterDTO; +import com.powsybl.ws.commons.computation.specification.AbstractCommonSpecificationBuilder; +import com.powsybl.ws.commons.computation.utils.SpecificationUtils; import jakarta.persistence.criteria.Path; import jakarta.persistence.criteria.Root; -import org.gridsuite.securityanalysis.server.dto.ResourceFilterDTO; import org.gridsuite.securityanalysis.server.entities.SecurityAnalysisResultEntity; import org.gridsuite.securityanalysis.server.entities.SubjectLimitViolationEntity; import org.springframework.data.jpa.domain.Specification; @@ -37,12 +39,12 @@ public Path getResultIdPath(Root root) { } @Override - public Specification childrenNotEmpty() { + public Specification addSpecificFilterWhenChildrenFilters() { return SpecificationUtils.isNotEmpty(SubjectLimitViolationEntity.Fields.contingencyLimitViolations); } @Override public Specification addSpecificFilterWhenNoChildrenFilter() { - return this.childrenNotEmpty(); + return this.addSpecificFilterWhenChildrenFilters(); } } diff --git a/src/main/java/org/gridsuite/securityanalysis/server/service/LimitReductionService.java b/src/main/java/org/gridsuite/securityanalysis/server/service/LimitReductionService.java index c95d68a1..2b11e43c 100644 --- a/src/main/java/org/gridsuite/securityanalysis/server/service/LimitReductionService.java +++ b/src/main/java/org/gridsuite/securityanalysis/server/service/LimitReductionService.java @@ -6,11 +6,11 @@ */ package org.gridsuite.securityanalysis.server.service; +import com.powsybl.ws.commons.computation.ComputationException; import lombok.Getter; import lombok.Setter; import org.apache.commons.lang3.Range; import org.gridsuite.securityanalysis.server.dto.LimitReductionsByVoltageLevel; -import org.gridsuite.securityanalysis.server.util.SecurityAnalysisException; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Service; @@ -64,41 +64,41 @@ private List getLimitReductionsByD private void assertValidConfig(List> values) { if (voltageLevels.isEmpty()) { - throw new SecurityAnalysisException(SecurityAnalysisException.Type.LIMIT_REDUCTION_CONFIG_ERROR, "No configuration for voltage levels"); + throw new ComputationException(ComputationException.Type.LIMIT_REDUCTION_CONFIG_ERROR, "No configuration for voltage levels"); } if (limitDurations.isEmpty()) { - throw new SecurityAnalysisException(SecurityAnalysisException.Type.LIMIT_REDUCTION_CONFIG_ERROR, "No configuration for limit durations"); + throw new ComputationException(ComputationException.Type.LIMIT_REDUCTION_CONFIG_ERROR, "No configuration for limit durations"); } if (values.isEmpty() || values.get(0).isEmpty()) { - throw new SecurityAnalysisException(SecurityAnalysisException.Type.LIMIT_REDUCTION_CONFIG_ERROR, "No values provided"); + throw new ComputationException(ComputationException.Type.LIMIT_REDUCTION_CONFIG_ERROR, "No values provided"); } int nbValuesByVl = values.get(0).size(); if (values.stream().anyMatch(valuesByVl -> valuesByVl.size() != nbValuesByVl)) { - throw new SecurityAnalysisException(SecurityAnalysisException.Type.LIMIT_REDUCTION_CONFIG_ERROR, "Number of values for a voltage level is incorrect"); + throw new ComputationException(ComputationException.Type.LIMIT_REDUCTION_CONFIG_ERROR, "Number of values for a voltage level is incorrect"); } if (voltageLevels.size() < values.size()) { - throw new SecurityAnalysisException(SecurityAnalysisException.Type.LIMIT_REDUCTION_CONFIG_ERROR, "Too many values provided for voltage levels"); + throw new ComputationException(ComputationException.Type.LIMIT_REDUCTION_CONFIG_ERROR, "Too many values provided for voltage levels"); } if (voltageLevels.size() > values.size()) { - throw new SecurityAnalysisException(SecurityAnalysisException.Type.LIMIT_REDUCTION_CONFIG_ERROR, "Not enough values provided for voltage levels"); + throw new ComputationException(ComputationException.Type.LIMIT_REDUCTION_CONFIG_ERROR, "Not enough values provided for voltage levels"); } if (limitDurations.size() < nbValuesByVl - 1) { - throw new SecurityAnalysisException(SecurityAnalysisException.Type.LIMIT_REDUCTION_CONFIG_ERROR, "Too many values provided for limit durations"); + throw new ComputationException(ComputationException.Type.LIMIT_REDUCTION_CONFIG_ERROR, "Too many values provided for limit durations"); } if (limitDurations.size() > nbValuesByVl - 1) { - throw new SecurityAnalysisException(SecurityAnalysisException.Type.LIMIT_REDUCTION_CONFIG_ERROR, "Not enough values provided for limit durations"); + throw new ComputationException(ComputationException.Type.LIMIT_REDUCTION_CONFIG_ERROR, "Not enough values provided for limit durations"); } values.forEach(valuesByVl -> { if (valuesByVl.stream().anyMatch(v -> !Range.of(0.0, 1.0).contains(v))) { - throw new SecurityAnalysisException(SecurityAnalysisException.Type.LIMIT_REDUCTION_CONFIG_ERROR, "Value not between 0 and 1"); + throw new ComputationException(ComputationException.Type.LIMIT_REDUCTION_CONFIG_ERROR, "Value not between 0 and 1"); } }); } diff --git a/src/main/java/org/gridsuite/securityanalysis/server/service/SecurityAnalysisParametersService.java b/src/main/java/org/gridsuite/securityanalysis/server/service/SecurityAnalysisParametersService.java index 0d21c11c..441d96c6 100644 --- a/src/main/java/org/gridsuite/securityanalysis/server/service/SecurityAnalysisParametersService.java +++ b/src/main/java/org/gridsuite/securityanalysis/server/service/SecurityAnalysisParametersService.java @@ -7,19 +7,19 @@ package org.gridsuite.securityanalysis.server.service; import com.powsybl.security.SecurityAnalysisParameters; +import com.powsybl.ws.commons.computation.ComputationException; import com.powsybl.ws.commons.computation.dto.ReportInfos; import lombok.NonNull; import org.gridsuite.securityanalysis.server.dto.*; import org.gridsuite.securityanalysis.server.entities.SecurityAnalysisParametersEntity; import org.gridsuite.securityanalysis.server.repositories.SecurityAnalysisParametersRepository; -import org.gridsuite.securityanalysis.server.util.SecurityAnalysisException; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.*; -import static org.gridsuite.securityanalysis.server.util.SecurityAnalysisException.Type.PARAMETERS_NOT_FOUND; +import static com.powsybl.ws.commons.computation.ComputationException.Type.PARAMETERS_NOT_FOUND; /** * @author Abdelsalem HEDHILI @@ -159,7 +159,7 @@ public Optional duplicateParameters(UUID sourceParametersUuid) { @Transactional public UUID updateParameters(UUID parametersUuid, SecurityAnalysisParametersValues parametersInfos) { - SecurityAnalysisParametersEntity securityAnalysisParametersEntity = securityAnalysisParametersRepository.findById(parametersUuid).orElseThrow(() -> new SecurityAnalysisException(PARAMETERS_NOT_FOUND)); + SecurityAnalysisParametersEntity securityAnalysisParametersEntity = securityAnalysisParametersRepository.findById(parametersUuid).orElseThrow(() -> new ComputationException(PARAMETERS_NOT_FOUND)); //if the parameters is null it means it's a reset to defaultValues, but we need to keep the provider because it's updated separately if (parametersInfos == null) { securityAnalysisParametersEntity.update(getDefaultSecurityAnalysisParametersValues(securityAnalysisParametersEntity.getProvider())); diff --git a/src/main/java/org/gridsuite/securityanalysis/server/service/SecurityAnalysisResultService.java b/src/main/java/org/gridsuite/securityanalysis/server/service/SecurityAnalysisResultService.java index 57a0049b..e90871a6 100644 --- a/src/main/java/org/gridsuite/securityanalysis/server/service/SecurityAnalysisResultService.java +++ b/src/main/java/org/gridsuite/securityanalysis/server/service/SecurityAnalysisResultService.java @@ -6,23 +6,23 @@ */ package org.gridsuite.securityanalysis.server.service; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import com.powsybl.iidm.network.Network; import com.powsybl.iidm.network.ThreeSides; import com.powsybl.security.LimitViolationType; import com.powsybl.security.SecurityAnalysisResult; +import com.powsybl.ws.commons.computation.ComputationException; +import com.powsybl.ws.commons.computation.dto.ResourceFilterDTO; import com.powsybl.ws.commons.computation.service.AbstractComputationResultService; +import com.powsybl.ws.commons.computation.utils.SpecificationUtils; +import lombok.Getter; import org.gridsuite.securityanalysis.server.dto.*; import org.gridsuite.securityanalysis.server.entities.*; import org.gridsuite.securityanalysis.server.repositories.*; import org.gridsuite.securityanalysis.server.repositories.specifications.ContingencySpecificationBuilder; import org.gridsuite.securityanalysis.server.repositories.specifications.PreContingencyLimitViolationSpecificationBuilder; -import org.gridsuite.securityanalysis.server.repositories.specifications.SpecificationUtils; import org.gridsuite.securityanalysis.server.repositories.specifications.SubjectLimitViolationSpecificationBuilder; import org.gridsuite.securityanalysis.server.util.CsvExportUtils; -import org.gridsuite.securityanalysis.server.util.SecurityAnalysisException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Lazy; @@ -35,6 +35,8 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; +import static com.powsybl.ws.commons.computation.utils.FilterUtils.fromStringFiltersToDTO; + /** * @author Geoffroy Jamgotchian */ @@ -49,8 +51,9 @@ public class SecurityAnalysisResultService extends AbstractComputationResultServ private final ContingencySpecificationBuilder contingencySpecificationBuilder; private final SubjectLimitViolationSpecificationBuilder subjectLimitViolationSpecificationBuilder; private final PreContingencyLimitViolationSpecificationBuilder preContingencyLimitViolationSpecificationBuilder; + @Getter private final ObjectMapper objectMapper; - private SecurityAnalysisResultService self; + private final SecurityAnalysisResultService self; private static final Sort.Direction DEFAULT_SORT_DIRECTION = Sort.Direction.ASC; @@ -139,7 +142,7 @@ public byte[] findNResultZippedCsv(UUID resultUuid, CsvTranslationDTO csvTransla public Page findNmKContingenciesPaged(UUID resultUuid, String stringFilters, Pageable pageable) { assertResultExists(resultUuid); - Page contingencyPageBis = self.findContingenciesPage(resultUuid, fromStringFiltersToDTO(stringFilters), pageable); + Page contingencyPageBis = self.findContingenciesPage(resultUuid, fromStringFiltersToDTO(stringFilters, objectMapper), pageable); return contingencyPageBis.map(ContingencyResultDTO::toDto); } @@ -168,7 +171,7 @@ public byte[] findNmKContingenciesResultZippedCsv(UUID resultUuid, CsvTranslatio public Page findNmKConstraintsResultPaged(UUID resultUuid, String stringFilters, Pageable pageable) { assertResultExists(resultUuid); - Page subjectLimitViolationsPage = self.findSubjectLimitViolationsPage(resultUuid, fromStringFiltersToDTO(stringFilters), pageable); + Page subjectLimitViolationsPage = self.findSubjectLimitViolationsPage(resultUuid, fromStringFiltersToDTO(stringFilters, objectMapper), pageable); return subjectLimitViolationsPage.map(SubjectLimitViolationResultDTO::toDto); } @@ -209,25 +212,13 @@ private void assertNmKSubjectLimitViolationsSortAllowed(Sort sort) { private void assertSortAllowed(Sort sort, List allowedSortProperties) { if (!sort.stream().allMatch(order -> allowedSortProperties.contains(order.getProperty()))) { - throw new SecurityAnalysisException(SecurityAnalysisException.Type.INVALID_SORT_FORMAT); - } - } - - public List fromStringFiltersToDTO(String stringFilters) { - if (stringFilters == null || stringFilters.isEmpty()) { - return List.of(); - } - try { - return objectMapper.readValue(stringFilters, new TypeReference<>() { - }); - } catch (JsonProcessingException e) { - throw new SecurityAnalysisException(SecurityAnalysisException.Type.INVALID_FILTER_FORMAT); + throw new ComputationException(ComputationException.Type.INVALID_SORT_FORMAT); } } public void assertResultExists(UUID resultUuid) { if (securityAnalysisResultRepository.findById(resultUuid).isEmpty()) { - throw new SecurityAnalysisException(SecurityAnalysisException.Type.RESULT_NOT_FOUND); + throw new ComputationException(ComputationException.Type.RESULT_NOT_FOUND); } } diff --git a/src/main/java/org/gridsuite/securityanalysis/server/util/CsvExportUtils.java b/src/main/java/org/gridsuite/securityanalysis/server/util/CsvExportUtils.java index 6b017cc9..3195629c 100644 --- a/src/main/java/org/gridsuite/securityanalysis/server/util/CsvExportUtils.java +++ b/src/main/java/org/gridsuite/securityanalysis/server/util/CsvExportUtils.java @@ -1,5 +1,6 @@ package org.gridsuite.securityanalysis.server.util; +import com.powsybl.ws.commons.computation.ComputationException; import com.univocity.parsers.csv.CsvFormat; import com.univocity.parsers.csv.CsvWriter; import com.univocity.parsers.csv.CsvWriterSettings; @@ -40,7 +41,7 @@ public static byte[] csvRowsToZippedCsv(List headers, List> csvWriter.close(); return outputStream.toByteArray(); } catch (IOException e) { - throw new SecurityAnalysisException(SecurityAnalysisException.Type.FILE_EXPORT_ERROR); + throw new ComputationException(ComputationException.Type.FILE_EXPORT_ERROR); } } diff --git a/src/main/java/org/gridsuite/securityanalysis/server/util/SecurityAnalysisException.java b/src/main/java/org/gridsuite/securityanalysis/server/util/SecurityAnalysisException.java deleted file mode 100644 index f8c758a1..00000000 --- a/src/main/java/org/gridsuite/securityanalysis/server/util/SecurityAnalysisException.java +++ /dev/null @@ -1,40 +0,0 @@ -/** - * 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.securityanalysis.server.util; - -import java.util.Objects; -/** - * @author Kevin Le Saulnier - */ - -public class SecurityAnalysisException extends RuntimeException { - public enum Type { - RESULT_NOT_FOUND, - INVALID_FILTER_FORMAT, - INVALID_SORT_FORMAT, - INVALID_FILTER, - PARAMETERS_NOT_FOUND, - FILE_EXPORT_ERROR, - LIMIT_REDUCTION_CONFIG_ERROR - } - - private final Type type; - - public SecurityAnalysisException(Type type) { - super(Objects.requireNonNull(type.name())); - this.type = type; - } - - public SecurityAnalysisException(Type type, String message) { - super(message); - this.type = type; - } - - public Type getType() { - return type; - } -} diff --git a/src/test/java/org/gridsuite/securityanalysis/server/FindContingenciesTest.java b/src/test/java/org/gridsuite/securityanalysis/server/FindContingenciesTest.java index 3f39125e..a731e519 100644 --- a/src/test/java/org/gridsuite/securityanalysis/server/FindContingenciesTest.java +++ b/src/test/java/org/gridsuite/securityanalysis/server/FindContingenciesTest.java @@ -11,8 +11,10 @@ import com.powsybl.iidm.network.test.EurostagTutorialExample1Factory; import com.powsybl.network.store.iidm.impl.NetworkFactoryImpl; import com.powsybl.security.LimitViolationType; +import com.powsybl.ws.commons.computation.dto.ResourceFilterDTO; +import com.powsybl.ws.commons.computation.ComputationException; +import com.powsybl.ws.commons.computation.utils.SpecificationUtils; import org.gridsuite.securityanalysis.server.dto.ContingencyResultDTO; -import org.gridsuite.securityanalysis.server.dto.ResourceFilterDTO; import org.gridsuite.securityanalysis.server.dto.SecurityAnalysisStatus; import org.gridsuite.securityanalysis.server.dto.SubjectLimitViolationDTO; import org.gridsuite.securityanalysis.server.entities.AbstractLimitViolationEntity; @@ -20,9 +22,7 @@ import org.gridsuite.securityanalysis.server.entities.SecurityAnalysisResultEntity; import org.gridsuite.securityanalysis.server.entities.SubjectLimitViolationEntity; import org.gridsuite.securityanalysis.server.repositories.SecurityAnalysisResultRepository; -import org.gridsuite.securityanalysis.server.repositories.specifications.SpecificationUtils; import org.gridsuite.securityanalysis.server.service.SecurityAnalysisResultService; -import org.gridsuite.securityanalysis.server.util.SecurityAnalysisException; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.TestInstance; @@ -253,8 +253,8 @@ private static Stream provideEdgeCasesFilters() { private static Stream provideForbiddenSort() { return Stream.of( - Arguments.of(List.of(), PageRequest.of(0, 30, Sort.by(Sort.Direction.ASC, "limitType")), new SecurityAnalysisException(SecurityAnalysisException.Type.INVALID_SORT_FORMAT)), - Arguments.of(List.of(), PageRequest.of(0, 30, Sort.by(Sort.Direction.DESC, "side")), new SecurityAnalysisException(SecurityAnalysisException.Type.INVALID_SORT_FORMAT)) + Arguments.of(List.of(), PageRequest.of(0, 30, Sort.by(Sort.Direction.ASC, "limitType")), new ComputationException(ComputationException.Type.INVALID_SORT_FORMAT)), + Arguments.of(List.of(), PageRequest.of(0, 30, Sort.by(Sort.Direction.DESC, "side")), new ComputationException(ComputationException.Type.INVALID_SORT_FORMAT)) ); } diff --git a/src/test/java/org/gridsuite/securityanalysis/server/FindPreContingencyLimitViolationTest.java b/src/test/java/org/gridsuite/securityanalysis/server/FindPreContingencyLimitViolationTest.java index e1140812..75b649ab 100644 --- a/src/test/java/org/gridsuite/securityanalysis/server/FindPreContingencyLimitViolationTest.java +++ b/src/test/java/org/gridsuite/securityanalysis/server/FindPreContingencyLimitViolationTest.java @@ -8,12 +8,13 @@ import com.powsybl.iidm.network.Network; import com.powsybl.iidm.network.ThreeSides; +import com.powsybl.ws.commons.computation.dto.ResourceFilterDTO; +import com.powsybl.ws.commons.computation.utils.SpecificationUtils; import com.powsybl.iidm.network.test.EurostagTutorialExample1Factory; import com.powsybl.network.store.iidm.impl.NetworkFactoryImpl; import org.gridsuite.securityanalysis.server.dto.*; import org.gridsuite.securityanalysis.server.entities.*; import org.gridsuite.securityanalysis.server.repositories.SecurityAnalysisResultRepository; -import org.gridsuite.securityanalysis.server.repositories.specifications.SpecificationUtils; import org.gridsuite.securityanalysis.server.service.SecurityAnalysisResultService; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; diff --git a/src/test/java/org/gridsuite/securityanalysis/server/FindSubjectLimitViolationsTest.java b/src/test/java/org/gridsuite/securityanalysis/server/FindSubjectLimitViolationsTest.java index ae9f903b..77bdc822 100644 --- a/src/test/java/org/gridsuite/securityanalysis/server/FindSubjectLimitViolationsTest.java +++ b/src/test/java/org/gridsuite/securityanalysis/server/FindSubjectLimitViolationsTest.java @@ -11,15 +11,15 @@ import com.powsybl.iidm.network.test.EurostagTutorialExample1Factory; import com.powsybl.network.store.iidm.impl.NetworkFactoryImpl; import com.powsybl.security.LimitViolationType; +import com.powsybl.ws.commons.computation.dto.ResourceFilterDTO; +import com.powsybl.ws.commons.computation.ComputationException; +import com.powsybl.ws.commons.computation.utils.SpecificationUtils; import org.gridsuite.securityanalysis.server.dto.ContingencyLimitViolationDTO; -import org.gridsuite.securityanalysis.server.dto.ResourceFilterDTO; import org.gridsuite.securityanalysis.server.dto.SecurityAnalysisStatus; import org.gridsuite.securityanalysis.server.dto.SubjectLimitViolationResultDTO; import org.gridsuite.securityanalysis.server.entities.*; import org.gridsuite.securityanalysis.server.repositories.SecurityAnalysisResultRepository; -import org.gridsuite.securityanalysis.server.repositories.specifications.SpecificationUtils; import org.gridsuite.securityanalysis.server.service.SecurityAnalysisResultService; -import org.gridsuite.securityanalysis.server.util.SecurityAnalysisException; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.TestInstance; @@ -216,8 +216,8 @@ private static Stream provideEachColumnFilter() { private static Stream provideForbiddenSort() { return Stream.of( - Arguments.of(List.of(), PageRequest.of(0, 30, Sort.by(Sort.Direction.ASC, "contingencyId")), new SecurityAnalysisException(SecurityAnalysisException.Type.INVALID_SORT_FORMAT)), - Arguments.of(List.of(), PageRequest.of(0, 30, Sort.by(Sort.Direction.DESC, "side")), new SecurityAnalysisException(SecurityAnalysisException.Type.INVALID_SORT_FORMAT)) + Arguments.of(List.of(), PageRequest.of(0, 30, Sort.by(Sort.Direction.ASC, "contingencyId")), new ComputationException(ComputationException.Type.INVALID_SORT_FORMAT)), + Arguments.of(List.of(), PageRequest.of(0, 30, Sort.by(Sort.Direction.DESC, "side")), new ComputationException(ComputationException.Type.INVALID_SORT_FORMAT)) ); } diff --git a/src/test/java/org/gridsuite/securityanalysis/server/SecurityAnalysisControllerTest.java b/src/test/java/org/gridsuite/securityanalysis/server/SecurityAnalysisControllerTest.java index c8c71deb..a3cb01bf 100644 --- a/src/test/java/org/gridsuite/securityanalysis/server/SecurityAnalysisControllerTest.java +++ b/src/test/java/org/gridsuite/securityanalysis/server/SecurityAnalysisControllerTest.java @@ -24,15 +24,16 @@ import com.powsybl.network.store.client.PreloadingStrategy; import com.powsybl.network.store.iidm.impl.NetworkFactoryImpl; import com.powsybl.security.*; +import com.powsybl.ws.commons.computation.dto.ResourceFilterDTO; import com.powsybl.ws.commons.computation.service.ReportService; import com.powsybl.ws.commons.computation.service.UuidGeneratorService; +import com.powsybl.ws.commons.computation.utils.SpecificationUtils; import com.vladmihalcea.sql.SQLStatementCountValidator; import org.assertj.core.api.Assertions; import org.gridsuite.securityanalysis.server.dto.*; import org.gridsuite.securityanalysis.server.entities.AbstractLimitViolationEntity; import org.gridsuite.securityanalysis.server.entities.SubjectLimitViolationEntity; import org.gridsuite.securityanalysis.server.repositories.SubjectLimitViolationRepository; -import org.gridsuite.securityanalysis.server.repositories.specifications.SpecificationUtils; import org.gridsuite.securityanalysis.server.service.ActionsService; import org.gridsuite.securityanalysis.server.service.LoadFlowService; import org.gridsuite.securityanalysis.server.service.SecurityAnalysisWorkerService; diff --git a/src/test/java/org/gridsuite/securityanalysis/server/SecurityAnalysisParametersControllerTest.java b/src/test/java/org/gridsuite/securityanalysis/server/SecurityAnalysisParametersControllerTest.java index 43c74d85..47253470 100644 --- a/src/test/java/org/gridsuite/securityanalysis/server/SecurityAnalysisParametersControllerTest.java +++ b/src/test/java/org/gridsuite/securityanalysis/server/SecurityAnalysisParametersControllerTest.java @@ -8,6 +8,7 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; +import com.powsybl.ws.commons.computation.ComputationException; import org.gridsuite.securityanalysis.server.dto.LimitReductionsByVoltageLevel; import org.gridsuite.securityanalysis.server.dto.SecurityAnalysisParametersValues; import org.gridsuite.securityanalysis.server.entities.SecurityAnalysisParametersEntity; @@ -16,7 +17,6 @@ import org.gridsuite.securityanalysis.server.service.SecurityAnalysisParametersService; import org.gridsuite.securityanalysis.server.util.ContextConfigurationWithTestChannel; import org.gridsuite.securityanalysis.server.util.MatcherJson; -import org.gridsuite.securityanalysis.server.util.SecurityAnalysisException; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -30,7 +30,7 @@ import java.util.UUID; import static com.powsybl.network.store.model.NetworkStoreApi.VERSION; -import static org.gridsuite.securityanalysis.server.util.SecurityAnalysisException.Type.PARAMETERS_NOT_FOUND; +import static com.powsybl.ws.commons.computation.ComputationException.Type.PARAMETERS_NOT_FOUND; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.jupiter.api.Assertions.*; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; @@ -71,37 +71,37 @@ void limitReductionConfigTest() { List vls = limitReductionService.getVoltageLevels(); limitReductionService.setVoltageLevels(List.of()); - assertEquals("No configuration for voltage levels", assertThrows(SecurityAnalysisException.class, () -> limitReductionService.createDefaultLimitReductions()).getMessage()); + assertEquals("No configuration for voltage levels", assertThrows(ComputationException.class, () -> limitReductionService.createDefaultLimitReductions()).getMessage()); limitReductionService.setVoltageLevels(vls); List lrs = limitReductionService.getLimitDurations(); limitReductionService.setLimitDurations(List.of()); - assertEquals("No configuration for limit durations", assertThrows(SecurityAnalysisException.class, () -> limitReductionService.createDefaultLimitReductions()).getMessage()); + assertEquals("No configuration for limit durations", assertThrows(ComputationException.class, () -> limitReductionService.createDefaultLimitReductions()).getMessage()); limitReductionService.setLimitDurations(lrs); limitReductionService.setDefaultValues(List.of()); - assertEquals("No values provided", assertThrows(SecurityAnalysisException.class, () -> limitReductionService.createDefaultLimitReductions()).getMessage()); + assertEquals("No values provided", assertThrows(ComputationException.class, () -> limitReductionService.createDefaultLimitReductions()).getMessage()); limitReductionService.setDefaultValues(List.of(List.of())); - assertEquals("No values provided", assertThrows(SecurityAnalysisException.class, () -> limitReductionService.createDefaultLimitReductions()).getMessage()); + assertEquals("No values provided", assertThrows(ComputationException.class, () -> limitReductionService.createDefaultLimitReductions()).getMessage()); limitReductionService.setDefaultValues(List.of(List.of(1.0))); - assertEquals("Not enough values provided for voltage levels", assertThrows(SecurityAnalysisException.class, () -> limitReductionService.createDefaultLimitReductions()).getMessage()); + assertEquals("Not enough values provided for voltage levels", assertThrows(ComputationException.class, () -> limitReductionService.createDefaultLimitReductions()).getMessage()); limitReductionService.setDefaultValues(List.of(List.of(1.0), List.of(1.0), List.of(1.0))); - assertEquals("Too many values provided for voltage levels", assertThrows(SecurityAnalysisException.class, () -> limitReductionService.createDefaultLimitReductions()).getMessage()); + assertEquals("Too many values provided for voltage levels", assertThrows(ComputationException.class, () -> limitReductionService.createDefaultLimitReductions()).getMessage()); limitReductionService.setDefaultValues(List.of(List.of(1.0), List.of(1.0))); - assertEquals("Not enough values provided for limit durations", assertThrows(SecurityAnalysisException.class, () -> limitReductionService.createDefaultLimitReductions()).getMessage()); + assertEquals("Not enough values provided for limit durations", assertThrows(ComputationException.class, () -> limitReductionService.createDefaultLimitReductions()).getMessage()); limitReductionService.setDefaultValues(List.of(List.of(1.0, 1.0, 1.0, 1.0, 1.0), List.of(1.0))); - assertEquals("Number of values for a voltage level is incorrect", assertThrows(SecurityAnalysisException.class, () -> limitReductionService.createDefaultLimitReductions()).getMessage()); + assertEquals("Number of values for a voltage level is incorrect", assertThrows(ComputationException.class, () -> limitReductionService.createDefaultLimitReductions()).getMessage()); limitReductionService.setDefaultValues(List.of(List.of(1.0, 1.0, 1.0, 1.0, 1.0), List.of(1.0, 1.0, 1.0, 1.0, 1.0))); - assertEquals("Too many values provided for limit durations", assertThrows(SecurityAnalysisException.class, () -> limitReductionService.createDefaultLimitReductions()).getMessage()); + assertEquals("Too many values provided for limit durations", assertThrows(ComputationException.class, () -> limitReductionService.createDefaultLimitReductions()).getMessage()); limitReductionService.setDefaultValues(List.of(List.of(2.0, 1.0, 1.0, 1.0), List.of(1.0, 1.0, 1.0, 1.0))); - assertEquals("Value not between 0 and 1", assertThrows(SecurityAnalysisException.class, () -> limitReductionService.createDefaultLimitReductions()).getMessage()); + assertEquals("Value not between 0 and 1", assertThrows(ComputationException.class, () -> limitReductionService.createDefaultLimitReductions()).getMessage()); } @Test