From 80b2285c18663bf211a37ea3330a02f1049aae41 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Fri, 22 Sep 2017 14:42:01 +0200 Subject: [PATCH] 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 --- .../data/keyvalue/core/SpelSortAccessor.java | 6 ++-- ...ValueRepositoryConfigurationExtension.java | 25 +++++++++++++-- .../query/KeyValuePartTreeQuery.java | 32 +++++++++++++++---- 3 files changed, 53 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/springframework/data/keyvalue/core/SpelSortAccessor.java b/src/main/java/org/springframework/data/keyvalue/core/SpelSortAccessor.java index cb67b0a..867edf7 100644 --- a/src/main/java/org/springframework/data/keyvalue/core/SpelSortAccessor.java +++ b/src/main/java/org/springframework/data/keyvalue/core/SpelSortAccessor.java @@ -32,14 +32,16 @@ import org.springframework.util.Assert; * @author Oliver Gierke * @author Mark Paluch */ -class SpelSortAccessor implements SortAccessor> { +public class SpelSortAccessor implements SortAccessor> { 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; diff --git a/src/main/java/org/springframework/data/keyvalue/repository/config/KeyValueRepositoryConfigurationExtension.java b/src/main/java/org/springframework/data/keyvalue/repository/config/KeyValueRepositoryConfigurationExtension.java index 99088f2..83375c4 100644 --- a/src/main/java/org/springframework/data/keyvalue/repository/config/KeyValueRepositoryConfigurationExtension.java +++ b/src/main/java/org/springframework/data/keyvalue/repository/config/KeyValueRepositoryConfigurationExtension.java @@ -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 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; + } } diff --git a/src/main/java/org/springframework/data/keyvalue/repository/query/KeyValuePartTreeQuery.java b/src/main/java/org/springframework/data/keyvalue/repository/query/KeyValuePartTreeQuery.java index a52f89f..34a828f 100644 --- a/src/main/java/org/springframework/data/keyvalue/repository/query/KeyValuePartTreeQuery.java +++ b/src/main/java/org/springframework/data/keyvalue/repository/query/KeyValuePartTreeQuery.java @@ -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> constructor = ClassUtils.getConstructorIfAvailable(queryCreator, - PartTree.class, ParameterAccessor.class); + AbstractQueryCreator, ?> 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, ?> createQueryCreator(PartTree tree, + ParameterAccessor accessor) { + + Constructor> constructor = ClassUtils.getConstructorIfAvailable(queryCreator, + PartTree.class, ParameterAccessor.class); + + return (AbstractQueryCreator, ?>) BeanUtils.instantiateClass(constructor, tree, accessor); + } + /* * (non-Javadoc) * @see org.springframework.data.repository.query.RepositoryQuery#getQueryMethod()