DELTASPIKE-1158 When extracting methods to be used in repository classes, take generic type arguments in to consideration.
Undid unnecessary parts from prior commit. Project: http://git-wip-us.apache.org/repos/asf/deltaspike/repo Commit: http://git-wip-us.apache.org/repos/asf/deltaspike/commit/df1a0c9d Tree: http://git-wip-us.apache.org/repos/asf/deltaspike/tree/df1a0c9d Diff: http://git-wip-us.apache.org/repos/asf/deltaspike/diff/df1a0c9d Branch: refs/heads/master Commit: df1a0c9d45fb7474ca23c0ab8fe56ef3dc185224 Parents: 9d66769 Author: John D. Ament <[email protected]> Authored: Wed Jun 1 19:06:25 2016 -0400 Committer: John D. Ament <[email protected]> Committed: Wed Jun 1 19:06:25 2016 -0400 ---------------------------------------------------------------------- .../apache/deltaspike/core/util/ClassUtils.java | 65 ++++++++++++++++++++ .../data/impl/builder/DelegateQueryBuilder.java | 4 +- .../handler/EntityRepositoryHandlerTest.java | 3 +- .../test/service/IntermediateRepository.java | 36 ----------- .../service/SimpleIntermediateRepository.java | 11 +++- 5 files changed, 78 insertions(+), 41 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/deltaspike/blob/df1a0c9d/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/ClassUtils.java ---------------------------------------------------------------------- diff --git a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/ClassUtils.java b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/ClassUtils.java index 3737a48..29d4bd8 100644 --- a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/ClassUtils.java +++ b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/ClassUtils.java @@ -354,4 +354,69 @@ public abstract class ClassUtils return null; } } + + /** + * Checks if the given class has a method with the same signature, taking in to account generic types + * @param targetClass + * @param method + * @return if it contains a method with the same signature. + */ + public static boolean containsPossiblyGenericMethod(Class<?> targetClass, Method method) + { + return extractPossiblyGenericMethod(targetClass, method) != null; + } + + /** + * Extracts a method matching the source method, allowing generic type parameters to be substituted as + * long as they are properly castable. + * + * @param clazz The target class + * @param sourceMethod The source method. + * @return the extracted method or <code>null</code> + */ + public static Method extractPossiblyGenericMethod(Class<?> clazz, Method sourceMethod) + { + Method exactMethod = extractMethod(clazz, sourceMethod); + if (exactMethod == null) + { + String methodName = sourceMethod.getName(); + Class<?>[] parameterTypes = sourceMethod.getParameterTypes(); + for (Method method : clazz.getMethods()) + { + if (method.getName().equals(methodName) && + allSameType(method.getParameterTypes(), parameterTypes)) + { + return method; + } + } + return null; + } + else + { + return exactMethod; + } + } + + /** + * Whether all of the parameters from left to right are equivalent. + * In order to support generics, it takes the form of left.isAssignableFrom(right) + * @param left left hand side to check + * @param right right hand side to check + * @return whether all of the left classes can be assigned to the right hand side types + */ + private static boolean allSameType(Class<?>[] left, Class<?>[] right) + { + if (left.length != right.length) + { + return false; + } + for (int p = 0; p < left.length; p++) + { + if (!left[p].isAssignableFrom(right[p])) + { + return false; + } + } + return true; + } } http://git-wip-us.apache.org/repos/asf/deltaspike/blob/df1a0c9d/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/DelegateQueryBuilder.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/DelegateQueryBuilder.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/DelegateQueryBuilder.java index a3eda41..99ccf87 100644 --- a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/DelegateQueryBuilder.java +++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/DelegateQueryBuilder.java @@ -72,7 +72,7 @@ public class DelegateQueryBuilder extends QueryBuilder .getBeanDefinitions(DelegateQueryHandler.class, true, true); for (Bean<DelegateQueryHandler> bean : beans) { - if (ClassUtils.containsMethod(bean.getBeanClass(), context.getMethod())) + if (ClassUtils.containsPossiblyGenericMethod(bean.getBeanClass(), context.getMethod())) { if (bean.getScope().equals(Dependent.class)) { @@ -111,7 +111,7 @@ public class DelegateQueryBuilder extends QueryBuilder protected Object invoke(Object target, Method method, Object[] args) throws InvocationTargetException, IllegalAccessException { - Method extract = ClassUtils.extractMethod(target.getClass(), method); + Method extract = ClassUtils.extractPossiblyGenericMethod(target.getClass(), method); return extract.invoke(target, args); } http://git-wip-us.apache.org/repos/asf/deltaspike/blob/df1a0c9d/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/handler/EntityRepositoryHandlerTest.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/handler/EntityRepositoryHandlerTest.java b/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/handler/EntityRepositoryHandlerTest.java index c72c311..6a8eb2a 100644 --- a/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/handler/EntityRepositoryHandlerTest.java +++ b/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/handler/EntityRepositoryHandlerTest.java @@ -27,7 +27,6 @@ import org.apache.deltaspike.data.test.service.ExtendedRepositoryAbstract; import org.apache.deltaspike.data.test.service.ExtendedRepositoryAbstract2; import org.apache.deltaspike.data.test.service.ExtendedRepositoryAbstract4; import org.apache.deltaspike.data.test.service.ExtendedRepositoryInterface; -import org.apache.deltaspike.data.test.service.IntermediateRepository; import org.apache.deltaspike.data.test.service.SimpleIntermediateRepository; import org.apache.deltaspike.data.test.service.SimpleStringIdRepository; import org.apache.deltaspike.test.category.WebProfileCategory; @@ -57,7 +56,7 @@ public class EntityRepositoryHandlerTest extends TransactionalTestCase .addClasses(ExtendedRepositoryInterface.class) .addClasses(ExtendedRepositoryAbstract.class) .addClasses(ExtendedRepositoryAbstract2.class) - .addClasses(ExtendedRepositoryAbstract4.class, IntermediateRepository.class) + .addClasses(ExtendedRepositoryAbstract4.class) .addClasses(SimpleStringIdRepository.class, SimpleIntermediateRepository.class) .addPackage(Simple.class.getPackage()); } http://git-wip-us.apache.org/repos/asf/deltaspike/blob/df1a0c9d/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/service/IntermediateRepository.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/service/IntermediateRepository.java b/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/service/IntermediateRepository.java deleted file mode 100644 index fb12773..0000000 --- a/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/service/IntermediateRepository.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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.apache.deltaspike.data.test.service; - -import org.apache.deltaspike.data.api.EntityRepository; -import org.apache.deltaspike.data.api.Query; - -import javax.persistence.QueryHint; -import java.io.Serializable; - -public interface IntermediateRepository<E, PK extends Serializable> extends EntityRepository<E, PK> -{ - @Query(hints = { - @QueryHint(name = "openjpa.hint.OptimizeResultCount", value = "some.invalid.value"), - @QueryHint(name = "org.hibernate.comment", value = "I'm a little comment short and stout") - }) - @Override - E findBy(PK pk); -} http://git-wip-us.apache.org/repos/asf/deltaspike/blob/df1a0c9d/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/service/SimpleIntermediateRepository.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/service/SimpleIntermediateRepository.java b/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/service/SimpleIntermediateRepository.java index 38410a1..85ea36e 100644 --- a/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/service/SimpleIntermediateRepository.java +++ b/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/service/SimpleIntermediateRepository.java @@ -19,10 +19,19 @@ package org.apache.deltaspike.data.test.service; +import org.apache.deltaspike.data.api.EntityRepository; +import org.apache.deltaspike.data.api.Query; import org.apache.deltaspike.data.api.Repository; import org.apache.deltaspike.data.test.domain.Simple; +import javax.persistence.QueryHint; + @Repository -public interface SimpleIntermediateRepository extends IntermediateRepository<Simple, Long> +public interface SimpleIntermediateRepository extends EntityRepository<Simple, Long> { + @Query(hints = { + @QueryHint(name = "openjpa.hint.OptimizeResultCount", value = "some.invalid.value"), + @QueryHint(name = "org.hibernate.comment", value = "I'm a little comment short and stout") + }) + Simple findBy(Long id); }
