Permalink
Browse files

DATACMNS-41 - Refactored DefaultRepositoryInformation to take custom …

…implementation class into account as well.
  • Loading branch information...
olivergierke committed May 31, 2011
1 parent 399bc5e commit 70da7b00f8731187f972543167e9c8e52201d10f
@@ -5,6 +5,11 @@
<projects>
</projects>
<buildSpec>
+ <buildCommand>
+ <name>org.eclipse.wst.common.project.facet.core.builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
@@ -15,9 +20,16 @@
<arguments>
</arguments>
</buildCommand>
+ <buildCommand>
+ <name>org.eclipse.wst.validation.validationbuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.maven.ide.eclipse.maven2Nature</nature>
+ <nature>org.eclipse.wst.common.project.facet.core.nature</nature>
+ <nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
</natures>
</projectDescription>
@@ -33,7 +33,7 @@
*
* @author Oliver Gierke
*/
-public class DefaultRepositoryInformation implements RepositoryInformation {
+class DefaultRepositoryInformation implements RepositoryInformation {
@SuppressWarnings("rawtypes")
private static final TypeVariable<Class<Repository>>[] PARAMETERS = Repository.class.getTypeParameters();
@@ -44,71 +44,76 @@
private final RepositoryMetadata metadata;
private final Class<?> repositoryBaseClass;
+ private final Class<?> customImplementationClass;
/**
* Creates a new {@link DefaultRepositoryMetadata} for the given repository interface and repository base class.
*
- * @param repositoryInterface
+ * @param metadata
+ * @param repositoryBaseClass
+ * @param customImplementationClass
*/
- public DefaultRepositoryInformation(RepositoryMetadata metadata, Class<?> repositoryBaseClass) {
+ public DefaultRepositoryInformation(RepositoryMetadata metadata, Class<?> repositoryBaseClass, Class<?> customImplementationClass) {
Assert.notNull(metadata);
Assert.notNull(repositoryBaseClass);
this.metadata = metadata;
this.repositoryBaseClass = repositoryBaseClass;
+ this.customImplementationClass = customImplementationClass;
}
- /* (non-Javadoc)
- * @see org.springframework.data.repository.support.RepositoryMetadata#getRepositoryInterface()
- */
+ /*
+ * (non-Javadoc)
+ * @see org.springframework.data.repository.support.RepositoryMetadata#getRepositoryInterface()
+ */
public Class<?> getRepositoryInterface() {
return metadata.getRepositoryInterface();
}
- /* (non-Javadoc)
- * @see org.springframework.data.repository.support.RepositoryMetadata#getDomainClass()
- */
+ /*
+ * (non-Javadoc)
+ * @see org.springframework.data.repository.support.RepositoryMetadata#getDomainClass()
+ */
public Class<?> getDomainClass() {
return metadata.getDomainClass();
}
- /* (non-Javadoc)
- * @see org.springframework.data.repository.support.RepositoryMetadata#getIdClass()
- */
+ /*
+ * (non-Javadoc)
+ * @see org.springframework.data.repository.support.RepositoryMetadata#getIdClass()
+ */
public Class<?> getIdClass() {
return metadata.getIdClass();
}
/*
- * (non-Javadoc)
- *
- * @see org.springframework.data.repository.support.RepositoryMetadata#
- * getRepositoryBaseClass()
- */
+ * (non-Javadoc)
+ * @see org.springframework.data.repository.support.RepositoryInformation#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) {
+ * (non-Javadoc)
+ * @see org.springframework.data.repository.support.RepositoryInformation#getTargetClassMethod(java.lang.reflect.Method)
+ */
+ public Method getTargetClassMethod(Method method) {
+
+ if (methodCache.containsKey(method)) {
+ return methodCache.get(method);
+ }
+
+ Method result = getTargetClassMethod(method, customImplementationClass);
+
+ if (!result.equals(method)) {
+ methodCache.put(method, result);
return result;
}
-
- result = getBaseClassMethodFor(method);
+
+ result = getTargetClassMethod(method, repositoryBaseClass);
methodCache.put(method, result);
-
return result;
}
@@ -118,28 +123,31 @@ public Method getBaseClassMethod(Method method) {
* @param method
* @return
*/
- private boolean isBaseClassMethod(Method method) {
+ private boolean isTargetClassMethod(Method method, Class<?> targetType) {
Assert.notNull(method);
+
+ if (targetType == null) {
+ return false;
+ }
- if (method.getDeclaringClass().isAssignableFrom(repositoryBaseClass)) {
+ if (method.getDeclaringClass().isAssignableFrom(targetType)) {
return true;
}
- return !method.equals(getBaseClassMethod(method));
+ return !method.equals(getTargetClassMethod(method, targetType));
}
+
/*
- * (non-Javadoc)
- *
- * @see org.springframework.data.repository.support.RepositoryMetadata#
- * getFinderMethods()
- */
+ * (non-Javadoc)
+ * @see org.springframework.data.repository.support.RepositoryInformation#getQueryMethods()
+ */
public Iterable<Method> getQueryMethods() {
Set<Method> result = new HashSet<Method>();
- for (Method method : getRepositoryInterface().getDeclaredMethods()) {
+ for (Method method : getRepositoryInterface().getMethods()) {
if (!isCustomMethod(method) && !isBaseClassMethod(method)) {
result.add(method);
}
@@ -149,34 +157,39 @@ private boolean isBaseClassMethod(Method method) {
}
/*
- * (non-Javadoc)
- *
- * @see
- * org.springframework.data.repository.support.RepositoryMetadata#isCustomMethod
- * (java.lang.reflect.Method)
- */
+ * (non-Javadoc)
+ * @see org.springframework.data.repository.support.RepositoryInformation#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);
+ return isTargetClassMethod(method, customImplementationClass);
+ }
+
+ /**
+ * Returns whether the given method is a method covered by the base implementation.
+ *
+ * @param method
+ * @return
+ */
+ public boolean isBaseClassMethod(Method method) {
+ return isTargetClassMethod(method, repositoryBaseClass);
}
/**
- * 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.
+ * Returns the given target class' method if the given method (declared in the repository interface) was also declared
+ * at the target class. Returns the given method if the given base class does not declare the method given.
* Takes generics into account.
*
- * @param method
+ * @param method must not be {@literal null}
+ * @param baseClass
* @return
*/
- Method getBaseClassMethodFor(Method method) {
+ Method getTargetClassMethod(Method method, Class<?> baseClass) {
+
+ if (baseClass == null) {
+ return method;
+ }
- for (Method baseClassMethod : repositoryBaseClass.getMethods()) {
+ for (Method baseClassMethod : baseClass.getMethods()) {
// Wrong name
if (!method.getName().equals(baseClassMethod.getName())) {
@@ -200,11 +213,9 @@ Method getBaseClassMethodFor(Method method) {
}
/*
- * (non-Javadoc)
- *
- * @see org.springframework.data.repository.support.RepositoryMetadata#
- * hasCustomMethod()
- */
+ * (non-Javadoc)
+ * @see org.springframework.data.repository.support.RepositoryInformation#hasCustomMethod()
+ */
public boolean hasCustomMethod() {
Class<?> repositoryInterface = getRepositoryInterface();
@@ -125,7 +125,8 @@ public void addRepositoryProxyPostProcessor(
Object customImplementation) {
RepositoryMetadata metadata = getRepositoryMetadata(repositoryInterface);
- RepositoryInformation information = getRepositoryInformation(metadata);
+ Class<?> customImplementationClass = null == customImplementation ? null : customImplementation.getClass();
+ RepositoryInformation information = getRepositoryInformation(metadata, customImplementationClass);
validate(information, customImplementation);
@@ -162,10 +163,11 @@ RepositoryMetadata getRepositoryMetadata(Class<?> repositoryInterface) {
* Returns the {@link RepositoryInformation} for the given repository interface.
*
* @param repositoryInterface
+ * @param customImplementationClass
* @return
*/
- private RepositoryInformation getRepositoryInformation(RepositoryMetadata metadata) {
- return new DefaultRepositoryInformation(metadata, getRepositoryBaseClass(metadata));
+ private RepositoryInformation getRepositoryInformation(RepositoryMetadata metadata, Class<?> customImplementationClass) {
+ return new DefaultRepositoryInformation(metadata, getRepositoryBaseClass(metadata), customImplementationClass);
}
@@ -321,9 +323,9 @@ public Object invoke(MethodInvocation invocation) throws Throwable {
Method method = invocation.getMethod();
if (isCustomMethodInvocation(invocation)) {
-
- makeAccessible(method);
- return executeMethodOn(customImplementation, method,
+ Method actualMethod = repositoryInformation.getTargetClassMethod(method);
+ makeAccessible(actualMethod);
+ return executeMethodOn(customImplementation, actualMethod,
invocation.getArguments());
}
@@ -333,7 +335,7 @@ public Object invoke(MethodInvocation invocation) throws Throwable {
// Lookup actual method as it might be redeclared in the interface
// and we have to use the repository instance nevertheless
- Method actualMethod = repositoryInformation.getBaseClassMethod(method);
+ Method actualMethod = repositoryInformation.getTargetClassMethod(method);
return executeMethodOn(target, actualMethod,
invocation.getArguments());
}
@@ -387,6 +389,8 @@ private boolean isCustomMethodInvocation(MethodInvocation invocation) {
if (null == customImplementation) {
return false;
}
+
+
return repositoryInformation.isCustomMethod(invocation.getMethod());
}
@@ -22,7 +22,7 @@
*
* @author Oliver Gierke
*/
-interface RepositoryInformation extends RepositoryMetadata {
+public interface RepositoryInformation extends RepositoryMetadata {
/**
* Returns the base class to be used to create the proxy backing instance.
@@ -62,14 +62,14 @@
/**
- * Returns the base class method that is backing the given method. This can
+ * Returns the target 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
+ * Returns the method itself if the target class does not implement the given
* method.
*
* @param method
* @return
*/
- Method getBaseClassMethod(Method method);
+ Method getTargetClassMethod(Method method);
}
Oops, something went wrong.

0 comments on commit 70da7b0

Please sign in to comment.