diff --git a/pom.xml b/pom.xml index 8d2f647f..332f8d9c 100644 --- a/pom.xml +++ b/pom.xml @@ -44,7 +44,7 @@ 43.1.0 - 1.9.0 + 1.11.0-SNAPSHOT 4.3.1 org.gridsuite.filter.server **/migrations/**/* @@ -88,8 +88,6 @@ - - org.gridsuite diff --git a/src/main/java/org/gridsuite/filter/server/FilterService.java b/src/main/java/org/gridsuite/filter/server/FilterService.java index 0dfebd86..8ec2e400 100644 --- a/src/main/java/org/gridsuite/filter/server/FilterService.java +++ b/src/main/java/org/gridsuite/filter/server/FilterService.java @@ -11,25 +11,20 @@ import com.powsybl.iidm.network.Network; import com.powsybl.network.store.client.NetworkStoreService; import com.powsybl.network.store.client.PreloadingStrategy; +import lombok.AllArgsConstructor; import org.apache.commons.collections4.CollectionUtils; import org.gridsuite.filter.AbstractFilter; import org.gridsuite.filter.FilterLoader; import org.gridsuite.filter.IFilterAttributes; import org.gridsuite.filter.expertfilter.ExpertFilter; import org.gridsuite.filter.identifierlistfilter.FilterEquipments; -import org.gridsuite.filter.identifierlistfilter.IdentifiableAttributes; 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.entities.AbstractFilterEntity; -import org.gridsuite.filter.server.repositories.FilterRepository; -import org.gridsuite.filter.server.repositories.expertfilter.ExpertFilterRepository; -import org.gridsuite.filter.server.repositories.identifierlistfilter.IdentifierListFilterRepository; import org.gridsuite.filter.server.repositories.proxies.AbstractFilterRepositoryProxy; -import org.gridsuite.filter.server.repositories.proxies.expertfiler.ExpertFilterRepositoryProxy; -import org.gridsuite.filter.server.repositories.proxies.identifierlistfilter.IdentifierListFilterRepositoryProxy; import org.gridsuite.filter.server.service.DirectoryService; import org.gridsuite.filter.server.utils.FilterWithEquipmentTypesUtils; import org.gridsuite.filter.utils.EquipmentType; @@ -52,43 +47,26 @@ */ @Service @ComponentScan(basePackageClasses = {NetworkStoreService.class}) +@AllArgsConstructor public class FilterService { private static final String FILTER_LIST = "Filter list "; private static final String NOT_FOUND = " not found"; public static final String FILTER_UUIDS_NOT_FOUND = "Some filter uuids have not bean found"; - private final Map> filterRepositories = new HashMap<>(); - + private final RepositoryService repositoriesService; private final NetworkStoreService networkStoreService; - private final NotificationService notificationService; - private final DirectoryService directoryService; - public FilterService(final IdentifierListFilterRepository identifierListFilterRepository, - final ExpertFilterRepository expertFilterRepository, - NetworkStoreService networkStoreService, - NotificationService notificationService, - DirectoryService directoryService) { - filterRepositories.put(FilterType.IDENTIFIER_LIST.name(), new IdentifierListFilterRepositoryProxy(identifierListFilterRepository)); - - filterRepositories.put(FilterType.EXPERT.name(), new ExpertFilterRepositoryProxy(expertFilterRepository)); - this.networkStoreService = networkStoreService; - this.notificationService = notificationService; - this.directoryService = directoryService; - } - public List getFilters() { - return filterRepositories.entrySet().stream() - .flatMap(entry -> entry.getValue().getFiltersAttributes()) - .collect(Collectors.toList()); + return this.repositoriesService.getFiltersAttributes() + .map(IFilterAttributes.class::cast) // cast because generics are invariants + .toList(); } public List getFiltersAttributes(List filterUuids, String userId) { - List filterAttributes = filterRepositories.entrySet().stream() - .flatMap(entry -> entry.getValue().getFiltersAttributes(filterUuids)) - .collect(Collectors.toList()); + List filterAttributes = this.repositoriesService.getFiltersAttributes(filterUuids).collect(Collectors.toList()); // call directory server to add name information Map elementsName = directoryService.getElementsName(filterAttributes.stream().map(FilterAttributes::getId).toList(), userId); filterAttributes.forEach(attribute -> attribute.setName(elementsName.get(attribute.getId()))); @@ -107,41 +85,21 @@ public List getFiltersAttributes(List filterUuids, Strin @Transactional(readOnly = true) public Optional getFilter(UUID id) { - return getFilterFromRepository(id); - } - - public Optional getFilterFromRepository(UUID id) { - Objects.requireNonNull(id); - for (AbstractFilterRepositoryProxy repository : filterRepositories.values()) { - Optional res = repository.getFilter(id); - if (res.isPresent()) { - return res; - } - } - return Optional.empty(); + return this.repositoriesService.getFilter(id); } @Transactional(readOnly = true) public List getFilters(List ids) { - return getFiltersFromRepositories(ids); - } - - private List getFiltersFromRepositories(List ids) { - Objects.requireNonNull(ids); - return filterRepositories.values() - .stream() - .flatMap(repository -> repository.getFilters(ids) - .stream()) - .toList(); + return this.repositoriesService.getFilters(ids); } @Transactional - public AbstractFilter createFilter(F filter) { + public AbstractFilter createFilter(AbstractFilter filter) { return doCreateFilter(filter); } - private AbstractFilter doCreateFilter(F filter) { - return getRepository(filter).insert(filter); + private AbstractFilter doCreateFilter(AbstractFilter filter) { + return this.repositoriesService.getRepositoryFromType(filter).insert(filter); } @Transactional @@ -151,7 +109,7 @@ public List createFilters(List filters) { } Map, List> repositoryFiltersMap = filters.stream() - .collect(Collectors.groupingBy(this::getRepository)); + .collect(Collectors.groupingBy(this.repositoriesService::getRepositoryFromType)); List createdFilters = new ArrayList<>(); repositoryFiltersMap.forEach((repository, subFilters) -> createdFilters.addAll(repository.insertAll(subFilters))); @@ -160,7 +118,7 @@ public List createFilters(List filters) { @Transactional public Optional duplicateFilter(UUID sourceFilterId) { - Optional sourceFilterOptional = getFilterFromRepository(sourceFilterId); + Optional sourceFilterOptional = this.repositoriesService.getFilter(sourceFilterId); if (sourceFilterOptional.isPresent()) { UUID newFilterId = UUID.randomUUID(); AbstractFilter sourceFilter = sourceFilterOptional.get(); @@ -178,7 +136,7 @@ public Optional duplicateFilter(UUID sourceFilterId) { public Map duplicateFilters(List filterUuids) { Map uuidsMap = new HashMap<>(); - List sourceFilters = getFiltersFromRepositories(filterUuids); + List sourceFilters = this.repositoriesService.getFilters(filterUuids); // check whether found all if (sourceFilters.isEmpty() || sourceFilters.size() != filterUuids.size()) { @@ -192,49 +150,45 @@ public Map duplicateFilters(List filterUuids) { }); Map, List> repositoryFiltersMap = sourceFilters.stream() - .collect(Collectors.groupingBy(this::getRepository)); + .collect(Collectors.groupingBy(this.repositoriesService::getRepositoryFromType)); repositoryFiltersMap.forEach(AbstractFilterRepositoryProxy::insertAll); return uuidsMap; } - private AbstractFilterRepositoryProxy> getRepository(AbstractFilter filter) { - return filterRepositories.get(filter.getType().name()); - } - @Transactional - public AbstractFilter updateFilter(UUID id, F newFilter, String userId) { + public AbstractFilter updateFilter(UUID id, AbstractFilter newFilter, String userId) { return doUpdateFilter(id, newFilter, userId); } - private AbstractFilter doUpdateFilter(UUID id, F newFilter, String userId) { - Optional filterOpt = getFilterFromRepository(id); - AbstractFilter modifiedOrCreatedFilter; + private AbstractFilter doUpdateFilter(UUID id, AbstractFilter newFilter, String userId) { + Optional filterOpt = this.repositoriesService.getFilter(id); if (filterOpt.isPresent()) { newFilter.setId(id); FilterLoader filterLoader = uuids -> uuids.stream() - .map(uuid -> uuid.equals(id) ? newFilter : getFilterFromRepository(uuid).orElse(null)) + .map(uuid -> uuid.equals(id) ? newFilter : this.repositoriesService.getFilter(uuid).orElse(null)) .toList(); FilterCycleDetector.checkNoCycle(newFilter, filterLoader); - if (getRepository(filterOpt.get()) == getRepository(newFilter)) { // filter type has not changed - modifiedOrCreatedFilter = getRepository(newFilter).modify(id, newFilter); + AbstractFilter modifiedOrCreatedFilter; + if (filterOpt.get().getType() == newFilter.getType()) { // filter type has not changed + modifiedOrCreatedFilter = this.repositoriesService.getRepositoryFromType(newFilter).modify(id, newFilter); } else { // filter type has changed - getRepository(filterOpt.get()).deleteById(id); + this.repositoriesService.getRepositoryFromType(filterOpt.get()).deleteById(id); + newFilter.setId(id); modifiedOrCreatedFilter = doCreateFilter(newFilter); } + + if (userId != null) { + notificationService.emitElementUpdated(id, userId); + } + + return modifiedOrCreatedFilter; } else { throw new ResponseStatusException(HttpStatus.NOT_FOUND, FILTER_LIST + id + NOT_FOUND); } - - if (userId != null) { - notificationService.emitElementUpdated(id, userId); - } - - return modifiedOrCreatedFilter; } @Transactional @@ -246,18 +200,18 @@ public List updateFilters(Map filtersToUpd public void deleteFilter(UUID id) { Objects.requireNonNull(id); - if (filterRepositories.values().stream().noneMatch(repository -> repository.deleteById(id))) { + if (!this.repositoriesService.deleteFilter(id)) { throw new ResponseStatusException(HttpStatus.NOT_FOUND, FILTER_LIST + id + NOT_FOUND); } } public void deleteFilters(List ids) { Objects.requireNonNull(ids); - filterRepositories.values().forEach(repository -> repository.deleteAllByIds(ids)); + this.repositoriesService.deleteFilters(ids); } public void deleteAll() { - filterRepositories.values().forEach(AbstractFilterRepositoryProxy::deleteAll); + this.repositoriesService.deleteAll(); } private Network getNetwork(UUID networkUuid, String variantId) { @@ -279,8 +233,7 @@ private List getIdentifiableAttributes(AbstractFilter fi @Transactional(readOnly = true) public List evaluateFilter(AbstractFilter filter, UUID networkUuid, String variantId) { Objects.requireNonNull(filter); - FilterLoader filterLoader = new FilterLoaderImpl(filterRepositories); - return getIdentifiableAttributes(filter, networkUuid, variantId, filterLoader); + return getIdentifiableAttributes(filter, networkUuid, variantId, this.repositoriesService.getFilterLoader()); } @Transactional(readOnly = true) @@ -288,11 +241,11 @@ public FilteredIdentifiables evaluateFiltersWithEquipmentTypes(FiltersWithEquipm Map result = new TreeMap<>(); Map notFound = new TreeMap<>(); Network network = getNetwork(networkUuid, variantId); - FilterLoader filterLoader = new FilterLoaderImpl(filterRepositories); + FilterLoader filterLoader = this.repositoriesService.getFilterLoader(); filtersWithEquipmentTypes.filters().forEach((FilterAttributes filterAttributes) -> { UUID filterUuid = filterAttributes.getId(); - Optional optFilter = getFilterFromRepository(filterUuid); + Optional optFilter = this.repositoriesService.getFilter(filterUuid); if (optFilter.isEmpty()) { return; } @@ -339,18 +292,18 @@ public FilteredIdentifiables evaluateFiltersWithEquipmentTypes(FiltersWithEquipm @Transactional(readOnly = true) public Optional> exportFilter(UUID id, UUID networkUuid, String variantId) { Objects.requireNonNull(id); - FilterLoader filterLoader = new FilterLoaderImpl(filterRepositories); - return getFilterFromRepository(id).map(filter -> getIdentifiableAttributes(filter, networkUuid, variantId, filterLoader)); + final FilterLoader filterLoader = this.repositoriesService.getFilterLoader(); + return this.repositoriesService.getFilter(id).map(filter -> getIdentifiableAttributes(filter, networkUuid, variantId, filterLoader)); } @Transactional(readOnly = true) public Map getIdentifiablesCountByGroup(IdsByGroup idsByGroup, UUID networkUuid, String variantId) { Objects.requireNonNull(idsByGroup); - FilterLoader filterLoader = new FilterLoaderImpl(filterRepositories); + final FilterLoader filterLoader = this.repositoriesService.getFilterLoader(); return idsByGroup.getIds().entrySet().stream() .collect(Collectors.toMap( Map.Entry::getKey, - entry -> getFiltersFromRepositories(entry.getValue()).stream() + entry -> this.repositoriesService.getFilters(entry.getValue()).stream() .mapToLong(f -> getIdentifiableAttributes(f, networkUuid, variantId, filterLoader).size()) .sum() ) @@ -360,14 +313,13 @@ public Map getIdentifiablesCountByGroup(IdsByGroup idsByGroup, UUI @Transactional(readOnly = true) public List exportFilters(List ids, UUID networkUuid, String variantId) { Network network = getNetwork(networkUuid, variantId); - FilterLoader filterLoader = new FilterLoaderImpl(filterRepositories); - return exportFilters(ids, network, Set.of(), filterLoader); + return exportFilters(ids, network, Set.of(), this.repositoriesService.getFilterLoader()); } public List exportFilters(List ids, Network network, Set filterTypesToExclude, FilterLoader filterLoader) { // we stream on the ids so that we can keep the same order of ids sent return ids.stream() - .map(id -> getFilterFromRepository(id).orElse(null)) + .map(id -> this.repositoriesService.getFilter(id).orElse(null)) .filter(filter -> filter != null && !filterTypesToExclude.contains(filter.getType())) .map(filter -> filter.toFilterEquipments(FilterServiceUtils.getIdentifiableAttributes(filter, network, filterLoader))) .toList(); diff --git a/src/main/java/org/gridsuite/filter/server/GlobalFilterController.java b/src/main/java/org/gridsuite/filter/server/GlobalFilterController.java new file mode 100644 index 00000000..1466f567 --- /dev/null +++ b/src/main/java/org/gridsuite/filter/server/GlobalFilterController.java @@ -0,0 +1,45 @@ +package org.gridsuite.filter.server; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.AllArgsConstructor; +import org.gridsuite.filter.globalfilter.GlobalFilter; +import org.gridsuite.filter.utils.EquipmentType; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.lang.NonNull; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.client.HttpClientErrorException; + +import java.util.List; +import java.util.UUID; + +@Validated +@RestController +@RequestMapping(value = "/" + FilterApi.API_VERSION + "/global-filter", + produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE) +@Tag(name = "GlobalFilter component controller") +@AllArgsConstructor +public class GlobalFilterController { + private final GlobalFilterService service; + + @PostMapping(value = "") + @Operation(summary = "Get network equipments IDs that match the filter(s)") + @ApiResponse(responseCode = "200", description = "The list of matching elements IDs") + @ApiResponse(responseCode = "400", description = "Invalid parameters") + @ApiResponse(responseCode = "404", description = "The filter does not exists") + public ResponseEntity> getResults( + @Parameter(description = "The network UUID") @RequestParam(name = "networkUuid") @NonNull final UUID networkUuid, + @Parameter(description = "The variant ID of the network") @RequestParam(name = "variantId") @NonNull final String variantId, + @Parameter(description = "The equipments types to filter and return") @RequestParam(name = "equipmentTypes") @NonNull final List equipmentTypes, + @Parameter(description = "The filter(s) to apply") @RequestBody @NonNull final GlobalFilter filterParams) { + if (filterParams.isEmpty()) { + throw HttpClientErrorException.create(HttpStatus.BAD_REQUEST, "At least one filter must be specified.", null, null, null); + } + return ResponseEntity.ok(service.getFilteredIds(networkUuid, variantId, filterParams, equipmentTypes)); + } +} diff --git a/src/main/java/org/gridsuite/filter/server/GlobalFilterService.java b/src/main/java/org/gridsuite/filter/server/GlobalFilterService.java new file mode 100644 index 00000000..3a926897 --- /dev/null +++ b/src/main/java/org/gridsuite/filter/server/GlobalFilterService.java @@ -0,0 +1,54 @@ +package org.gridsuite.filter.server; + +import com.powsybl.commons.PowsyblException; +import com.powsybl.iidm.network.Network; +import com.powsybl.network.store.client.NetworkStoreService; +import com.powsybl.network.store.client.PreloadingStrategy; +import lombok.AllArgsConstructor; +import lombok.NonNull; +import org.gridsuite.filter.AbstractFilter; +import org.gridsuite.filter.globalfilter.AbstractGlobalFilterService; +import org.gridsuite.filter.globalfilter.GlobalFilter; +import org.gridsuite.filter.utils.EquipmentType; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.server.ResponseStatusException; + +import java.util.List; +import java.util.UUID; + +@Service +@AllArgsConstructor +public class GlobalFilterService extends AbstractGlobalFilterService { + private final NetworkStoreService networkStoreService; + private final RepositoryService repositoriesService; + + /** {@inheritDoc} */ + @Override + protected Network getNetwork(@NonNull final UUID networkUuid, @NonNull final String variantId) { + try { + Network network = networkStoreService.getNetwork(networkUuid, PreloadingStrategy.COLLECTION); + network.getVariantManager().setWorkingVariant(variantId); + return network; + } catch (final PowsyblException ex) { + throw new ResponseStatusException(HttpStatus.NOT_FOUND, ex.getMessage()); + } + } + + /** {@inheritDoc} */ + @Override + @Transactional(readOnly = true) + public List getFilters(@NonNull final List filtersUuids) { + return this.repositoriesService.getFilters(filtersUuids); + } + + /* Expose it publicly */ + /** {@inheritDoc} */ + @Override + public List getFilteredIds(@NonNull final UUID networkUuid, @NonNull final String variantId, + @NonNull final GlobalFilter globalFilter, + @NonNull final List equipmentTypes) { + return super.getFilteredIds(networkUuid, variantId, globalFilter, equipmentTypes); + } +} diff --git a/src/main/java/org/gridsuite/filter/server/RepositoryService.java b/src/main/java/org/gridsuite/filter/server/RepositoryService.java new file mode 100644 index 00000000..1a31b13d --- /dev/null +++ b/src/main/java/org/gridsuite/filter/server/RepositoryService.java @@ -0,0 +1,98 @@ +package org.gridsuite.filter.server; + +import lombok.Getter; +import lombok.NonNull; +import org.apache.commons.collections4.ListUtils; +import org.gridsuite.filter.AbstractFilter; +import org.gridsuite.filter.FilterLoader; +import org.gridsuite.filter.server.dto.FilterAttributes; +import org.gridsuite.filter.server.repositories.expertfilter.ExpertFilterRepository; +import org.gridsuite.filter.server.repositories.identifierlistfilter.IdentifierListFilterRepository; +import org.gridsuite.filter.server.repositories.proxies.AbstractFilterRepositoryProxy; +import org.gridsuite.filter.server.repositories.proxies.expertfiler.ExpertFilterRepositoryProxy; +import org.gridsuite.filter.server.repositories.proxies.identifierlistfilter.IdentifierListFilterRepositoryProxy; +import org.gridsuite.filter.utils.FilterType; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; +import java.util.stream.Stream; + +/** + * More an utility service to call a methode on all {@link AbstractFilterRepositoryProxy repositories} + * and merge the result. + */ +@Service +public class RepositoryService { + private final IdentifierListFilterRepositoryProxy identifierListFilterProxy; + private final ExpertFilterRepositoryProxy expertFilterProxy; + @Getter private final FilterLoader filterLoader; + + public RepositoryService(final IdentifierListFilterRepository identifierListFilterRepository, + final ExpertFilterRepository expertFilterRepository) { + this.identifierListFilterProxy = new IdentifierListFilterRepositoryProxy(identifierListFilterRepository); + this.expertFilterProxy = new ExpertFilterRepositoryProxy(expertFilterRepository); + this.filterLoader = new FilterLoaderImpl(Map.of( + FilterType.IDENTIFIER_LIST.name(), this.identifierListFilterProxy, + FilterType.EXPERT.name(), this.expertFilterProxy + )); + } + + public AbstractFilterRepositoryProxy getRepositoryFromType(@NonNull final FilterType type) { + return switch (type) { + case IDENTIFIER_LIST -> identifierListFilterProxy; + case EXPERT -> expertFilterProxy; + }; + } + + public AbstractFilterRepositoryProxy getRepositoryFromType(@NonNull final AbstractFilter filter) { + return this.getRepositoryFromType(filter.getType()); + } + + /** @see AbstractFilterRepositoryProxy#deleteById(UUID) */ + public boolean deleteFilter(@NonNull final UUID id) { + return this.identifierListFilterProxy.deleteById(id) || this.expertFilterProxy.deleteById(id); + } + + /** @see AbstractFilterRepositoryProxy#deleteAllByIds(List) */ + public void deleteFilters(@NonNull final List ids) { + this.identifierListFilterProxy.deleteAllByIds(ids); + this.expertFilterProxy.deleteAllByIds(ids); + } + + /** @see AbstractFilterRepositoryProxy#deleteAll() */ + public void deleteAll() { + this.identifierListFilterProxy.deleteAll(); + this.expertFilterProxy.deleteAll(); + } + + /** @see AbstractFilterRepositoryProxy#getFiltersAttributes() */ + @Transactional(readOnly = true) + public Stream getFiltersAttributes() { + return Stream.concat(this.identifierListFilterProxy.getFiltersAttributes(), this.expertFilterProxy.getFiltersAttributes()); + } + + /** @see AbstractFilterRepositoryProxy#getFiltersAttributes(List) */ + @Transactional(readOnly = true) + public Stream getFiltersAttributes(@NonNull final List ids) { + return Stream.concat(this.identifierListFilterProxy.getFiltersAttributes(ids), this.expertFilterProxy.getFiltersAttributes(ids)); + } + + /** @see AbstractFilterRepositoryProxy#getFilters(List) */ + @Transactional(readOnly = true) + public List getFilters(@NonNull final List ids) { + return ListUtils.union( + this.identifierListFilterProxy.getFilters(ids), + this.expertFilterProxy.getFilters(ids) + ); + } + + /** @see AbstractFilterRepositoryProxy#getFilter(UUID) */ + @Transactional(readOnly = true) + public Optional getFilter(@NonNull final UUID id) { + return this.identifierListFilterProxy.getFilter(id).or(() -> this.expertFilterProxy.getFilter(id)); + } +} diff --git a/src/main/java/org/gridsuite/filter/server/repositories/FilterRepository.java b/src/main/java/org/gridsuite/filter/server/repositories/FilterRepository.java index c61549ec..923a8840 100644 --- a/src/main/java/org/gridsuite/filter/server/repositories/FilterRepository.java +++ b/src/main/java/org/gridsuite/filter/server/repositories/FilterRepository.java @@ -11,6 +11,7 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.NoRepositoryBean; +import org.springframework.lang.NonNull; import org.springframework.transaction.annotation.Transactional; import java.util.List; @@ -28,8 +29,14 @@ public interface FilterRepository extends JpaRep @Query(value = "SELECT t.id as id, t.modificationDate as modificationDate from #{#entityName} as t WHERE t.id in (:ids)") List findFiltersMetaDataById(List ids); + /** + * Remove a filter by id. + * @param id the filter id + * @return the number of filter(s) removed ({@code 0} or {@code 1}) + * @see #deleteById(Object) like deleteById(id) but with the indicator of either a filter has been removed or not + */ @Transactional - Integer removeById(UUID id); + long removeById(@NonNull UUID id); @Transactional void deleteAllByIdIn(List ids); diff --git a/src/main/java/org/gridsuite/filter/server/repositories/proxies/AbstractFilterRepositoryProxy.java b/src/main/java/org/gridsuite/filter/server/repositories/proxies/AbstractFilterRepositoryProxy.java index 36fafd74..53e89c1e 100644 --- a/src/main/java/org/gridsuite/filter/server/repositories/proxies/AbstractFilterRepositoryProxy.java +++ b/src/main/java/org/gridsuite/filter/server/repositories/proxies/AbstractFilterRepositoryProxy.java @@ -47,11 +47,7 @@ public static SortedSet setToSorterSet(Set set) { public abstract FilterType getFilterType(); - public abstract EquipmentType getEquipmentType(); - - public EquipmentType getEquipmentType(UUID id) { - return getEquipmentType(); - } + public abstract EquipmentType getEquipmentType(UUID id); public Optional getFilter(UUID id) { Optional element = getRepository().findById(id); @@ -76,7 +72,7 @@ public Stream getFiltersAttributes(List ids) { return getRepository().findFiltersMetaDataById(ids).stream().map(this::metadataToAttribute); } - FilterAttributes metadataToAttribute(FilterMetadata f) { + private FilterAttributes metadataToAttribute(final FilterMetadata f) { return new FilterAttributes(f, getFilterType(), getEquipmentType(f.getId())); } @@ -94,8 +90,13 @@ public AbstractFilter modify(UUID id, AbstractFilter f) { return toDto(getRepository().save(fromDto(f))); } + /** + * Delete a filter by its id. + * @param id the filter id + * @return true if the filter has been deleted, false otherwise + */ public boolean deleteById(UUID id) { - return getRepository().removeById(id) != 0; + return getRepository().removeById(id) > 0L; } public void deleteAllByIds(List ids) { @@ -106,7 +107,7 @@ public void deleteAll() { getRepository().deleteAll(); } - public void buildAbstractFilter(AbstractFilterEntity.AbstractFilterEntityBuilder builder, AbstractFilter dto) { + public static void buildAbstractFilter(AbstractFilterEntity.AbstractFilterEntityBuilder builder, AbstractFilter dto) { /* modification date is managed by jpa, so we don't process it */ builder.id(dto.getId()); } diff --git a/src/main/java/org/gridsuite/filter/server/repositories/proxies/expertfiler/ExpertFilterRepositoryProxy.java b/src/main/java/org/gridsuite/filter/server/repositories/proxies/expertfiler/ExpertFilterRepositoryProxy.java index 897ef7ca..ca8ddb01 100644 --- a/src/main/java/org/gridsuite/filter/server/repositories/proxies/expertfiler/ExpertFilterRepositoryProxy.java +++ b/src/main/java/org/gridsuite/filter/server/repositories/proxies/expertfiler/ExpertFilterRepositoryProxy.java @@ -244,11 +244,6 @@ public FilterType getFilterType() { return FilterType.EXPERT; } - @Override - public EquipmentType getEquipmentType() { - throw new UnsupportedOperationException("A filter id must be provided to get equipment type !!"); - } - @Override public EquipmentType getEquipmentType(UUID id) { return expertFilterRepository.findById(id) diff --git a/src/main/java/org/gridsuite/filter/server/repositories/proxies/identifierlistfilter/IdentifierListFilterRepositoryProxy.java b/src/main/java/org/gridsuite/filter/server/repositories/proxies/identifierlistfilter/IdentifierListFilterRepositoryProxy.java index 4596a2d1..54c3da07 100644 --- a/src/main/java/org/gridsuite/filter/server/repositories/proxies/identifierlistfilter/IdentifierListFilterRepositoryProxy.java +++ b/src/main/java/org/gridsuite/filter/server/repositories/proxies/identifierlistfilter/IdentifierListFilterRepositoryProxy.java @@ -75,11 +75,6 @@ public FilterType getFilterType() { return FilterType.IDENTIFIER_LIST; } - @Override - public EquipmentType getEquipmentType() { - throw new UnsupportedOperationException("A filter id must be provided to get equipment type !!"); - } - @Override public EquipmentType getEquipmentType(UUID id) { return identifierListFilterRepository.findById(id) diff --git a/src/test/java/org/gridsuite/filter/server/GlobalFilterControllerTest.java b/src/test/java/org/gridsuite/filter/server/GlobalFilterControllerTest.java new file mode 100644 index 00000000..42d6958e --- /dev/null +++ b/src/test/java/org/gridsuite/filter/server/GlobalFilterControllerTest.java @@ -0,0 +1,136 @@ +/** + * Copyright (c) 2021, 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.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.jayway.jsonpath.Configuration; +import com.jayway.jsonpath.Option; +import com.jayway.jsonpath.spi.json.JacksonJsonProvider; +import com.jayway.jsonpath.spi.json.JsonProvider; +import com.jayway.jsonpath.spi.mapper.JacksonMappingProvider; +import com.jayway.jsonpath.spi.mapper.MappingProvider; +import com.powsybl.iidm.network.Country; +import com.powsybl.iidm.network.Network; +import com.powsybl.iidm.network.test.EurostagTutorialExample1Factory; +import com.powsybl.network.store.client.NetworkStoreService; +import com.powsybl.network.store.client.PreloadingStrategy; +import com.powsybl.network.store.iidm.impl.NetworkFactoryImpl; +import org.gridsuite.filter.globalfilter.GlobalFilter; +import org.gridsuite.filter.utils.EquipmentType; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.cloud.stream.binder.test.TestChannelBinderConfiguration; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; + +import java.util.EnumSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + +import static com.powsybl.iidm.network.VariantManagerConstants.INITIAL_VARIANT_ID; +import static org.mockito.BDDMockito.given; +import static org.springframework.http.MediaType.APPLICATION_JSON; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +/** + * @author Franck Lecuyer + */ +@RunWith(SpringRunner.class) +@SpringBootTest +@AutoConfigureMockMvc +@ContextConfiguration(classes = {FilterApplication.class, TestChannelBinderConfiguration.class}) +public class GlobalFilterControllerTest { + public static final String URL_TEMPLATE = "/" + FilterApi.API_VERSION + "/global-filter"; + + @Autowired + private MockMvc mvc; + + @Autowired + ObjectMapper objectMapper = new ObjectMapper(); + + @MockBean + private NetworkStoreService networkStoreService; + + private static final UUID NETWORK_UUID = UUID.fromString("7928181c-7977-4592-ba19-88027e4254e4"); + + @Before + public void setUp() { + Configuration.defaultConfiguration(); + final ObjectMapper mapper = new ObjectMapper(); + mapper.enable(DeserializationFeature.USE_LONG_FOR_INTS); + mapper.enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS); + mapper.disable(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE); + + Network network = EurostagTutorialExample1Factory.createWithMoreGenerators(new NetworkFactoryImpl()); + network.getSubstation("P1").setProperty("region", "north"); + network.getSubstation("P1").setName("P1"); + network.getSubstation("P2").setProperty("region", "south"); + network.getGenerator("GEN").setProperty("region", "north"); + network.getGenerator("GEN").setName("GEN"); + network.getGenerator("GEN2").setProperty("region", "south"); + network.getLoad("LOAD").setProperty("region", "north"); + network.getVoltageLevel("VLGEN").setName("VLGEN"); + given(networkStoreService.getNetwork(NETWORK_UUID, PreloadingStrategy.COLLECTION)).willReturn(network); + + Configuration.setDefaults(new Configuration.Defaults() { + + private final JsonProvider jsonProvider = new JacksonJsonProvider(mapper); + private final MappingProvider mappingProvider = new JacksonMappingProvider(mapper); + + @Override + public JsonProvider jsonProvider() { + return jsonProvider; + } + + @Override + public MappingProvider mappingProvider() { + return mappingProvider; + } + + @Override + public Set