diff --git a/spring-data-commons-core/pom.xml b/spring-data-commons-core/pom.xml
index 9b8c48dab..337812e7e 100644
--- a/spring-data-commons-core/pom.xml
+++ b/spring-data-commons-core/pom.xml
@@ -35,24 +35,10 @@
-
- org.slf4j
- slf4j-api
-
-
- org.slf4j
- jcl-over-slf4j
- test
-
-
- org.slf4j
- slf4j-log4j12
- test
-
log4j
log4j
- runtime
+ test
diff --git a/spring-data-commons-core/src/main/java/org/springframework/data/mapping/BasicMappingContext.java b/spring-data-commons-core/src/main/java/org/springframework/data/mapping/BasicMappingContext.java
index 13e3a5d01..bd8dbeb8c 100644
--- a/spring-data-commons-core/src/main/java/org/springframework/data/mapping/BasicMappingContext.java
+++ b/spring-data-commons-core/src/main/java/org/springframework/data/mapping/BasicMappingContext.java
@@ -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
private static final Set UNMAPPED_FIELDS = new HashSet(Arrays.asList("class", "this$0"));
- protected Logger log = LoggerFactory.getLogger(getClass());
+ protected Log log = LogFactory.getLog(getClass());
protected ApplicationEventPublisher applicationEventPublisher;
protected ConcurrentMap> persistentEntities = new ConcurrentHashMap>();
protected ConcurrentMap, List> validators = new ConcurrentHashMap, List>();
diff --git a/spring-data-commons-core/src/main/java/org/springframework/data/mapping/MappingBeanHelper.java b/spring-data-commons-core/src/main/java/org/springframework/data/mapping/MappingBeanHelper.java
index c113138fc..0be10d80a 100644
--- a/spring-data-commons-core/src/main/java/org/springframework/data/mapping/MappingBeanHelper.java
+++ b/spring-data-commons-core/src/main/java/org/springframework/data/mapping/MappingBeanHelper.java
@@ -48,13 +48,21 @@ public abstract class MappingBeanHelper {
static {
simpleTypes.add(boolean.class);
+ simpleTypes.add(boolean[].class);
simpleTypes.add(long.class);
+ simpleTypes.add(long[].class);
simpleTypes.add(short.class);
+ simpleTypes.add(short[].class);
simpleTypes.add(int.class);
+ simpleTypes.add(int[].class);
simpleTypes.add(byte.class);
+ simpleTypes.add(byte[].class);
simpleTypes.add(float.class);
+ simpleTypes.add(float[].class);
simpleTypes.add(double.class);
+ simpleTypes.add(double[].class);
simpleTypes.add(char.class);
+ simpleTypes.add(char[].class);
simpleTypes.add(Boolean.class);
simpleTypes.add(Long.class);
simpleTypes.add(Short.class);
diff --git a/spring-data-commons-core/src/main/java/org/springframework/data/mapping/context/MappingContextAware.java b/spring-data-commons-core/src/main/java/org/springframework/data/mapping/context/MappingContextAware.java
new file mode 100644
index 000000000..0513804e1
--- /dev/null
+++ b/spring-data-commons-core/src/main/java/org/springframework/data/mapping/context/MappingContextAware.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2011 by the original author(s).
+ *
+ * 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.mapping.context;
+
+import org.springframework.data.mapping.model.MappingContext;
+
+/**
+ * An interface to make beans aware of the active MappingContext in the current ApplicationContext.
+ *
+ * @author Jon Brisbin
+ */
+public interface MappingContextAware {
+
+ /**
+ * The active MappingContext for the environment.
+ *
+ * @param mappingContext
+ */
+ void setMappingContext(MappingContext mappingContext);
+
+}
diff --git a/spring-data-commons-core/src/main/java/org/springframework/data/mapping/context/MappingContextAwareBeanPostProcessor.java b/spring-data-commons-core/src/main/java/org/springframework/data/mapping/context/MappingContextAwareBeanPostProcessor.java
new file mode 100644
index 000000000..b36a2978f
--- /dev/null
+++ b/spring-data-commons-core/src/main/java/org/springframework/data/mapping/context/MappingContextAwareBeanPostProcessor.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2011 by the original author(s).
+ *
+ * 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.mapping.context;
+
+import java.util.Map;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.config.BeanPostProcessor;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.data.mapping.model.MappingContext;
+
+/**
+ * BeanPostProcessor to make Spring beans aware of the current MappingContext. If a MappingContext exists with the
+ * default bean name ("mappingContext"), then that bean is used. If there is no MappingContext registered under the
+ * default bean name, then the first MappingContext it finds is the one it chooses.
+ *
+ * @author Jon Brisbin
+ */
+public class MappingContextAwareBeanPostProcessor implements BeanPostProcessor, ApplicationContextAware {
+
+ private ApplicationContext applicationContext;
+ private String mappingContextBeanName = "mappingContext";
+ private MappingContext mappingContext;
+
+ public MappingContextAwareBeanPostProcessor() {
+ }
+
+ public MappingContextAwareBeanPostProcessor(MappingContext mappingContext) {
+ this.mappingContext = mappingContext;
+ }
+
+ public String getMappingContextBeanName() {
+ return mappingContextBeanName;
+ }
+
+ public void setMappingContextBeanName(String mappingContextBeanName) {
+ this.mappingContextBeanName = mappingContextBeanName;
+ }
+
+ @Override
+ public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+ this.applicationContext = applicationContext;
+ }
+
+ @Override
+ public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
+ return bean;
+ }
+
+ @Override
+ public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
+ if (bean instanceof MappingContextAware) {
+ if (null == mappingContext) {
+ Map mappingContexts = applicationContext.getBeansOfType(MappingContext.class);
+ if (mappingContexts.containsKey(mappingContextBeanName)) {
+ this.mappingContext = mappingContexts.get(mappingContextBeanName);
+ } else {
+ String firstBean = mappingContexts.keySet().iterator().next();
+ this.mappingContext = applicationContext.getBean(firstBean, MappingContext.class);
+ }
+ }
+ ((MappingContextAware) bean).setMappingContext(mappingContext);
+ }
+ return bean;
+ }
+}
diff --git a/spring-data-commons-core/src/main/java/org/springframework/data/persistence/AbstractConstructorEntityInstantiator.java b/spring-data-commons-core/src/main/java/org/springframework/data/persistence/AbstractConstructorEntityInstantiator.java
index 146a70c11..3109d29a8 100644
--- a/spring-data-commons-core/src/main/java/org/springframework/data/persistence/AbstractConstructorEntityInstantiator.java
+++ b/spring-data-commons-core/src/main/java/org/springframework/data/persistence/AbstractConstructorEntityInstantiator.java
@@ -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 sun.reflect.ReflectionFactory;
@@ -18,7 +18,7 @@ import java.util.Map;
*/
public abstract class AbstractConstructorEntityInstantiator implements EntityInstantiator {
- private final Logger log = LoggerFactory.getLogger(getClass());
+ private final Log log = LogFactory.getLog(getClass());
private final Map,StateBackedCreator extends BACKING_INTERFACE,STATE>> cache = new HashMap,StateBackedCreator extends BACKING_INTERFACE,STATE>>();
public T createEntityFromState(STATE n, Class c) {
diff --git a/spring-data-commons-core/src/main/java/org/springframework/data/repository/config/AbstractRepositoryConfigDefinitionParser.java b/spring-data-commons-core/src/main/java/org/springframework/data/repository/config/AbstractRepositoryConfigDefinitionParser.java
index 63039f087..33dd0b7c8 100644
--- a/spring-data-commons-core/src/main/java/org/springframework/data/repository/config/AbstractRepositoryConfigDefinitionParser.java
+++ b/spring-data-commons-core/src/main/java/org/springframework/data/repository/config/AbstractRepositoryConfigDefinitionParser.java
@@ -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;
public abstract class AbstractRepositoryConfigDefinitionParser, T extends SingleRepositoryConfigInformation>
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 domainClass);
+ RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata);
}
\ No newline at end of file
diff --git a/spring-data-commons-core/src/main/java/org/springframework/data/repository/query/QueryMethod.java b/spring-data-commons-core/src/main/java/org/springframework/data/repository/query/QueryMethod.java
index eeca97b92..3c06c2a22 100644
--- a/spring-data-commons-core/src/main/java/org/springframework/data/repository/query/QueryMethod.java
+++ b/spring-data-commons-core/src/main/java/org/springframework/data/repository/query/QueryMethod.java
@@ -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 {
SINGLE_ENTITY, PAGING, COLLECTION, MODIFYING;
}
+ private final RepositoryMetadata metadata;
private final Method method;
private final Parameters parameters;
@@ -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 {
this.method = method;
this.parameters = new Parameters(method);
+ this.metadata = metadata;
}
@@ -103,8 +106,12 @@ public class QueryMethod {
protected Class> getDomainClass() {
+
+ Class> repositoryDomainClass = metadata.getDomainClass();
+ Class> methodDomainClass = ClassUtils.getReturnedDomainClass(method);
- return ClassUtils.getReturnedDomainClass(method);
+ return repositoryDomainClass == null || repositoryDomainClass.isAssignableFrom(methodDomainClass) ? methodDomainClass
+ : repositoryDomainClass;
}
diff --git a/spring-data-commons-core/src/main/java/org/springframework/data/repository/support/DefaultRepositoryInformation.java b/spring-data-commons-core/src/main/java/org/springframework/data/repository/support/DefaultRepositoryInformation.java
new file mode 100644
index 000000000..33ae52b1f
--- /dev/null
+++ b/spring-data-commons-core/src/main/java/org/springframework/data/repository/support/DefaultRepositoryInformation.java
@@ -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>[] 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 methodCache = new ConcurrentHashMap();
+
+ 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 getQueryMethods() {
+
+ Set result = new HashSet();
+
+ 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;
+ }
+}
diff --git a/spring-data-commons-core/src/main/java/org/springframework/data/repository/support/DefaultRepositoryMetadata.java b/spring-data-commons-core/src/main/java/org/springframework/data/repository/support/DefaultRepositoryMetadata.java
index e776bc1ed..b7ad5b251 100644
--- a/spring-data-commons-core/src/main/java/org/springframework/data/repository/support/DefaultRepositoryMetadata.java
+++ b/spring-data-commons-core/src/main/java/org/springframework/data/repository/support/DefaultRepositoryMetadata.java
@@ -37,17 +37,7 @@ import org.springframework.util.Assert;
*/
public class DefaultRepositoryMetadata implements RepositoryMetadata {
- @SuppressWarnings("rawtypes")
- private static final TypeVariable>[] 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 methodCache =
- new ConcurrentHashMap();
-
private final Class> repositoryInterface;
- private final Class> repositoryBaseClass;
/**
@@ -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 {
}
- /*
- * (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 {
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 getQueryMethods() {
-
- Set result = new HashSet();
-
- 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;
- }
}
diff --git a/spring-data-commons-core/src/main/java/org/springframework/data/repository/support/RepositoryFactorySupport.java b/spring-data-commons-core/src/main/java/org/springframework/data/repository/support/RepositoryFactorySupport.java
index 5aefd18ae..c4ecf35dd 100644
--- a/spring-data-commons-core/src/main/java/org/springframework/data/repository/support/RepositoryFactorySupport.java
+++ b/spring-data-commons-core/src/main/java/org/springframework/data/repository/support/RepositoryFactorySupport.java
@@ -124,12 +124,12 @@ public abstract class RepositoryFactorySupport {
public T getRepository(Class 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 {
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) {
-
- return new DefaultRepositoryMetadata(repositoryInterface, getRepositoryBaseClass(repositoryInterface));
+ RepositoryMetadata getRepositoryMetadata(Class> repositoryInterface) {
+ return new DefaultRepositoryMetadata(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 {
/**
* 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 {
* {@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 {
* 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 {
new ConcurrentHashMap();
private final Object customImplementation;
- private final RepositoryMetadata metadata;
+ private final RepositoryInformation repositoryInformation;
private final Object target;
@@ -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 {
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 {
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 {
// 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 {
return false;
}
- return metadata.isCustomMethod(invocation.getMethod());
+ return repositoryInformation.isCustomMethod(invocation.getMethod());
}
}
}
diff --git a/spring-data-commons-core/src/main/java/org/springframework/data/repository/support/RepositoryInformation.java b/spring-data-commons-core/src/main/java/org/springframework/data/repository/support/RepositoryInformation.java
new file mode 100644
index 000000000..62b878833
--- /dev/null
+++ b/spring-data-commons-core/src/main/java/org/springframework/data/repository/support/RepositoryInformation.java
@@ -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 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);
+}
diff --git a/spring-data-commons-core/src/main/java/org/springframework/data/repository/support/RepositoryMetadata.java b/spring-data-commons-core/src/main/java/org/springframework/data/repository/support/RepositoryMetadata.java
index 9d75b7862..07972f75b 100644
--- a/spring-data-commons-core/src/main/java/org/springframework/data/repository/support/RepositoryMetadata.java
+++ b/spring-data-commons-core/src/main/java/org/springframework/data/repository/support/RepositoryMetadata.java
@@ -15,7 +15,6 @@
*/
package org.springframework.data.repository.support;
-import java.lang.reflect.Method;
/**
@@ -24,81 +23,29 @@ import java.lang.reflect.Method;
* @author Oliver Gierke
*/
public interface RepositoryMetadata {
+
+ /**
+ * Returns the id class the given class is declared for.
+ *
+ * @param clazz
+ * @return the id class of the entity managed by the repository for or
+ * {@code null} if none found.
+ */
+ Class> getIdClass();
- /**
- * Returns the repository interface.
- *
- * @return
- */
- Class> getRepositoryInterface();
+ /**
+ * Returns the domain class the repository is declared for.
+ *
+ * @param clazz
+ * @return the domain class the repository is handling or {@code null} if
+ * none found.
+ */
+ Class> getDomainClass();
-
- /**
- * 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 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);
-
-
- /**
- * Returns the domain class the repository is declared for.
- *
- * @param clazz
- * @return the domain class the repository is handling or {@code null} if
- * none found.
- */
- Class> getDomainClass();
-
-
- /**
- * Returns the id class the given class is declared for.
- *
- * @param clazz
- * @return the id class of the entity managed by the repository for or
- * {@code null} if none found.
- */
- Class> getIdClass();
+ /**
+ * Returns the repository interface.
+ *
+ * @return
+ */
+ Class> getRepositoryInterface();
}
diff --git a/spring-data-commons-core/src/main/java/org/springframework/data/transaction/ChangeSetBackedTransactionSynchronization.java b/spring-data-commons-core/src/main/java/org/springframework/data/transaction/ChangeSetBackedTransactionSynchronization.java
index 5ea9353d6..a13afcfe5 100644
--- a/spring-data-commons-core/src/main/java/org/springframework/data/transaction/ChangeSetBackedTransactionSynchronization.java
+++ b/spring-data-commons-core/src/main/java/org/springframework/data/transaction/ChangeSetBackedTransactionSynchronization.java
@@ -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
org.springframework
@@ -136,23 +129,6 @@
-
- org.slf4j
- slf4j-api
- ${org.slf4j.version}
-
-
- org.slf4j
- jcl-over-slf4j
- ${org.slf4j.version}
- runtime
-
-
- org.slf4j
- slf4j-log4j12
- ${org.slf4j.version}
- runtime
-
log4j
log4j