Allow configuration of QueryEngine for Map repositories.
EnableMapRepositories now accepts a QueryEngineFactory to configure the QueryEngine and allows configuring the QueryCreator. Closes: #576 Original Pull Request: #577
This commit is contained in:
committed by
Christoph Strobl
parent
c355374234
commit
008e1e2dd8
@@ -19,8 +19,11 @@ import static org.assertj.core.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.Iterator;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentSkipListMap;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.assertj.core.api.InstanceOfAssertFactories;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -32,12 +35,24 @@ import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.FilterType;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.keyvalue.core.KeyValueAdapter;
|
||||
import org.springframework.data.keyvalue.core.KeyValueOperations;
|
||||
import org.springframework.data.keyvalue.core.KeyValueTemplate;
|
||||
import org.springframework.data.keyvalue.core.PathSortAccessor;
|
||||
import org.springframework.data.keyvalue.core.QueryEngine;
|
||||
import org.springframework.data.keyvalue.core.QueryEngineFactory;
|
||||
import org.springframework.data.keyvalue.core.SortAccessor;
|
||||
import org.springframework.data.keyvalue.core.SpelQueryEngine;
|
||||
import org.springframework.data.keyvalue.core.query.KeyValueQuery;
|
||||
import org.springframework.data.keyvalue.repository.KeyValueRepository;
|
||||
import org.springframework.data.keyvalue.repository.query.PredicateQueryCreator;
|
||||
import org.springframework.data.keyvalue.repository.support.KeyValueRepositoryFactoryBean;
|
||||
import org.springframework.data.map.MapKeyValueAdapter;
|
||||
import org.springframework.data.repository.query.ParameterAccessor;
|
||||
import org.springframework.data.repository.query.parser.AbstractQueryCreator;
|
||||
import org.springframework.data.repository.query.parser.Part;
|
||||
import org.springframework.data.repository.query.parser.PartTree;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
/**
|
||||
@@ -78,7 +93,8 @@ class MapRepositoriesConfigurationExtensionIntegrationTests {
|
||||
|
||||
PersonRepository repository = context.getBean(PersonRepository.class);
|
||||
|
||||
assertThatThrownBy(() -> repository.findById("foo")).hasRootCauseInstanceOf(IllegalStateException.class).hasMessageContaining("Mock");
|
||||
assertThatThrownBy(() -> repository.findById("foo")).hasRootCauseInstanceOf(IllegalStateException.class)
|
||||
.hasMessageContaining("Mock");
|
||||
|
||||
context.close();
|
||||
}
|
||||
@@ -101,6 +117,41 @@ class MapRepositoriesConfigurationExtensionIntegrationTests {
|
||||
new AnnotationConfigApplicationContext(ConfigWithCustomizedSortAccessor.class));
|
||||
}
|
||||
|
||||
@Test // GH-576
|
||||
void considersQueryEngineConfiguration() {
|
||||
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConfigWithQueryEngine.class);
|
||||
|
||||
KeyValueTemplate template = context.getBean(KeyValueTemplate.class);
|
||||
Object adapter = ReflectionTestUtils.getField(template, "adapter");
|
||||
|
||||
assertThat(adapter).isInstanceOf(MapKeyValueAdapter.class);
|
||||
|
||||
Object engine = ReflectionTestUtils.getField(adapter, "engine");
|
||||
|
||||
assertThat(engine).isInstanceOf(SpelQueryEngine.class);
|
||||
}
|
||||
|
||||
@Test // GH-576
|
||||
void considersQueryEngineAndSortAccessorConfiguration() {
|
||||
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
|
||||
ConfigWithQueryEngineAndCustomizedSortAccessor.class);
|
||||
|
||||
KeyValueTemplate template = context.getBean(KeyValueTemplate.class);
|
||||
Object adapter = ReflectionTestUtils.getField(template, "adapter");
|
||||
|
||||
assertThat(adapter).isInstanceOf(MapKeyValueAdapter.class);
|
||||
|
||||
Object engine = ReflectionTestUtils.getField(adapter, "engine");
|
||||
|
||||
assertThat(engine).isInstanceOf(SpelQueryEngine.class);
|
||||
Object sortAccessor = ReflectionTestUtils.getField(engine, "sortAccessor");
|
||||
|
||||
assertThat(sortAccessor).asInstanceOf(InstanceOfAssertFactories.OPTIONAL)
|
||||
.containsInstanceOf(PathSortAccessor.class);
|
||||
}
|
||||
|
||||
private static void assertKeyValueTemplateWithAdapterFor(Class<?> mapType, ApplicationContext context) {
|
||||
|
||||
KeyValueTemplate template = context.getBean(KeyValueTemplate.class);
|
||||
@@ -123,8 +174,32 @@ class MapRepositoriesConfigurationExtensionIntegrationTests {
|
||||
assertThat(sortAccessor).asInstanceOf(InstanceOfAssertFactories.OPTIONAL).containsInstanceOf(sortAccessorType);
|
||||
}
|
||||
|
||||
@Test // GH-576
|
||||
void considersDefaultQueryCreator() {
|
||||
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
|
||||
|
||||
KeyValueRepositoryFactoryBean<?, ?, ?> factoryBean = context.getBean(KeyValueRepositoryFactoryBean.class);
|
||||
Object queryCreator = ReflectionTestUtils.getField(factoryBean, "queryCreator");
|
||||
|
||||
assertThat(queryCreator).isEqualTo(PredicateQueryCreator.class);
|
||||
}
|
||||
|
||||
@Test // GH-576
|
||||
void considersCustomQueryCreator() {
|
||||
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
|
||||
ConfigWithCustomQueryCreator.class);
|
||||
|
||||
KeyValueRepositoryFactoryBean<?, ?, ?> factoryBean = context.getBean(KeyValueRepositoryFactoryBean.class);
|
||||
Object queryCreator = ReflectionTestUtils.getField(factoryBean, "queryCreator");
|
||||
|
||||
assertThat(queryCreator).isEqualTo(MyQueryCreator.class);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableMapRepositories
|
||||
@EnableMapRepositories(considerNestedRepositories = true,
|
||||
includeFilters = @ComponentScan.Filter(value = PersonRepository.class, type = FilterType.ASSIGNABLE_TYPE))
|
||||
static class Config {}
|
||||
|
||||
@Configuration
|
||||
@@ -167,9 +242,74 @@ class MapRepositoriesConfigurationExtensionIntegrationTests {
|
||||
}
|
||||
}
|
||||
|
||||
@EnableMapRepositories(queryEngineFactory = JustSpelQueryEngineFactory.class)
|
||||
static class ConfigWithQueryEngine {}
|
||||
|
||||
static class JustSpelQueryEngineFactory implements QueryEngineFactory {
|
||||
|
||||
@Override
|
||||
public QueryEngine<?, ?, ?> create() {
|
||||
return new SpelQueryEngine();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EnableMapRepositories(sortAccessor = PathSortAccessor.class)
|
||||
static class ConfigWithCustomizedSortAccessor {}
|
||||
|
||||
@EnableMapRepositories(sortAccessor = PathSortAccessor.class, queryEngineFactory = SpelQueryEngineFactory.class)
|
||||
static class ConfigWithQueryEngineAndCustomizedSortAccessor {}
|
||||
|
||||
@EnableMapRepositories(queryCreator = MyQueryCreator.class, considerNestedRepositories = true,
|
||||
includeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = PersonRepository.class))
|
||||
static class ConfigWithCustomQueryCreator {}
|
||||
|
||||
static class SpelQueryEngineFactory implements QueryEngineFactory {
|
||||
|
||||
private final SortAccessor<Comparator<?>> sortAccessor;
|
||||
|
||||
public SpelQueryEngineFactory(SortAccessor<Comparator<?>> sortAccessor) {
|
||||
this.sortAccessor = sortAccessor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryEngine<?, ?, ?> create() {
|
||||
return new SpelQueryEngine(sortAccessor);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class MyQueryCreator extends AbstractQueryCreator<KeyValueQuery<Predicate<?>>, Predicate<?>> {
|
||||
|
||||
public MyQueryCreator(PartTree tree) {
|
||||
super(tree);
|
||||
}
|
||||
|
||||
public MyQueryCreator(PartTree tree, ParameterAccessor parameters) {
|
||||
super(tree, parameters);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Predicate<?> create(Part part, Iterator<Object> iterator) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Predicate<?> and(Part part, Predicate<?> base, Iterator<Object> iterator) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Predicate<?> or(Predicate<?> base, Predicate<?> criteria) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected KeyValueQuery<Predicate<?>> complete(Predicate<?> criteria, Sort sort) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
interface PersonRepository extends KeyValueRepository<Person, String> {
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user