DATADOC-34 - Infrastructure for callbacks on RepositoryQuery creation.
Introduced QueryCreationListener that allows plugging in functionality after a query was created. Heavily refactored QueryMethod and RepositoryQuery subsystem. Splitted up simple EntityMetadata (domain class and potentially other stuff) from the more advanced methods like getId(Object) and isNew(…). QueryMethod now carries a type enum that allows switching over it to determine the execution. Beyond that QueryMethod now returns a EntityMetadata rather than a plain class. RepositoryQuery in turn exposes the query method. PartTree allows iterating over all contained Parts as well now. Introduced AbstractEntityInformation that regards an entity as new if its id is null. Simplified handling of RepositoryProxyPostProcessors and aligned them to QueryCreationListener handling.
This commit is contained in:
@@ -111,6 +111,24 @@ public class Sort implements
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the order registered for the given property.
|
||||
*
|
||||
* @param property
|
||||
* @return
|
||||
*/
|
||||
public Order getOrderFor(String property) {
|
||||
|
||||
for (Order order : this) {
|
||||
if (order.getProperty().equals(property)) {
|
||||
return order;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
|
||||
@@ -23,6 +23,8 @@ import java.util.List;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.repository.support.EntityMetadata;
|
||||
import org.springframework.data.repository.util.ClassUtils;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
||||
@@ -35,6 +37,11 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public class QueryMethod {
|
||||
|
||||
public static enum Type {
|
||||
|
||||
SINGLE_ENTITY, PAGING, COLLECTION, MODIFYING;
|
||||
}
|
||||
|
||||
private final Method method;
|
||||
private final Parameters parameters;
|
||||
|
||||
@@ -82,27 +89,21 @@ public class QueryMethod {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether the given
|
||||
*
|
||||
* @param number
|
||||
* @return
|
||||
*/
|
||||
public boolean isCorrectNumberOfParameters(int number) {
|
||||
public EntityMetadata<?> getEntityMetadata() {
|
||||
|
||||
return number == parameters.getBindableParameters()
|
||||
.getNumberOfParameters();
|
||||
return new EntityMetadata() {
|
||||
|
||||
public Class<?> getJavaType() {
|
||||
|
||||
return getDomainClass();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the domain class for this method.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Class<?> getDomainClass() {
|
||||
protected Class<?> getDomainClass() {
|
||||
|
||||
return getReturnedDomainClass(method);
|
||||
return ClassUtils.getReturnedDomainClass(method);
|
||||
}
|
||||
|
||||
|
||||
@@ -112,7 +113,7 @@ public class QueryMethod {
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isCollectionQuery() {
|
||||
protected boolean isCollectionQuery() {
|
||||
|
||||
Class<?> returnType = method.getReturnType();
|
||||
return org.springframework.util.ClassUtils.isAssignable(List.class,
|
||||
@@ -125,7 +126,7 @@ public class QueryMethod {
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isPageQuery() {
|
||||
protected boolean isPageQuery() {
|
||||
|
||||
Class<?> returnType = method.getReturnType();
|
||||
return org.springframework.util.ClassUtils.isAssignable(Page.class,
|
||||
@@ -133,6 +134,30 @@ public class QueryMethod {
|
||||
}
|
||||
|
||||
|
||||
public Type getType() {
|
||||
|
||||
if (isModifyingQuery()) {
|
||||
return Type.MODIFYING;
|
||||
}
|
||||
|
||||
if (isPageQuery()) {
|
||||
return Type.PAGING;
|
||||
}
|
||||
|
||||
if (isCollectionQuery()) {
|
||||
return Type.COLLECTION;
|
||||
}
|
||||
|
||||
return Type.SINGLE_ENTITY;
|
||||
}
|
||||
|
||||
|
||||
protected boolean isModifyingQuery() {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the {@link Parameters} wrapper to gain additional information
|
||||
* about {@link Method} parameters.
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package org.springframework.data.repository.query;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Interface for a query abstraction.
|
||||
*
|
||||
@@ -30,4 +32,12 @@ public interface RepositoryQuery {
|
||||
* @return
|
||||
*/
|
||||
public Object execute(Object[] parameters);
|
||||
|
||||
|
||||
/**
|
||||
* Returns the
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public QueryMethod getQueryMethod();
|
||||
}
|
||||
@@ -125,6 +125,26 @@ public class PartTree implements Iterable<OrPart> {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns an {@link Iterable} of all parts contained in the
|
||||
* {@link PartTree}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Iterable<Part> getParts() {
|
||||
|
||||
List<Part> result = new ArrayList<Part>();
|
||||
|
||||
for (OrPart orPart : this) {
|
||||
for (Part part : orPart) {
|
||||
result.add(part);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Splits the given text at the given keywords. Expects camelcase style to
|
||||
* only match concrete keywords and not derivatives of it.
|
||||
|
||||
@@ -19,22 +19,24 @@ import org.springframework.util.Assert;
|
||||
|
||||
|
||||
/**
|
||||
* Base class for implementations of {@link EntityMetadata}. Considers an entity
|
||||
* to be new whenever {@link #getId(Object)} returns {@literal null}.
|
||||
* Base class for implementations of {@link EntityInformation}. Considers an
|
||||
* entity to be new whenever {@link #getId(Object)} returns {@literal null}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public abstract class AbstractEntityMetadata<T> implements EntityMetadata<T> {
|
||||
public abstract class AbstractEntityInformation<T> implements
|
||||
EntityInformation<T> {
|
||||
|
||||
private final Class<T> domainClass;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new {@link AbstractEntityMetadata} from the given domain class.
|
||||
* Creates a new {@link AbstractEntityInformation} from the given domain
|
||||
* class.
|
||||
*
|
||||
* @param domainClass
|
||||
*/
|
||||
public AbstractEntityMetadata(Class<T> domainClass) {
|
||||
public AbstractEntityInformation(Class<T> domainClass) {
|
||||
|
||||
Assert.notNull(domainClass);
|
||||
this.domainClass = domainClass;
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.repository.support;
|
||||
|
||||
/**
|
||||
* Extension of {@link EntityMetadata} to add functionality to query information
|
||||
* of entity instances.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface EntityInformation<T> extends EntityMetadata<T> {
|
||||
|
||||
/**
|
||||
* Returns whether the given entity is considered to be new.
|
||||
*
|
||||
* @param entity must never be {@literal null}
|
||||
* @return
|
||||
*/
|
||||
boolean isNew(T entity);
|
||||
|
||||
|
||||
/**
|
||||
* Returns the id of the given entity.
|
||||
*
|
||||
* @param entity must never be {@literal null}
|
||||
* @return
|
||||
*/
|
||||
Object getId(T entity);
|
||||
}
|
||||
@@ -22,24 +22,6 @@ package org.springframework.data.repository.support;
|
||||
*/
|
||||
public interface EntityMetadata<T> {
|
||||
|
||||
/**
|
||||
* Returns whether the given entity is considered to be new.
|
||||
*
|
||||
* @param entity must never be {@literal null}
|
||||
* @return
|
||||
*/
|
||||
boolean isNew(T entity);
|
||||
|
||||
|
||||
/**
|
||||
* Returns the id of the given entity.
|
||||
*
|
||||
* @param entity must never be {@literal null}
|
||||
* @return
|
||||
*/
|
||||
Object getId(T entity);
|
||||
|
||||
|
||||
/**
|
||||
* Returns the actual domain class type.
|
||||
*
|
||||
|
||||
@@ -26,15 +26,15 @@ import org.springframework.data.domain.Persistable;
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public class PersistableEntityMetadata<T extends Persistable> extends
|
||||
AbstractEntityMetadata<T> {
|
||||
public class PersistableEntityInformation<T extends Persistable> extends
|
||||
AbstractEntityInformation<T> {
|
||||
|
||||
/**
|
||||
* Creates a new {@link PersistableEntityMetadata}.
|
||||
* Creates a new {@link PersistableEntityInformation}.
|
||||
*
|
||||
* @param domainClass
|
||||
*/
|
||||
public PersistableEntityMetadata(Class<T> domainClass) {
|
||||
public PersistableEntityInformation(Class<T> domainClass) {
|
||||
|
||||
super(domainClass);
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.repository.support;
|
||||
|
||||
import org.springframework.data.repository.query.RepositoryQuery;
|
||||
|
||||
|
||||
/**
|
||||
* Callback for listeners that want to execute functionality on
|
||||
* {@link RepositoryQuery} creation.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface QueryCreationListener<T extends RepositoryQuery> {
|
||||
|
||||
/**
|
||||
* Will be invoked just after the {@link RepositoryQuery} was created.
|
||||
*
|
||||
* @param query
|
||||
*/
|
||||
void onCreation(T query);
|
||||
}
|
||||
@@ -15,9 +15,6 @@
|
||||
*/
|
||||
package org.springframework.data.repository.support;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Required;
|
||||
@@ -124,23 +121,6 @@ public abstract class RepositoryFactoryBeanSupport<T extends Repository<?, ?>>
|
||||
|
||||
this.factory = createRepositoryFactory();
|
||||
this.factory.setQueryLookupStrategyKey(queryLookupStrategyKey);
|
||||
|
||||
for (RepositoryProxyPostProcessor processor : getRepositoryPostProcessors()) {
|
||||
this.factory.addRepositoryProxyPostProcessor(processor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns all {@link RepositoryProxyPostProcessor} to be added to the
|
||||
* repository factory to be created. Default implementation will return an
|
||||
* empty list.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected List<RepositoryProxyPostProcessor> getRepositoryPostProcessors() {
|
||||
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.core.GenericTypeResolver;
|
||||
import org.springframework.data.repository.Repository;
|
||||
import org.springframework.data.repository.query.QueryLookupStrategy;
|
||||
import org.springframework.data.repository.query.QueryLookupStrategy.Key;
|
||||
@@ -49,6 +50,8 @@ public abstract class RepositoryFactorySupport {
|
||||
private final List<RepositoryProxyPostProcessor> postProcessors =
|
||||
new ArrayList<RepositoryProxyPostProcessor>();
|
||||
private QueryLookupStrategy.Key queryLookupStrategyKey;
|
||||
private List<QueryCreationListener<?>> queryPostProcessors =
|
||||
new ArrayList<QueryCreationListener<?>>();
|
||||
|
||||
|
||||
/**
|
||||
@@ -62,6 +65,20 @@ public abstract class RepositoryFactorySupport {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds a {@link QueryCreationListener} to the factory to plug in
|
||||
* functionality triggered right after creation of {@link RepositoryQuery}
|
||||
* instances.
|
||||
*
|
||||
* @param listener
|
||||
*/
|
||||
public void addQueryCreationListener(QueryCreationListener<?> listener) {
|
||||
|
||||
Assert.notNull(listener);
|
||||
this.queryPostProcessors.add(listener);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds {@link RepositoryProxyPostProcessor}s to the factory to allow
|
||||
* manipulation of the {@link ProxyFactory} before the proxy gets created.
|
||||
@@ -71,7 +88,7 @@ public abstract class RepositoryFactorySupport {
|
||||
*
|
||||
* @param processor
|
||||
*/
|
||||
protected void addRepositoryProxyPostProcessor(
|
||||
public void addRepositoryProxyPostProcessor(
|
||||
RepositoryProxyPostProcessor processor) {
|
||||
|
||||
Assert.notNull(processor);
|
||||
@@ -205,10 +222,10 @@ public abstract class RepositoryFactorySupport {
|
||||
* interface methods.
|
||||
*/
|
||||
public QueryExecuterMethodInterceptor(
|
||||
RepositoryMetadata repositoryInterface,
|
||||
RepositoryMetadata repositoryMetadata,
|
||||
Object customImplementation, Object target) {
|
||||
|
||||
this.metadata = repositoryInterface;
|
||||
this.metadata = repositoryMetadata;
|
||||
this.customImplementation = customImplementation;
|
||||
this.target = target;
|
||||
|
||||
@@ -216,10 +233,28 @@ public abstract class RepositoryFactorySupport {
|
||||
getQueryLookupStrategy(queryLookupStrategyKey);
|
||||
|
||||
for (Method method : metadata.getQueryMethods()) {
|
||||
queries.put(
|
||||
method,
|
||||
RepositoryQuery query =
|
||||
lookupStrategy.resolveQuery(method,
|
||||
repositoryInterface.getDomainClass()));
|
||||
repositoryMetadata.getDomainClass());
|
||||
invokeListeners(query, metadata);
|
||||
queries.put(method, query);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
private void invokeListeners(RepositoryQuery query,
|
||||
RepositoryMetadata metadata) {
|
||||
|
||||
for (QueryCreationListener listener : queryPostProcessors) {
|
||||
Class<?> typeArgument =
|
||||
GenericTypeResolver.resolveTypeArgument(
|
||||
listener.getClass(),
|
||||
QueryCreationListener.class);
|
||||
if (typeArgument != null
|
||||
&& typeArgument.isAssignableFrom(query.getClass())) {
|
||||
listener.onCreation(query);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,9 +15,6 @@
|
||||
*/
|
||||
package org.springframework.data.repository.support;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
@@ -59,20 +56,32 @@ public abstract class TransactionalRepositoryFactoryBeanSupport<T extends Reposi
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
/**
|
||||
* Delegates {@link RepositoryFactorySupport} creation to
|
||||
* {@link #doCreateRepositoryFactory()} and applies the
|
||||
* {@link TransactionalRepositoryProxyPostProcessor} to the created
|
||||
* instance.
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.support.RepositoryFactoryBeanSupport
|
||||
* #getRepositoryPostProcessors()
|
||||
* @see org.springframework.data.repository.support.RepositoryFactoryBeanSupport
|
||||
* #createRepositoryFactory()
|
||||
*/
|
||||
@Override
|
||||
public List<RepositoryProxyPostProcessor> getRepositoryPostProcessors() {
|
||||
protected final RepositoryFactorySupport createRepositoryFactory() {
|
||||
|
||||
return Arrays.asList(txPostProcessor);
|
||||
RepositoryFactorySupport factory = doCreateRepositoryFactory();
|
||||
factory.addRepositoryProxyPostProcessor(txPostProcessor);
|
||||
return factory;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates the actual {@link RepositoryFactorySupport} instance.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected abstract RepositoryFactorySupport doCreateRepositoryFactory();
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
|
||||
@@ -22,32 +22,32 @@ import org.junit.Test;
|
||||
|
||||
|
||||
/**
|
||||
* Unit tests for {@link AbstractEntityMetadata}.
|
||||
* Unit tests for {@link AbstractEntityInformation}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class AbstractEntityMetadataUnitTests {
|
||||
public class AbstractEntityInformationUnitTests {
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void rejectsNullDomainClass() throws Exception {
|
||||
|
||||
new DummyAbstractEntityMetadata(null);
|
||||
new DummyAbstractEntityInformation(null);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void considersEntityNewIfGetIdReturnsNull() throws Exception {
|
||||
|
||||
EntityMetadata<Object> metadata =
|
||||
new DummyAbstractEntityMetadata(Object.class);
|
||||
EntityInformation<Object> metadata =
|
||||
new DummyAbstractEntityInformation(Object.class);
|
||||
assertThat(metadata.isNew(null), is(true));
|
||||
assertThat(metadata.isNew(new Object()), is(false));
|
||||
}
|
||||
|
||||
private static class DummyAbstractEntityMetadata extends
|
||||
AbstractEntityMetadata<Object> {
|
||||
private static class DummyAbstractEntityInformation extends
|
||||
AbstractEntityInformation<Object> {
|
||||
|
||||
public DummyAbstractEntityMetadata(Class<Object> domainClass) {
|
||||
public DummyAbstractEntityInformation(Class<Object> domainClass) {
|
||||
|
||||
super(domainClass);
|
||||
}
|
||||
@@ -32,11 +32,11 @@ import org.springframework.data.domain.Persistable;
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class PersistableEntityMetadataUnitTests {
|
||||
public class PersistableEntityInformationUnitTests {
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
static final PersistableEntityMetadata<Persistable> metadata =
|
||||
new PersistableEntityMetadata<Persistable>(Persistable.class);
|
||||
static final PersistableEntityInformation<Persistable> metadata =
|
||||
new PersistableEntityInformation<Persistable>(Persistable.class);
|
||||
|
||||
@Mock
|
||||
Persistable<Long> persistable;
|
||||
@@ -64,8 +64,8 @@ public class PersistableEntityMetadataUnitTests {
|
||||
@Test
|
||||
public void returnsGivenClassAsEntityType() throws Exception {
|
||||
|
||||
PersistableEntityMetadata<PersistableEntity> info =
|
||||
new PersistableEntityMetadata<PersistableEntity>(
|
||||
PersistableEntityInformation<PersistableEntity> info =
|
||||
new PersistableEntityInformation<PersistableEntity>(
|
||||
PersistableEntity.class);
|
||||
|
||||
assertEquals(PersistableEntity.class, info.getJavaType());
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.repository.support;
|
||||
|
||||
import static org.mockito.Matchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.data.repository.Repository;
|
||||
import org.springframework.data.repository.query.QueryLookupStrategy;
|
||||
import org.springframework.data.repository.query.QueryLookupStrategy.Key;
|
||||
import org.springframework.data.repository.query.RepositoryQuery;
|
||||
|
||||
|
||||
/**
|
||||
* Unit tests for {@link RepositoryFactorySupport}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class RepositoryFactorySupportUnitTests {
|
||||
|
||||
RepositoryFactorySupport factory = new DummyRepositoryFactory();
|
||||
|
||||
@Mock
|
||||
MyQueryCreationListener listener;
|
||||
@Mock
|
||||
PlainQueryCreationListener otherListener;
|
||||
|
||||
|
||||
@Test
|
||||
public void invokesCustomQueryCreationListenerForSpecialRepositoryQueryOnly()
|
||||
throws Exception {
|
||||
|
||||
factory.addQueryCreationListener(listener);
|
||||
factory.addQueryCreationListener(otherListener);
|
||||
|
||||
factory.getRepository(ObjectRepository.class);
|
||||
|
||||
verify(listener, times(1)).onCreation(any(MyRepositoryQuery.class));
|
||||
verify(otherListener, times(2)).onCreation(any(RepositoryQuery.class));
|
||||
|
||||
}
|
||||
|
||||
class DummyRepositoryFactory extends RepositoryFactorySupport {
|
||||
|
||||
@Override
|
||||
protected Object getTargetRepository(RepositoryMetadata metadata) {
|
||||
|
||||
return new Object();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Class<?> getRepositoryBaseClass(Class<?> repositoryInterface) {
|
||||
|
||||
return Object.class;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected QueryLookupStrategy getQueryLookupStrategy(Key key) {
|
||||
|
||||
MyRepositoryQuery queryOne = mock(MyRepositoryQuery.class);
|
||||
RepositoryQuery queryTwo = mock(RepositoryQuery.class);
|
||||
|
||||
QueryLookupStrategy strategy = mock(QueryLookupStrategy.class);
|
||||
when(strategy.resolveQuery(any(Method.class), any(Class.class)))
|
||||
.thenReturn(queryOne, queryTwo);
|
||||
|
||||
return strategy;
|
||||
}
|
||||
}
|
||||
|
||||
interface ObjectRepository extends Repository<Object, Serializable> {
|
||||
|
||||
Object findByClass(Class<?> clazz);
|
||||
|
||||
|
||||
Object findByFoo();
|
||||
}
|
||||
|
||||
interface PlainQueryCreationListener extends
|
||||
QueryCreationListener<RepositoryQuery> {
|
||||
|
||||
}
|
||||
|
||||
interface MyQueryCreationListener extends
|
||||
QueryCreationListener<MyRepositoryQuery> {
|
||||
|
||||
}
|
||||
|
||||
interface MyRepositoryQuery extends RepositoryQuery {
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user