Browse Source

Merge branch 'master' of github.com:SpringSource/spring-data-commons

pull/2/head
J. Brisbin 15 years ago
parent
commit
71f08efa53
  1. 16
      spring-data-commons-core/pom.xml
  2. 6
      spring-data-commons-core/src/main/java/org/springframework/data/mapping/BasicMappingContext.java
  3. 6
      spring-data-commons-core/src/main/java/org/springframework/data/persistence/AbstractConstructorEntityInstantiator.java
  4. 25
      spring-data-commons-core/src/main/java/org/springframework/data/repository/config/AbstractRepositoryConfigDefinitionParser.java
  5. 5
      spring-data-commons-core/src/main/java/org/springframework/data/repository/query/QueryLookupStrategy.java
  6. 11
      spring-data-commons-core/src/main/java/org/springframework/data/repository/query/QueryMethod.java
  7. 289
      spring-data-commons-core/src/main/java/org/springframework/data/repository/support/DefaultRepositoryInformation.java
  8. 233
      spring-data-commons-core/src/main/java/org/springframework/data/repository/support/DefaultRepositoryMetadata.java
  9. 67
      spring-data-commons-core/src/main/java/org/springframework/data/repository/support/RepositoryFactorySupport.java
  10. 75
      spring-data-commons-core/src/main/java/org/springframework/data/repository/support/RepositoryInformation.java
  11. 69
      spring-data-commons-core/src/main/java/org/springframework/data/repository/support/RepositoryMetadata.java
  12. 6
      spring-data-commons-core/src/main/java/org/springframework/data/transaction/ChangeSetBackedTransactionSynchronization.java
  13. 63
      spring-data-commons-core/src/test/java/org/springframework/data/repository/support/DefaultRepositoryInformationUnitTests.java
  14. 52
      spring-data-commons-core/src/test/java/org/springframework/data/repository/support/DefaultRepositoryMetadataUnitTests.java
  15. 12
      spring-data-commons-core/src/test/java/org/springframework/data/repository/support/QueryExecuterMethodInterceptorUnitTests.java
  16. 4
      spring-data-commons-core/src/test/java/org/springframework/data/repository/support/RepositoryFactorySupportUnitTests.java
  17. 24
      spring-data-commons-parent/pom.xml

16
spring-data-commons-core/pom.xml

@ -35,24 +35,10 @@ @@ -35,24 +35,10 @@
</dependency>
<!-- Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<scope>runtime</scope>
<scope>test</scope>
</dependency>
<dependency>

6
spring-data-commons-core/src/main/java/org/springframework/data/mapping/BasicMappingContext.java

@ -38,8 +38,8 @@ import java.util.Set; @@ -38,8 +38,8 @@ import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationEventPublisher;
@ -75,7 +75,7 @@ public class BasicMappingContext implements MappingContext, InitializingBean, Ap @@ -75,7 +75,7 @@ public class BasicMappingContext implements MappingContext, InitializingBean, Ap
private static final Set<String> UNMAPPED_FIELDS = new HashSet<String>(Arrays.asList("class", "this$0"));
protected Logger log = LoggerFactory.getLogger(getClass());
protected Log log = LogFactory.getLog(getClass());
protected ApplicationEventPublisher applicationEventPublisher;
protected ConcurrentMap<TypeInformation, PersistentEntity<?>> persistentEntities = new ConcurrentHashMap<TypeInformation, PersistentEntity<?>>();
protected ConcurrentMap<PersistentEntity<?>, List<Validator>> validators = new ConcurrentHashMap<PersistentEntity<?>, List<Validator>>();

