@@ -17,6 +17,7 @@ package org.springframework.data.ldap.repository.support;
|
||||
|
||||
import static org.springframework.data.querydsl.QuerydslUtils.*;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Optional;
|
||||
|
||||
@@ -115,7 +116,15 @@ public class LdapRepositoryFactory extends RepositoryFactorySupport {
|
||||
*/
|
||||
@Override
|
||||
protected Object getTargetRepository(RepositoryInformation information) {
|
||||
return getTargetRepositoryViaReflection(information, ldapOperations, mappingContext,
|
||||
|
||||
boolean acceptsMappingContext = acceptsMappingContext(information);
|
||||
|
||||
if (acceptsMappingContext) {
|
||||
return getTargetRepositoryViaReflection(information, ldapOperations, mappingContext,
|
||||
ldapOperations.getObjectDirectoryMapper(), information.getDomainType());
|
||||
}
|
||||
|
||||
return getTargetRepositoryViaReflection(information, ldapOperations,
|
||||
ldapOperations.getObjectDirectoryMapper(),
|
||||
information.getDomainType());
|
||||
}
|
||||
@@ -130,9 +139,35 @@ public class LdapRepositoryFactory extends RepositoryFactorySupport {
|
||||
return Optional.of(queryLookupStrategy);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow creation of repository base classes that do not accept a {@link LdapMappingContext} that was introduced with
|
||||
* version 2.6.
|
||||
*
|
||||
* @param information
|
||||
* @return
|
||||
*/
|
||||
private static boolean acceptsMappingContext(RepositoryInformation information) {
|
||||
|
||||
Class<?> repositoryBaseClass = information.getRepositoryBaseClass();
|
||||
|
||||
Constructor<?>[] declaredConstructors = repositoryBaseClass.getDeclaredConstructors();
|
||||
|
||||
boolean acceptsMappingContext = false;
|
||||
|
||||
for (Constructor<?> declaredConstructor : declaredConstructors) {
|
||||
Class<?>[] parameterTypes = declaredConstructor.getParameterTypes();
|
||||
|
||||
if (parameterTypes.length == 4 && parameterTypes[1].isAssignableFrom(LdapMappingContext.class)) {
|
||||
acceptsMappingContext = true;
|
||||
}
|
||||
}
|
||||
|
||||
return acceptsMappingContext;
|
||||
}
|
||||
|
||||
private static final class LdapQueryLookupStrategy implements QueryLookupStrategy {
|
||||
|
||||
private LdapOperations ldapOperations;
|
||||
private final LdapOperations ldapOperations;
|
||||
|
||||
/**
|
||||
* @param ldapOperations must not be {@literal null}.
|
||||
|
||||
@@ -30,7 +30,6 @@ import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.dao.EmptyResultDataAccessException;
|
||||
import org.springframework.dao.IncorrectResultSizeDataAccessException;
|
||||
import org.springframework.data.domain.Example;
|
||||
import org.springframework.data.domain.Page;
|
||||
@@ -46,6 +45,7 @@ import org.springframework.data.projection.ProjectionInformation;
|
||||
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
|
||||
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
|
||||
import org.springframework.data.repository.query.FluentQuery;
|
||||
import org.springframework.data.support.PageableExecutionUtils;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.ldap.core.LdapOperations;
|
||||
import org.springframework.ldap.odm.core.ObjectDirectoryMapper;
|
||||
@@ -139,29 +139,40 @@ public class QuerydslLdapRepository<T> extends SimpleLdapRepository<T>
|
||||
*/
|
||||
@Override
|
||||
public long count(Predicate predicate) {
|
||||
return findAll(predicate).size();
|
||||
return findBy(predicate, FluentQuery.FetchableFluentQuery::count);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.querydsl.QueryDslPredicateExecutor#exists(com.querydsl.core.types.Predicate)
|
||||
*/
|
||||
public boolean exists(Predicate predicate) {
|
||||
return count(predicate) > 0;
|
||||
return findBy(predicate, FluentQuery.FetchableFluentQuery::exists);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.querydsl.QueryDslPredicateExecutor#findAll(com.querydsl.core.types.Predicate, org.springframework.data.domain.Sort)
|
||||
*/
|
||||
public Iterable<T> findAll(Predicate predicate, Sort sort) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
Assert.notNull(sort, "Pageable must not be null!");
|
||||
|
||||
if (sort.isUnsorted()) {
|
||||
return findAll(predicate);
|
||||
}
|
||||
|
||||
throw new UnsupportedOperationException("Sorting is not supported");
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.querydsl.QueryDslPredicateExecutor#findAll(com.querydsl.core.types.OrderSpecifier[])
|
||||
*/
|
||||
public Iterable<T> findAll(OrderSpecifier<?>... orders) {
|
||||
throw new UnsupportedOperationException();
|
||||
|
||||
if (orders.length == 0) {
|
||||
return findAll();
|
||||
}
|
||||
|
||||
throw new UnsupportedOperationException("Sorting is not supported");
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
@@ -169,7 +180,12 @@ public class QuerydslLdapRepository<T> extends SimpleLdapRepository<T>
|
||||
*/
|
||||
@Override
|
||||
public Iterable<T> findAll(Predicate predicate, OrderSpecifier<?>... orders) {
|
||||
throw new UnsupportedOperationException();
|
||||
|
||||
if (orders.length == 0) {
|
||||
return findAll(predicate);
|
||||
}
|
||||
|
||||
throw new UnsupportedOperationException("Sorting is not supported");
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
@@ -177,7 +193,20 @@ public class QuerydslLdapRepository<T> extends SimpleLdapRepository<T>
|
||||
*/
|
||||
@Override
|
||||
public Page<T> findAll(Predicate predicate, Pageable pageable) {
|
||||
throw new UnsupportedOperationException();
|
||||
|
||||
Assert.notNull(pageable, "Pageable must not be null!");
|
||||
|
||||
if (pageable.isUnpaged()) {
|
||||
return PageableExecutionUtils.getPage(findAll(predicate), pageable, () -> count(predicate));
|
||||
}
|
||||
|
||||
if (pageable.getSort().isUnsorted() && pageable.getPageNumber() == 0) {
|
||||
|
||||
return PageableExecutionUtils.getPage(queryFor(predicate, q -> q.countLimit(pageable.getPageSize())).list(),
|
||||
pageable, () -> count(predicate));
|
||||
}
|
||||
|
||||
throw new UnsupportedOperationException("Pagination and Sorting is not supported");
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -189,7 +218,6 @@ public class QuerydslLdapRepository<T> extends SimpleLdapRepository<T>
|
||||
public <S extends T, R> R findBy(Predicate predicate,
|
||||
Function<FluentQuery.FetchableFluentQuery<S>, R> queryFunction) {
|
||||
|
||||
Assert.notNull(predicate, "Predicate must not be null!");
|
||||
Assert.notNull(queryFunction, "Query function must not be null!");
|
||||
|
||||
return queryFunction.apply(new FluentQuerydsl<>(predicate, (Class<S>) entityType));
|
||||
@@ -202,6 +230,9 @@ public class QuerydslLdapRepository<T> extends SimpleLdapRepository<T>
|
||||
}
|
||||
|
||||
private QuerydslLdapQuery<T> queryFor(Predicate predicate, Consumer<LdapQueryBuilder> queryBuilderConsumer) {
|
||||
|
||||
Assert.notNull(predicate, "Predicate must not be null!");
|
||||
|
||||
return new QuerydslLdapQuery<>(ldapOperations, entityType, queryBuilderConsumer).where(predicate);
|
||||
}
|
||||
|
||||
@@ -281,7 +312,7 @@ public class QuerydslLdapRepository<T> extends SimpleLdapRepository<T>
|
||||
}
|
||||
|
||||
T one = results.get(0);
|
||||
return getConversionFunction(entityType, resultType).apply(one);
|
||||
return getConversionFunction().apply(one);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -299,9 +330,10 @@ public class QuerydslLdapRepository<T> extends SimpleLdapRepository<T>
|
||||
}
|
||||
|
||||
T one = results.get(0);
|
||||
return getConversionFunction(entityType, resultType).apply(one);
|
||||
return getConversionFunction().apply(one);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery#all()
|
||||
@@ -319,7 +351,21 @@ public class QuerydslLdapRepository<T> extends SimpleLdapRepository<T>
|
||||
public Page<R> page(Pageable pageable) {
|
||||
|
||||
Assert.notNull(pageable, "Pageable must not be null!");
|
||||
throw new UnsupportedOperationException();
|
||||
|
||||
if (pageable.isUnpaged()) {
|
||||
return PageableExecutionUtils.getPage(all(), pageable, this::count);
|
||||
}
|
||||
|
||||
if (pageable.getSort().isUnsorted() && pageable.getPageNumber() == 0) {
|
||||
|
||||
Function<Object, R> conversionFunction = getConversionFunction();
|
||||
|
||||
return PageableExecutionUtils.getPage(
|
||||
findTop(pageable.getPageSize()).stream().map(conversionFunction).collect(Collectors.toList()), pageable,
|
||||
this::count);
|
||||
}
|
||||
|
||||
throw new UnsupportedOperationException("Pagination and Sorting is not supported");
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -329,7 +375,7 @@ public class QuerydslLdapRepository<T> extends SimpleLdapRepository<T>
|
||||
@Override
|
||||
public Stream<R> stream() {
|
||||
|
||||
Function<Object, R> conversionFunction = getConversionFunction(entityType, resultType);
|
||||
Function<Object, R> conversionFunction = getConversionFunction();
|
||||
|
||||
return search(null, QuerydslLdapQuery::list).stream().map(conversionFunction);
|
||||
}
|
||||
@@ -390,6 +436,10 @@ public class QuerydslLdapRepository<T> extends SimpleLdapRepository<T>
|
||||
return o -> (P) converter.convert(o);
|
||||
}
|
||||
|
||||
private Function<Object, R> getConversionFunction() {
|
||||
return getConversionFunction(entityType, resultType);
|
||||
}
|
||||
|
||||
private List<String> getProjection() {
|
||||
|
||||
if (projection.isEmpty()) {
|
||||
@@ -410,5 +460,7 @@ public class QuerydslLdapRepository<T> extends SimpleLdapRepository<T>
|
||||
|
||||
return projection;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -35,6 +35,9 @@ import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoSettings;
|
||||
|
||||
import org.springframework.dao.IncorrectResultSizeDataAccessException;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.repository.query.FluentQuery;
|
||||
import org.springframework.ldap.core.ContextMapper;
|
||||
import org.springframework.ldap.core.LdapOperations;
|
||||
@@ -166,6 +169,43 @@ class QuerydslLdapRepositoryUnitTests {
|
||||
assertThat(all).hasOnlyElementsOfType(PersonProjection.class);
|
||||
}
|
||||
|
||||
@Test // GH-269
|
||||
void findByShouldReturnFirstPage() {
|
||||
|
||||
when(ldapOperations.find(any(LdapQuery.class), eq(UnitTestPerson.class)))
|
||||
.thenReturn(Collections.singletonList(walter));
|
||||
when(ldapOperations.search(any(LdapQuery.class), any(ContextMapper.class))).thenReturn(Arrays.asList(true, true));
|
||||
|
||||
Page<PersonProjection> page = repository.findBy(QPerson.person.fullName.eq("Walter"),
|
||||
it -> it.as(PersonProjection.class).page(PageRequest.of(0, 1, Sort.unsorted())));
|
||||
assertThat(page.getContent().get(0).getLastName()).isEqualTo("White");
|
||||
assertThat(page.getTotalPages()).isEqualTo(2);
|
||||
|
||||
ArgumentCaptor<LdapQuery> captor = ArgumentCaptor.forClass(LdapQuery.class);
|
||||
|
||||
verify(ldapOperations).find(captor.capture(), any());
|
||||
|
||||
LdapQuery query = captor.getValue();
|
||||
|
||||
assertThat(query.countLimit()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test // GH-269
|
||||
void shouldRejectNextPage() {
|
||||
|
||||
assertThatExceptionOfType(UnsupportedOperationException.class)
|
||||
.isThrownBy(() -> repository.findBy(QPerson.person.fullName.eq("Walter"),
|
||||
it -> it.as(PersonProjection.class).page(PageRequest.of(1, 1, Sort.unsorted()))));
|
||||
}
|
||||
|
||||
@Test // GH-269
|
||||
void shouldRejectSortedPage() {
|
||||
|
||||
assertThatExceptionOfType(UnsupportedOperationException.class)
|
||||
.isThrownBy(() -> repository.findBy(QPerson.person.fullName.eq("Walter"),
|
||||
it -> it.as(PersonProjection.class).page(PageRequest.of(0, 1, Sort.by(Sort.Direction.ASC, "foo")))));
|
||||
}
|
||||
|
||||
@Test // GH-269
|
||||
void findByShouldReturnStream() {
|
||||
|
||||
@@ -191,7 +231,7 @@ class QuerydslLdapRepositoryUnitTests {
|
||||
@Test // GH-269
|
||||
void findByShouldReturnCount() {
|
||||
|
||||
when(ldapOperations.find(any(LdapQuery.class), eq(UnitTestPerson.class))).thenReturn(Arrays.asList(walter, hank));
|
||||
when(ldapOperations.search(any(LdapQuery.class), any(ContextMapper.class))).thenReturn(Arrays.asList(true, true));
|
||||
|
||||
long count = repository.findBy(QPerson.person.fullName.eq("Walter"), FluentQuery.FetchableFluentQuery::count);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user