DATAKV-196 - Open up configuration and repository components for extension.

Make SpelSortAccessor public. Introduce getMappingContextBeanRef() template method to KeyValueRepositoryConfigurationExtension so subclasses may specify the mapping context bean name. Introduce createQueryCreator() template method to KeyValuePartTreeQuery for query creator customization in subclasses.

Original Pull Request: #27
This commit is contained in:
Mark Paluch
2017-09-22 14:42:01 +02:00
committed by Christoph Strobl
parent 7a89366075
commit 80b2285c18
3 changed files with 53 additions and 10 deletions

View File

@@ -32,14 +32,16 @@ import org.springframework.util.Assert;
* @author Oliver Gierke
* @author Mark Paluch
*/
class SpelSortAccessor implements SortAccessor<Comparator<?>> {
public class SpelSortAccessor implements SortAccessor<Comparator<?>> {
private final SpelExpressionParser parser;
/**
* Creates a new {@link SpelSortAccessor} given {@link SpelExpressionParser}.
*
* @param parser must not be {@literal null}.
*/
SpelSortAccessor(SpelExpressionParser parser) {
public SpelSortAccessor(SpelExpressionParser parser) {
Assert.notNull(parser, "SpelExpressionParser must not be null!");
this.parser = parser;

View File

@@ -98,7 +98,7 @@ public abstract class KeyValueRepositoryConfigurationExtension extends Repositor
builder.addPropertyReference("keyValueOperations", attributes.getString(KEY_VALUE_TEMPLATE_BEAN_REF_ATTRIBUTE));
builder.addPropertyValue("queryCreator", getQueryCreatorType(config));
builder.addPropertyValue("queryType", getQueryType(config));
builder.addPropertyReference("mappingContext", MAPPING_CONTEXT_BEAN_NAME);
builder.addPropertyReference("mappingContext", getMappingContextBeanRef());
}
/**
@@ -157,7 +157,7 @@ public abstract class KeyValueRepositoryConfigurationExtension extends Repositor
RootBeanDefinition mappingContextDefinition = new RootBeanDefinition(KeyValueMappingContext.class);
mappingContextDefinition.setSource(configurationSource.getSource());
registerIfNotAlreadyRegistered(mappingContextDefinition, registry, MAPPING_CONTEXT_BEAN_NAME, configurationSource);
registerIfNotAlreadyRegistered(mappingContextDefinition, registry, getMappingContextBeanRef(), configurationSource);
Optional<String> keyValueTemplateName = configurationSource.getAttribute(KEY_VALUE_TEMPLATE_BEAN_REF_ATTRIBUTE);
@@ -178,6 +178,7 @@ public abstract class KeyValueRepositoryConfigurationExtension extends Repositor
* Get the default {@link RootBeanDefinition} for {@link org.springframework.data.keyvalue.core.KeyValueTemplate}.
*
* @return {@literal null} to explicitly not register a template.
* @see #getDefaultKeyValueTemplateRef()
*/
@Nullable
protected AbstractBeanDefinition getDefaultKeyValueTemplateBeanDefinition(
@@ -185,5 +186,25 @@ public abstract class KeyValueRepositoryConfigurationExtension extends Repositor
return null;
}
/**
* Returns the {@link org.springframework.data.keyvalue.core.KeyValueTemplate} bean name to potentially register a
* default {@link org.springframework.data.keyvalue.core.KeyValueTemplate} bean if no bean is registered with the
* returned name.
*
* @return the default {@link org.springframework.data.keyvalue.core.KeyValueTemplate} bean name.
* @see #getDefaultKeyValueTemplateBeanDefinition(RepositoryConfigurationSource)
*/
protected abstract String getDefaultKeyValueTemplateRef();
/**
* Returns the {@link org.springframework.data.mapping.context.MappingContext} bean name to potentially register a
* default mapping context bean if no bean is registered with the returned name. Defaults to
* {@link MAPPING_CONTEXT_BEAN_NAME}.
*
* @return the {@link org.springframework.data.mapping.context.MappingContext} bean name.
* @since 2.0
*/
protected String getMappingContextBeanRef() {
return MAPPING_CONTEXT_BEAN_NAME;
}
}

View File

@@ -177,17 +177,19 @@ public class KeyValuePartTreeQuery implements RepositoryQuery {
throw new IllegalStateException(String.format("Cannot retrieve SpelExpression from %s", criteria));
}
/**
* Create a {@link KeyValueQuery} given {@link ParameterAccessor}.
*
* @param accessor must not be {@literal null}.
* @return the {@link KeyValueQuery}.
*/
public KeyValueQuery<?> createQuery(ParameterAccessor accessor) {
PartTree tree = new PartTree(getQueryMethod().getName(), getQueryMethod().getEntityInformation().getJavaType());
Constructor<? extends AbstractQueryCreator<?, ?>> constructor = ClassUtils.getConstructorIfAvailable(queryCreator,
PartTree.class, ParameterAccessor.class);
AbstractQueryCreator<? extends KeyValueQuery<?>, ?> queryCreator = createQueryCreator(tree, accessor);
Assert.state(constructor != null, String.format("Constructor %s(PartTree, ParameterAccessor) not available!",
ClassUtils.getShortName(queryCreator)));
KeyValueQuery<?> query = (KeyValueQuery<?>) BeanUtils.instantiateClass(constructor, tree, accessor).createQuery();
KeyValueQuery<?> query = queryCreator.createQuery();
if (tree.isLimiting()) {
query.setRows(tree.getMaxResults());
@@ -195,6 +197,24 @@ public class KeyValuePartTreeQuery implements RepositoryQuery {
return query;
}
/**
* Constructs a {@link AbstractQueryCreator} for repository query creation. Subclasses may override this method to
* customize query creator construction.
*
* @param tree must not be {@literal null}.
* @param accessor must not be {@literal null}.
* @return the {@link AbstractQueryCreator} object.
* @since 2.0
*/
protected AbstractQueryCreator<? extends KeyValueQuery<?>, ?> createQueryCreator(PartTree tree,
ParameterAccessor accessor) {
Constructor<? extends AbstractQueryCreator<?, ?>> constructor = ClassUtils.getConstructorIfAvailable(queryCreator,
PartTree.class, ParameterAccessor.class);
return (AbstractQueryCreator<KeyValueQuery<?>, ?>) BeanUtils.instantiateClass(constructor, tree, accessor);
}
/*
* (non-Javadoc)
* @see org.springframework.data.repository.query.RepositoryQuery#getQueryMethod()