6
spring-data-commons-core/src/main/java/org/springframework/data/persistence/AbstractConstructorEntityInstantiator.java

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
package org.springframework.data.persistence;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.ClassUtils;
import java.lang.reflect.Constructor;
@ -17,7 +17,7 @@ import java.util.Map; @@ -17,7 +17,7 @@ import java.util.Map;
*/
public abstract class AbstractConstructorEntityInstantiator<BACKING_INTERFACE, STATE> implements EntityInstantiator<BACKING_INTERFACE, STATE> {
private final Logger log = LoggerFactory.getLogger(getClass());
private final Log log = LogFactory.getLog(getClass());
private final Map<Class<? extends BACKING_INTERFACE>,StateBackedCreator<? extends BACKING_INTERFACE,STATE>> cache = new HashMap<Class<? extends BACKING_INTERFACE>,StateBackedCreator<? extends BACKING_INTERFACE,STATE>>();
final public <T extends BACKING_INTERFACE> T createEntityFromState(STATE n, Class<T> c) {

25
spring-data-commons-core/src/main/java/org/springframework/data/repository/config/AbstractRepositoryConfigDefinitionParser.java

@ -23,8 +23,8 @@ import java.util.HashSet; @@ -23,8 +23,8 @@ import java.util.HashSet;
import java.util.Set;
import java.util.regex.Pattern;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
@ -58,8 +58,8 @@ import org.w3c.dom.Element; @@ -58,8 +58,8 @@ import org.w3c.dom.Element;
public abstract class AbstractRepositoryConfigDefinitionParser<S extends GlobalRepositoryConfigInformation<T>, T extends SingleRepositoryConfigInformation<S>>
implements BeanDefinitionParser {
private static final Logger LOG = LoggerFactory
.getLogger(AbstractRepositoryConfigDefinitionParser.class);
private static final Log LOG = LogFactory.getLog(
AbstractRepositoryConfigDefinitionParser.class);
private static final String REPOSITORY_INTERFACE_POST_PROCESSOR =
"org.springframework.data.repository.support.RepositoryInterfaceAwareBeanPostProcessor";
@ -223,12 +223,13 @@ public abstract class AbstractRepositoryConfigDefinitionParser<S extends GlobalR @@ -223,12 +223,13 @@ public abstract class AbstractRepositoryConfigDefinitionParser<S extends GlobalR
AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
beanDefinition.setSource(beanSource);
if (LOG.isDebugEnabled()) {
LOG.debug(
"Registering repository: {} - Interface: {} - Factory: {}, - Custom implementation: {}",
new Object[] { context.getBeanId(),
context.getInterfaceName(),
context.getRepositoryFactoryBeanClassName(),
customImplementationBeanName });
"Registering repository: " + context.getBeanId() +
" - Interface: " + context.getInterfaceName() +
" - Factory: " + context.getRepositoryFactoryBeanClassName() +
", - Custom implementation: " + customImplementationBeanName);
}
BeanComponentDefinition definition =
new BeanComponentDefinition(beanDefinition,
@ -285,9 +286,11 @@ public abstract class AbstractRepositoryConfigDefinitionParser<S extends GlobalR @@ -285,9 +286,11 @@ public abstract class AbstractRepositoryConfigDefinitionParser<S extends GlobalR
return null;
}
LOG.debug("Registering custom repository implementation: {} {}",
config.getImplementationBeanName(),
if (LOG.isDebugEnabled()) {
LOG.debug("Registering custom repository implementation: " +
config.getImplementationBeanName() + " " +
beanDefinition.getBeanClassName());
}
beanDefinition.setSource(source);
parser.registerBeanComponent(new BeanComponentDefinition(

5
spring-data-commons-core/src/main/java/org/springframework/data/repository/query/QueryLookupStrategy.java

@ -18,6 +18,7 @@ package org.springframework.data.repository.query; @@ -18,6 +18,7 @@ package org.springframework.data.repository.query;
import java.lang.reflect.Method;
import java.util.Locale;
import org.springframework.data.repository.support.RepositoryMetadata;
import org.springframework.util.StringUtils;
@ -54,8 +55,8 @@ public interface QueryLookupStrategy { @@ -54,8 +55,8 @@ public interface QueryLookupStrategy {
* that can be executed afterwards.
*
* @param method
* @param domainClass
* @param metadata
* @return
*/
RepositoryQuery resolveQuery(Method method, Class<?> domainClass);
RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata);
}

11
spring-data-commons-core/src/main/java/org/springframework/data/repository/query/QueryMethod.java

@ -24,6 +24,7 @@ import org.springframework.data.domain.Page; @@ -24,6 +24,7 @@ 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.support.RepositoryMetadata;
import org.springframework.data.repository.util.ClassUtils;
import org.springframework.util.Assert;
@ -42,6 +43,7 @@ public class QueryMethod { @@ -42,6 +43,7 @@ public class QueryMethod {
SINGLE_ENTITY, PAGING, COLLECTION, MODIFYING;
}
private final RepositoryMetadata metadata;
private final Method method;
private final Parameters parameters;
@ -52,7 +54,7 @@ public class QueryMethod { @@ -52,7 +54,7 @@ public class QueryMethod {
*
* @param method must not be {@literal null}
*/
public QueryMethod(Method method) {
public QueryMethod(Method method, RepositoryMetadata metadata) {
Assert.notNull(method, "Method must not be null!");
@ -75,6 +77,7 @@ public class QueryMethod { @@ -75,6 +77,7 @@ public class QueryMethod {
this.method = method;
this.parameters = new Parameters(method);
this.metadata = metadata;
}
@ -104,7 +107,11 @@ public class QueryMethod { @@ -104,7 +107,11 @@ public class QueryMethod {
protected Class<?> getDomainClass() {
return ClassUtils.getReturnedDomainClass(method);
Class<?> repositoryDomainClass = metadata.getDomainClass();
Class<?> methodDomainClass = ClassUtils.getReturnedDomainClass(method);
return repositoryDomainClass == null || repositoryDomainClass.isAssignableFrom(methodDomainClass) ? methodDomainClass
: repositoryDomainClass;
}

289
spring-data-commons-core/src/main/java/org/springframework/data/repository/support/DefaultRepositoryInformation.java

@ -0,0 +1,289 @@ @@ -0,0 +1,289 @@
/*
* 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.springframework.data.repository.util.ClassUtils.*;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.springframework.data.repository.Repository;
import org.springframework.util.Assert;
/**
* Default implementation of {@link RepositoryInformation}.
*
* @author Oliver Gierke
*/
class DefaultRepositoryInformation implements RepositoryInformation {
private static final TypeVariable<Class<Repository>>[] PARAMETERS = Repository.class.getTypeParameters();
private static final String DOMAIN_TYPE_NAME = PARAMETERS[0].getName();
private static final String ID_TYPE_NAME = PARAMETERS[1].getName();
private final Map<Method, Method> methodCache = new ConcurrentHashMap<Method, Method>();
private final RepositoryMetadata metadata;
private final Class<?> repositoryBaseClass;
/**
* Creates a new {@link DefaultRepositoryMetadata} for the given repository interface and repository base class.
*
* @param repositoryInterface
*/
public DefaultRepositoryInformation(RepositoryMetadata metadata, Class<?> repositoryBaseClass) {
Assert.notNull(metadata);
Assert.notNull(repositoryBaseClass);
this.metadata = metadata;
this.repositoryBaseClass = repositoryBaseClass;
}
/* (non-Javadoc)
* @see org.springframework.data.repository.support.RepositoryMetadata#getRepositoryInterface()
*/
@Override
public Class<?> getRepositoryInterface() {
return metadata.getRepositoryInterface();
}
/* (non-Javadoc)
* @see org.springframework.data.repository.support.RepositoryMetadata#getDomainClass()
*/
@Override
public Class<?> getDomainClass() {
return metadata.getDomainClass();
}
/* (non-Javadoc)
* @see org.springframework.data.repository.support.RepositoryMetadata#getIdClass()
*/
@Override
public Class<?> getIdClass() {
return metadata.getIdClass();
}
/*
* (non-Javadoc)
*
* @see org.springframework.data.repository.support.RepositoryMetadata#
* getRepositoryBaseClass()
*/
public Class<?> getRepositoryBaseClass() {
return this.repositoryBaseClass;
}
/*
* (non-Javadoc)
*
* @see org.springframework.data.repository.support.RepositoryMetadata#
* getBaseClassMethod(java.lang.reflect.Method)
*/
public Method getBaseClassMethod(Method method) {
Assert.notNull(method);
Method result = methodCache.get(method);
if (null != result) {
return result;
}
result = getBaseClassMethodFor(method);
methodCache.put(method, result);
return result;
}
/**
* Returns whether the given method is considered to be a repository base class method.
*
* @param method
* @return
*/
private boolean isBaseClassMethod(Method method) {
Assert.notNull(method);
if (method.getDeclaringClass().isAssignableFrom(repositoryBaseClass)) {
return true;
}
return !method.equals(getBaseClassMethod(method));
}
/*
* (non-Javadoc)
*
* @see org.springframework.data.repository.support.RepositoryMetadata#
* getFinderMethods()
*/
public Iterable<Method> getQueryMethods() {
Set<Method> result = new HashSet<Method>();
for (Method method : getRepositoryInterface().getDeclaredMethods()) {
if (!isCustomMethod(method) && !isBaseClassMethod(method)) {
result.add(method);
}
}
return result;
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.support.RepositoryMetadata#isCustomMethod
* (java.lang.reflect.Method)
*/
public boolean isCustomMethod(Method method) {
Class<?> declaringClass = method.getDeclaringClass();
boolean isQueryMethod = declaringClass.equals(getRepositoryInterface());
boolean isRepositoryInterface = isGenericRepositoryInterface(declaringClass);
boolean isBaseClassMethod = isBaseClassMethod(method);
return !(isRepositoryInterface || isBaseClassMethod || isQueryMethod);
}
/**
* Returns the given base class' method if the given method (declared in the repository interface) was also declared
* at the repository base class. Returns the given method if the given base class does not declare the method given.
* Takes generics into account.
*
* @param method
* @return
*/
Method getBaseClassMethodFor(Method method) {
for (Method baseClassMethod : repositoryBaseClass.getMethods()) {
// Wrong name
if (!method.getName().equals(baseClassMethod.getName())) {
continue;
}
// Wrong number of arguments
if (!(method.getParameterTypes().length == baseClassMethod.getParameterTypes().length)) {
continue;
}
// Check whether all parameters match
if (!parametersMatch(method, baseClassMethod)) {
continue;
}
return baseClassMethod;
}
return method;
}
/*
* (non-Javadoc)
*
* @see org.springframework.data.repository.support.RepositoryMetadata#
* hasCustomMethod()
*/
public boolean hasCustomMethod() {
Class<?> repositoryInterface = getRepositoryInterface();
// No detection required if no typing interface was configured
if (isGenericRepositoryInterface(repositoryInterface)) {
return false;
}
for (Method method : repositoryInterface.getMethods()) {
if (isCustomMethod(method) && !isBaseClassMethod(method)) {
return true;
}
}
return false;
}
/**
* Checks the given method's parameters to match the ones of the given base class method. Matches generic arguments
* agains the ones bound in the given repository interface.
*
* @param method
* @param baseClassMethod
* @return
*/
private boolean parametersMatch(Method method, Method baseClassMethod) {
Type[] genericTypes = baseClassMethod.getGenericParameterTypes();
Class<?>[] types = baseClassMethod.getParameterTypes();
Class<?>[] methodParameters = method.getParameterTypes();
for (int i = 0; i < genericTypes.length; i++) {
Type type = genericTypes[i];
if (type instanceof TypeVariable<?>) {
String name = ((TypeVariable<?>) type).getName();
if (!matchesGenericType(name, methodParameters[i])) {
return false;
}
} else {
if (!types[i].equals(methodParameters[i])) {
return false;
}
}
}
return true;
}
/**
* Checks whether the given parameter type matches the generic type of the given parameter. Thus when {@literal PK} is
* declared, the method ensures that given method parameter is the primary key type declared in the given repository
* interface e.g.
*
* @param name
* @param parameterType
* @return
*/
private boolean matchesGenericType(String name, Class<?> parameterType) {
Class<?> entityType = getDomainClass();
Class<?> idClass = getIdClass();
if (ID_TYPE_NAME.equals(name) && parameterType.equals(idClass)) {
return true;
}
if (DOMAIN_TYPE_NAME.equals(name) && parameterType.equals(entityType)) {
return true;
}
return false;
}
}

233
spring-data-commons-core/src/main/java/org/springframework/data/repository/support/DefaultRepositoryMetadata.java

@ -37,17 +37,7 @@ import org.springframework.util.Assert; @@ -37,17 +37,7 @@ import org.springframework.util.Assert;
*/
public class DefaultRepositoryMetadata implements RepositoryMetadata {
@SuppressWarnings("rawtypes")
private static final TypeVariable<Class<Repository>>[] PARAMETERS =
Repository.class.getTypeParameters();
private static final String DOMAIN_TYPE_NAME = PARAMETERS[0].getName();
private static final String ID_TYPE_NAME = PARAMETERS[1].getName();
private final Map<Method, Method> methodCache =
new ConcurrentHashMap<Method, Method>();
private final Class<?> repositoryInterface;
private final Class<?> repositoryBaseClass;
/**
@ -56,13 +46,10 @@ public class DefaultRepositoryMetadata implements RepositoryMetadata { @@ -56,13 +46,10 @@ public class DefaultRepositoryMetadata implements RepositoryMetadata {
*
* @param repositoryInterface
*/
public DefaultRepositoryMetadata(Class<?> repositoryInterface,
Class<?> repositoryBaseClass) {
public DefaultRepositoryMetadata(Class<?> repositoryInterface) {
Assert.notNull(repositoryInterface);
Assert.notNull(repositoryBaseClass);
this.repositoryInterface = repositoryInterface;
this.repositoryBaseClass = repositoryBaseClass;
}
@ -78,17 +65,6 @@ public class DefaultRepositoryMetadata implements RepositoryMetadata { @@ -78,17 +65,6 @@ public class DefaultRepositoryMetadata implements RepositoryMetadata {
}
/*
* (non-Javadoc)
*
* @see org.springframework.data.repository.support.RepositoryMetadata#
* getRepositoryBaseClass()
*/
public Class<?> getRepositoryBaseClass() {
return this.repositoryBaseClass;
}
/*
* (non-Javadoc)
@ -118,211 +94,4 @@ public class DefaultRepositoryMetadata implements RepositoryMetadata { @@ -118,211 +94,4 @@ public class DefaultRepositoryMetadata implements RepositoryMetadata {
resolveTypeArguments(repositoryInterface, Repository.class);
return arguments == null ? null : arguments[1];
}
/*
* (non-Javadoc)
*
* @see org.springframework.data.repository.support.RepositoryMetadata#
* getBaseClassMethod(java.lang.reflect.Method)
*/
public Method getBaseClassMethod(Method method) {
Assert.notNull(method);
Method result = methodCache.get(method);
if (null != result) {
return result;
}
result = getBaseClassMethodFor(method);
methodCache.put(method, result);
return result;
}
/**
* Returns whether the given method is considered to be a repository base
* class method.
*
* @param method
* @return
*/
private boolean isBaseClassMethod(Method method) {
Assert.notNull(method);
if (method.getDeclaringClass().isAssignableFrom(repositoryBaseClass)) {
return true;
}
return !method.equals(getBaseClassMethod(method));
}
/*
* (non-Javadoc)
*
* @see org.springframework.data.repository.support.RepositoryMetadata#
* getFinderMethods()
*/
public Iterable<Method> getQueryMethods() {
Set<Method> result = new HashSet<Method>();
for (Method method : repositoryInterface.getDeclaredMethods()) {
if (!isCustomMethod(method) && !isBaseClassMethod(method)) {
result.add(method);
}
}
return result;
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.support.RepositoryMetadata#isCustomMethod
* (java.lang.reflect.Method)
*/
public boolean isCustomMethod(Method method) {
Class<?> declaringClass = method.getDeclaringClass();
boolean isQueryMethod = declaringClass.equals(repositoryInterface);
boolean isRepositoryInterface =
isGenericRepositoryInterface(declaringClass);
boolean isBaseClassMethod = isBaseClassMethod(method);
return !(isRepositoryInterface || isBaseClassMethod || isQueryMethod);
}
/**
* Returns the given base class' method if the given method (declared in the
* repository interface) was also declared at the repository base class.
* Returns the given method if the given base class does not declare the
* method given. Takes generics into account.
*
* @param method
* @return
*/
Method getBaseClassMethodFor(Method method) {
for (Method baseClassMethod : repositoryBaseClass.getMethods()) {
// Wrong name
if (!method.getName().equals(baseClassMethod.getName())) {
continue;
}
// Wrong number of arguments
if (!(method.getParameterTypes().length == baseClassMethod
.getParameterTypes().length)) {
continue;
}
// Check whether all parameters match
if (!parametersMatch(method, baseClassMethod)) {
continue;
}
return baseClassMethod;
}
return method;
}
/*
* (non-Javadoc)
*
* @see org.springframework.data.repository.support.RepositoryMetadata#
* hasCustomMethod()
*/
public boolean hasCustomMethod() {
// No detection required if no typing interface was configured
if (isGenericRepositoryInterface(repositoryInterface)) {
return false;
}
for (Method method : repositoryInterface.getMethods()) {
if (isCustomMethod(method) && !isBaseClassMethod(method)) {
return true;
}
}
return false;
}
/**
* Checks the given method's parameters to match the ones of the given base
* class method. Matches generic arguments agains the ones bound in the
* given repository interface.
*
* @param method
* @param baseClassMethod
* @return
*/
private boolean parametersMatch(Method method, Method baseClassMethod) {
Type[] genericTypes = baseClassMethod.getGenericParameterTypes();
Class<?>[] types = baseClassMethod.getParameterTypes();
Class<?>[] methodParameters = method.getParameterTypes();
for (int i = 0; i < genericTypes.length; i++) {
Type type = genericTypes[i];
if (type instanceof TypeVariable<?>) {
String name = ((TypeVariable<?>) type).getName();
if (!matchesGenericType(name, methodParameters[i])) {
return false;
}
} else {
if (!types[i].equals(methodParameters[i])) {
return false;
}
}
}
return true;
}
/**
* Checks whether the given parameter type matches the generic type of the
* given parameter. Thus when {@literal PK} is declared, the method ensures
* that given method parameter is the primary key type declared in the given
* repository interface e.g.
*
* @param name
* @param parameterType
* @return
*/
private boolean matchesGenericType(String name, Class<?> parameterType) {
Class<?> entityType = getDomainClass();
Class<?> idClass = getIdClass();
if (ID_TYPE_NAME.equals(name) && parameterType.equals(idClass)) {
return true;
}
if (DOMAIN_TYPE_NAME.equals(name) && parameterType.equals(entityType)) {
return true;
}
return false;
}
}

67
spring-data-commons-core/src/main/java/org/springframework/data/repository/support/RepositoryFactorySupport.java

@ -124,12 +124,12 @@ public abstract class RepositoryFactorySupport { @@ -124,12 +124,12 @@ public abstract class RepositoryFactorySupport {
public <T> T getRepository(Class<T> repositoryInterface,
Object customImplementation) {
RepositoryMetadata metadata =
getRepositoryMetadata(repositoryInterface);
RepositoryMetadata metadata = getRepositoryMetadata(repositoryInterface);
RepositoryInformation information = getRepositoryInformation(metadata);
validate(metadata, customImplementation);
validate(information, customImplementation);
Object target = getTargetRepository(metadata);
Object target = getTargetRepository(information);
// Create proxy
ProxyFactory result = new ProxyFactory();
@ -140,22 +140,31 @@ public abstract class RepositoryFactorySupport { @@ -140,22 +140,31 @@ public abstract class RepositoryFactorySupport {
processor.postProcess(result);
}
result.addAdvice(new QueryExecuterMethodInterceptor(metadata,
result.addAdvice(new QueryExecuterMethodInterceptor(information,
customImplementation, target));
return (T) result.getProxy();
}
/**
* Returns the {@link RepositoryMetadata} for the given repository interface.
*
* @param repositoryInterface
* @return
*/
protected RepositoryMetadata getRepositoryMetadata(Class<?> repositoryInterface) {
RepositoryMetadata getRepositoryMetadata(Class<?> repositoryInterface) {
return new DefaultRepositoryMetadata(repositoryInterface);
}
return new DefaultRepositoryMetadata(repositoryInterface, getRepositoryBaseClass(repositoryInterface));
/**
* Returns the {@link RepositoryInformation} for the given repository interface.
*
* @param repositoryInterface
* @return
*/
private RepositoryInformation getRepositoryInformation(RepositoryMetadata metadata) {
return new DefaultRepositoryInformation(metadata, getRepositoryBaseClass(metadata));
}
@ -173,7 +182,7 @@ public abstract class RepositoryFactorySupport { @@ -173,7 +182,7 @@ public abstract class RepositoryFactorySupport {
/**
* Create a repository instance as backing for the query proxy.
*
* @param domainClass
* @param metadata
* @return
*/
protected abstract Object getTargetRepository(RepositoryMetadata metadata);
@ -184,11 +193,11 @@ public abstract class RepositoryFactorySupport { @@ -184,11 +193,11 @@ public abstract class RepositoryFactorySupport {
* {@link #getTargetRepository(RepositoryMetadata)} returns an instance of
* this class.
*
* @param repositoryInterface
* @param metadata
* @return
*/
protected abstract Class<?> getRepositoryBaseClass(
Class<?> repositoryInterface);
RepositoryMetadata metadata);
/**
* Returns the {@link QueryLookupStrategy} for the given {@link Key}.
@ -205,20 +214,26 @@ public abstract class RepositoryFactorySupport { @@ -205,20 +214,26 @@ public abstract class RepositoryFactorySupport {
* Validates the given repository interface as well as the given custom
* implementation.
*
* @param repositoryMetadata
* @param repositoryInformation
* @param customImplementation
*/
protected void validate(RepositoryMetadata repositoryMetadata,
private void validate(RepositoryInformation repositoryInformation,
Object customImplementation) {
if (null == customImplementation
&& repositoryMetadata.hasCustomMethod()) {
&& repositoryInformation.hasCustomMethod()) {
throw new IllegalArgumentException(
String.format(
"You have custom methods in %s but not provided a custom implementation!",
repositoryMetadata.getRepositoryInterface()));
repositoryInformation.getRepositoryInterface()));
}
validate(repositoryInformation);
}
protected void validate(RepositoryMetadata repositoryMetadata) {
}
/**
@ -236,7 +251,7 @@ public abstract class RepositoryFactorySupport { @@ -236,7 +251,7 @@ public abstract class RepositoryFactorySupport {
new ConcurrentHashMap<Method, RepositoryQuery>();
private final Object customImplementation;
private final RepositoryMetadata metadata;
private final RepositoryInformation repositoryInformation;
private final Object target;
@ -246,10 +261,10 @@ public abstract class RepositoryFactorySupport { @@ -246,10 +261,10 @@ public abstract class RepositoryFactorySupport {
* interface methods.
*/
public QueryExecuterMethodInterceptor(
RepositoryMetadata repositoryMetadata,
RepositoryInformation repositoryInformation,
Object customImplementation, Object target) {
this.metadata = repositoryMetadata;
this.repositoryInformation = repositoryInformation;
this.customImplementation = customImplementation;
this.target = target;
@ -258,7 +273,7 @@ public abstract class RepositoryFactorySupport { @@ -258,7 +273,7 @@ public abstract class RepositoryFactorySupport {
if (lookupStrategy == null) {
if (repositoryMetadata.hasCustomMethod()) {
if (repositoryInformation.hasCustomMethod()) {
throw new IllegalStateException(
"You have defined query method in the repository but " +
"you don't have no query lookup strategy defined. The " +
@ -268,19 +283,17 @@ public abstract class RepositoryFactorySupport { @@ -268,19 +283,17 @@ public abstract class RepositoryFactorySupport {
return;
}
for (Method method : metadata.getQueryMethods()) {
for (Method method : repositoryInformation.getQueryMethods()) {
RepositoryQuery query =
lookupStrategy.resolveQuery(method,
repositoryMetadata.getDomainClass());
invokeListeners(query, metadata);
lookupStrategy.resolveQuery(method,repositoryInformation);
invokeListeners(query);
queries.put(method, query);
}
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private void invokeListeners(RepositoryQuery query,
RepositoryMetadata metadata) {
private void invokeListeners(RepositoryQuery query) {
for (QueryCreationListener listener : queryPostProcessors) {
Class<?> typeArgument =
@ -319,7 +332,7 @@ public abstract class RepositoryFactorySupport { @@ -319,7 +332,7 @@ public abstract class RepositoryFactorySupport {
// Lookup actual method as it might be redeclared in the interface
// and we have to use the repository instance nevertheless
Method actualMethod = metadata.getBaseClassMethod(method);
Method actualMethod = repositoryInformation.getBaseClassMethod(method);
return executeMethodOn(target, actualMethod,
invocation.getArguments());
}
@ -374,7 +387,7 @@ public abstract class RepositoryFactorySupport { @@ -374,7 +387,7 @@ public abstract class RepositoryFactorySupport {
return false;
}
return metadata.isCustomMethod(invocation.getMethod());
return repositoryInformation.isCustomMethod(invocation.getMethod());
}
}
}

75
spring-data-commons-core/src/main/java/org/springframework/data/repository/support/RepositoryInformation.java

@ -0,0 +1,75 @@ @@ -0,0 +1,75 @@
/*
* 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 java.lang.reflect.Method;
/**
* Aditional repository specific information
*
* @author Oliver Gierke
*/
interface RepositoryInformation extends RepositoryMetadata {
/**
* Returns the base class to be used to create the proxy backing instance.
*
* @return
*/
Class<?> getRepositoryBaseClass();
/**
* Returns if the configured repository interface has custom methods, that
* might have to be delegated to a custom implementation. This is used to
* verify repository configuration.
*
* @return
*/
boolean hasCustomMethod();
/**
* Returns whether the given method is a custom repository method.
*
* @param method
* @param baseClass
* @return
*/
boolean isCustomMethod(Method method);
/**
* Returns all methods considered to be query methods.
*
* @param repositoryInterface
* @return
*/
Iterable<Method> getQueryMethods();
/**
* Returns the base class method that is backing the given method. This can
* be necessary if a repository interface redeclares a method of the core
* repository interface (e.g. for transaction behaviour customization).
* Returns the method itself if the base class does not implement the given
* method.
*
* @param method
* @return
*/
Method getBaseClassMethod(Method method);
}

69
spring-data-commons-core/src/main/java/org/springframework/data/repository/support/RepositoryMetadata.java

@ -15,7 +15,6 @@ @@ -15,7 +15,6 @@
*/
package org.springframework.data.repository.support;
import java.lang.reflect.Method;
/**
@ -26,62 +25,13 @@ import java.lang.reflect.Method; @@ -26,62 +25,13 @@ import java.lang.reflect.Method;
public interface RepositoryMetadata {
/**
* Returns the repository interface.
*
* @return
*/
Class<?> getRepositoryInterface();
/**
* Returns the base class to be used to create the proxy backing instance.
*
* @return
*/
Class<?> getRepositoryBaseClass();
/**
* Returns if the configured repository interface has custom methods, that
* might have to be delegated to a custom implementation. This is used to
* verify repository configuration.
*
* @return
*/
boolean hasCustomMethod();
/**
* Returns whether the given method is a custom repository method.
*
* @param method
* @param baseClass
* @return
*/
boolean isCustomMethod(Method method);
/**
* Returns all methods considered to be query methods.
*
* @param repositoryInterface
* @return
*/
Iterable<Method> getQueryMethods();
/**
* Returns the base class method that is backing the given method. This can
* be necessary if a repository interface redeclares a method of the core
* repository interface (e.g. for transaction behaviour customization).
* Returns the method itself if the base class does not implement the given
* method.
* Returns the id class the given class is declared for.
*
* @param method
* @return
* @param clazz
* @return the id class of the entity managed by the repository for or
* {@code null} if none found.
*/
Method getBaseClassMethod(Method method);
Class<?> getIdClass();
/**
* Returns the domain class the repository is declared for.
@ -92,13 +42,10 @@ public interface RepositoryMetadata { @@ -92,13 +42,10 @@ public interface RepositoryMetadata {
*/
Class<?> getDomainClass();
/**
* Returns the id class the given class is declared for.
* Returns the repository interface.
*
* @param clazz
* @return the id class of the entity managed by the repository for or
* {@code null} if none found.
* @return
*/
Class<?> getIdClass();
Class<?> getRepositoryInterface();
}

6
spring-data-commons-core/src/main/java/org/springframework/data/transaction/ChangeSetBackedTransactionSynchronization.java

@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
package org.springframework.data.transaction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.data.persistence.ChangeSetBacked;
import org.springframework.data.persistence.ChangeSetPersister;
import org.springframework.transaction.support.TransactionSynchronization;
public class ChangeSetBackedTransactionSynchronization implements TransactionSynchronization {
protected final Logger log = LoggerFactory.getLogger(getClass());
protected final Log log = LogFactory.getLog(getClass());
private ChangeSetPersister<Object> changeSetPersister;

63
spring-data-commons-core/src/test/java/org/springframework/data/repository/support/DefaultRepositoryInformationUnitTests.java

@ -0,0 +1,63 @@ @@ -0,0 +1,63 @@
package org.springframework.data.repository.support;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import java.lang.reflect.Method;
import org.junit.Test;
import org.springframework.data.repository.Repository;
import org.springframework.data.repository.support.DefaultRepositoryMetadataUnitTests.DummyGenericRepositorySupport;
/**
*
* @author Oliver Gierke
*/
public class DefaultRepositoryInformationUnitTests {
@SuppressWarnings("rawtypes")
static final Class<DummyGenericRepositorySupport> REPOSITORY = DummyGenericRepositorySupport.class;
@Test
public void discoversRepositoryBaseClassMethod() throws Exception {
Method method = FooDao.class.getMethod("findOne", Integer.class);
RepositoryMetadata metadata = new DefaultRepositoryMetadata(FooDao.class);
DefaultRepositoryInformation information = new DefaultRepositoryInformation(metadata, REPOSITORY);
Method reference = information.getBaseClassMethodFor(method);
assertEquals(REPOSITORY, reference.getDeclaringClass());
assertThat(reference.getName(), is("findOne"));
}
@Test
public void discoveresNonRepositoryBaseClassMethod() throws Exception {
Method method = FooDao.class.getMethod("findOne", Long.class);
RepositoryMetadata metadata = new DefaultRepositoryMetadata(FooDao.class);
DefaultRepositoryInformation information = new DefaultRepositoryInformation(metadata, Repository.class);
assertThat(information.getBaseClassMethodFor(method), is(method));
}
private static interface FooDao extends Repository<User, Integer> {
// Redeclared method
User findOne(Integer primaryKey);
// Not a redeclared method
User findOne(Long primaryKey);
}
@SuppressWarnings("unused")
private class User {
private String firstname;
public String getAddress() {
return null;
}
}
}

52
spring-data-commons-core/src/test/java/org/springframework/data/repository/support/DefaultRepositoryMetadataUnitTests.java

@ -15,11 +15,9 @@ @@ -15,11 +15,9 @@
*/
package org.springframework.data.repository.support;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import java.io.Serializable;
import java.lang.reflect.Method;
import org.junit.Test;
import org.springframework.data.domain.Page;
@ -35,19 +33,14 @@ import org.springframework.data.repository.util.ClassUtils; @@ -35,19 +33,14 @@ import org.springframework.data.repository.util.ClassUtils;
*/
public class DefaultRepositoryMetadataUnitTests {
@SuppressWarnings("rawtypes")
static final Class<DummyGenericRepositorySupport> REPOSITORY =
DummyGenericRepositorySupport.class;
@Test
public void looksUpDomainClassCorrectly() throws Exception {
RepositoryMetadata metadata =
new DefaultRepositoryMetadata(UserRepository.class, REPOSITORY);
new DefaultRepositoryMetadata(UserRepository.class);
assertEquals(User.class, metadata.getDomainClass());
metadata = new DefaultRepositoryMetadata(SomeDao.class, REPOSITORY);
metadata = new DefaultRepositoryMetadata(SomeDao.class);
assertEquals(User.class, metadata.getDomainClass());
}
@ -57,7 +50,7 @@ public class DefaultRepositoryMetadataUnitTests { @@ -57,7 +50,7 @@ public class DefaultRepositoryMetadataUnitTests {
RepositoryMetadata metadata =
new DefaultRepositoryMetadata(
ExtensionOfUserCustomExtendedDao.class, REPOSITORY);
ExtensionOfUserCustomExtendedDao.class);
assertEquals(User.class, metadata.getDomainClass());
}
@ -66,8 +59,7 @@ public class DefaultRepositoryMetadataUnitTests { @@ -66,8 +59,7 @@ public class DefaultRepositoryMetadataUnitTests {
public void detectsParameterizedEntitiesCorrectly() {
RepositoryMetadata metadata =
new DefaultRepositoryMetadata(GenericEntityRepository.class,
REPOSITORY);
new DefaultRepositoryMetadata(GenericEntityRepository.class);
assertEquals(GenericEntity.class, metadata.getDomainClass());
}
@ -76,36 +68,12 @@ public class DefaultRepositoryMetadataUnitTests { @@ -76,36 +68,12 @@ public class DefaultRepositoryMetadataUnitTests {
public void looksUpIdClassCorrectly() throws Exception {
RepositoryMetadata metadata =
new DefaultRepositoryMetadata(UserRepository.class, REPOSITORY);
new DefaultRepositoryMetadata(UserRepository.class);
assertEquals(Integer.class, metadata.getIdClass());
}
@Test
public void discoversRepositoryBaseClassMethod() throws Exception {
Method method = FooDao.class.getMethod("findOne", Integer.class);
DefaultRepositoryMetadata metadata =
new DefaultRepositoryMetadata(FooDao.class, REPOSITORY);
Method reference = metadata.getBaseClassMethodFor(method);
assertEquals(REPOSITORY, reference.getDeclaringClass());
assertThat(reference.getName(), is("findOne"));
}
@Test
public void discoveresNonRepositoryBaseClassMethod() throws Exception {
Method method = FooDao.class.getMethod("findOne", Long.class);
DefaultRepositoryMetadata metadata =
new DefaultRepositoryMetadata(FooDao.class, Repository.class);
assertThat(metadata.getBaseClassMethodFor(method), is(method));
}
@SuppressWarnings("unused")
private class User {
@ -138,16 +106,6 @@ public class DefaultRepositoryMetadataUnitTests { @@ -138,16 +106,6 @@ public class DefaultRepositoryMetadataUnitTests {
Page<User> findByFirstname(Pageable pageable, String firstname);
}
private static interface FooDao extends Repository<User, Integer> {
// Redeclared method
User findOne(Integer primaryKey);
// Not a redeclared method
User findOne(Long primaryKey);
}
/**
* Sample interface to test recursive lookup of domain class.
*

12
spring-data-commons-core/src/test/java/org/springframework/data/repository/support/QueryExecuterMethodInterceptorUnitTests.java

@ -36,24 +36,24 @@ public class QueryExecuterMethodInterceptorUnitTests { @@ -36,24 +36,24 @@ public class QueryExecuterMethodInterceptorUnitTests {
@Mock
RepositoryFactorySupport factory;
@Mock
RepositoryMetadata metadata;
RepositoryInformation information;
@Test(expected=IllegalStateException.class)
public void rejectsRepositoryInterfaceWithQueryMethodsIfNoQueryLookupStrategyIsDefined() {
when(metadata.hasCustomMethod()).thenReturn(true);
when(information.hasCustomMethod()).thenReturn(true);
when(factory.getQueryLookupStrategy(any(Key.class))).thenReturn(null);
factory.new QueryExecuterMethodInterceptor(metadata, null, new Object());
factory.new QueryExecuterMethodInterceptor(information, null, new Object());
}
@Test
public void skipsQueryLookupsIfQueryLookupStrategyIsNull() {
when(metadata.hasCustomMethod()).thenReturn(false);
when(information.hasCustomMethod()).thenReturn(false);
when(factory.getQueryLookupStrategy(any(Key.class))).thenReturn(null);
factory.new QueryExecuterMethodInterceptor(metadata, null, new Object());
verify(metadata, times(0)).getQueryMethods();
factory.new QueryExecuterMethodInterceptor(information, null, new Object());
verify(information, times(0)).getQueryMethods();
}
}

4
spring-data-commons-core/src/test/java/org/springframework/data/repository/support/RepositoryFactorySupportUnitTests.java

@ -82,7 +82,7 @@ public class RepositoryFactorySupportUnitTests { @@ -82,7 +82,7 @@ public class RepositoryFactorySupportUnitTests {
@Override
protected Class<?> getRepositoryBaseClass(Class<?> repositoryInterface) {
protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
return Object.class;
}
@ -95,7 +95,7 @@ public class RepositoryFactorySupportUnitTests { @@ -95,7 +95,7 @@ public class RepositoryFactorySupportUnitTests {
RepositoryQuery queryTwo = mock(RepositoryQuery.class);
QueryLookupStrategy strategy = mock(QueryLookupStrategy.class);
when(strategy.resolveQuery(any(Method.class), any(Class.class)))
when(strategy.resolveQuery(any(Method.class), any(RepositoryMetadata.class)))
.thenReturn(queryOne, queryTwo);
return strategy;

24
spring-data-commons-parent/pom.xml

@ -14,7 +14,6 @@ @@ -14,7 +14,6 @@
<junit.version>4.8.1</junit.version>
<log4j.version>1.2.16</log4j.version>
<org.mockito.version>1.8.4</org.mockito.version>
<org.slf4j.version>1.5.10</org.slf4j.version>
<org.springframework.version>3.0.5.RELEASE</org.springframework.version>
</properties>
<profiles>
@ -99,12 +98,6 @@ @@ -99,12 +98,6 @@
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${org.springframework.version}</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
@ -136,23 +129,6 @@ @@ -136,23 +129,6 @@
</dependency>
<!-- Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${org.slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${org.slf4j.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${org.slf4j.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>

Loading…
Cancel
Save