Code development platform for open source projects from the European Union institutions

Skip to content
Snippets Groups Projects

In-memory sorting of roles returned by RoleService#search

Merged Jean Claude Correale requested to merge feature/fix-roles-search-sorting into develop
1 file
+ 56
0
Compare changes
  • Side-by-side
  • Inline
@@ -14,17 +14,25 @@ import eu.europa.ec.simpl.usersroles.services.KeycloakUserService;
import eu.europa.ec.simpl.usersroles.services.RoleService;
import jakarta.ws.rs.ClientErrorException;
import jakarta.ws.rs.NotFoundException;
import java.beans.PropertyDescriptor;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.UUID;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import lombok.SneakyThrows;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.keycloak.representations.idm.RoleRepresentation;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -203,6 +211,7 @@ public class RoleServiceImpl implements RoleService {
var filteredRoles = roleList.stream()
.map(role -> roleMapper.toDto(role, getEnabledAttrs(role)))
.filter(roleDTO -> shouldMatchFilter(roleDTO, request))
.sorted(toComparator(pageable.getSort()))
.skip(pageable.getOffset())
.limit(pageable.getPageSize())
.toList();
@@ -215,6 +224,53 @@ public class RoleServiceImpl implements RoleService {
return new PageImpl<>(filteredRoles, pageable, totalElements);
}
private Comparator<? super RoleDTO> toComparator(Sort sort) {
return sort.stream()
.flatMap(this::toComparator)
.reduce(Comparator::thenComparing)
.orElse(unsortedComparator());
}
private Stream<Comparator<RoleDTO>> toComparator(Sort.Order order) {
try {
return Optional.ofNullable(getPropertyDescriptor(order))
.flatMap(property -> toComparator(property, order.getDirection()))
.stream();
} catch (BeansException e) {
return Stream.empty();
}
}
private static PropertyDescriptor getPropertyDescriptor(Sort.Order order) {
return BeanUtils.getPropertyDescriptor(RoleDTO.class, order.getProperty());
}
private static Optional<Comparator<RoleDTO>> toComparator(PropertyDescriptor property, Sort.Direction direction) {
if (Comparable.class.isAssignableFrom(property.getPropertyType())) {
return Optional.of(buildComparator(property, direction));
} else {
return Optional.empty();
}
}
private static Comparator<RoleDTO> buildComparator(PropertyDescriptor property, Sort.Direction direction) {
var comparator = Comparator.<RoleDTO, Comparable<Object>>comparing(o -> get(o, property));
if (direction == Sort.Direction.DESC) {
comparator = comparator.reversed();
}
return comparator;
}
private static Comparator<RoleDTO> unsortedComparator() {
return (o1, o2) -> 0;
}
@SneakyThrows
@SuppressWarnings("unchecked")
private static Comparable<Object> get(RoleDTO o, PropertyDescriptor property) {
return (Comparable<Object>) property.getReadMethod().invoke(o);
}
@Override
public void importRoles(List<KeycloakRoleDTO> roles) {
keycloakService.importRoles(roles);
Loading