2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
10 package eu
.etaxonomy
.cdm
.persistence
.dao
;
12 import java
.lang
.reflect
.Method
;
13 import java
.util
.ArrayList
;
14 import java
.util
.Arrays
;
15 import java
.util
.HashMap
;
16 import java
.util
.List
;
19 import org
.apache
.log4j
.Logger
;
20 import org
.springframework
.stereotype
.Component
;
28 public class MethodCacheImpl
implements IMethodCache
{
32 private Map
<MethodDescriptor
, Method
> methodMap
= new HashMap
<MethodDescriptor
, Method
>();
36 * @see eu.etaxonomy.cdm.persistence.dao.IMethodCache#getMethod(java.lang.Class, java.lang.String, java.lang.Class)
38 public Method
getMethod(Class clazz
, String methodName
, Class parameterType
) {
39 MethodDescriptor methodDescriptor
= new MethodDescriptor(clazz
, methodName
, new Class
[]{parameterType
});
41 if(methodMap
.containsKey(methodDescriptor
)){
42 return methodMap
.get(methodDescriptor
);
45 Method method
= getMethodInternal(clazz
, methodName
, parameterType
);
47 method
.setAccessible(true);
49 // we also put null methods into the map to benefit from caching
50 put(methodDescriptor
, method
);
56 * Checks class hierarchy of the given class for a method that fits to the given name and parameter type
60 * @param parameterType
63 private Method
getMethodInternal(Class clazz
, String methodName
,
65 // stop recursing when there are no more superclasses
72 for(Class includedType
: getIncludedTypes(parameterType
, new ArrayList
<Class
>())){
74 method
= clazz
.getDeclaredMethod(methodName
, includedType
);
75 }catch (NoSuchMethodException e
) {
80 // if we have a method return it
85 // recurse into superclass if no method was found
86 return getMethodInternal(clazz
.getSuperclass(), methodName
, parameterType
);
90 * Create a list containing the type and all supertypes of a given type
96 private List
<Class
> getIncludedTypes(Class clazz
, List
<Class
> classList
){
100 classList
.add(clazz
);
101 Class
[] interfaces
= clazz
.getInterfaces();
102 if(interfaces
!= null){
103 classList
.addAll(Arrays
.asList(interfaces
));
105 return getIncludedTypes(clazz
.getSuperclass(), classList
);
111 * @param methodDescriptor
114 private void put(MethodDescriptor methodDescriptor
, Method method
) {
115 methodMap
.put(methodDescriptor
, method
);
121 * @since Mar 11, 2010
124 private static class MethodDescriptor
{
125 private static final Logger logger
= Logger
126 .getLogger(MethodDescriptor
.class);
128 /** An empty class array */
129 private static final Class
[] emptyClassArray
= new Class
[0];
132 private String methodName
;
133 private Class
[] parameterTypes
;
134 private int hashCode
;
137 * The sole constructor.
139 * @param clazz the class to reflect, must not be null
140 * @param methodName the method name to obtain
141 * @param paramTypes the array of classes representing the paramater types
142 * @param exact whether the match has to be exact.
144 public MethodDescriptor(Class clazz
, String methodName
, Class
[] paramTypes
) {
146 throw new IllegalArgumentException("Class cannot be null");
148 if (methodName
== null) {
149 throw new IllegalArgumentException("Method Name cannot be null");
151 if (paramTypes
== null) {
152 paramTypes
= emptyClassArray
;
156 this.methodName
= methodName
;
157 this.parameterTypes
= paramTypes
;
159 this.hashCode
= methodName
.length();
162 * Checks for equality.
163 * @param object object to be tested for equality
164 * @return true, if the object describes the same Method.
166 public boolean equals(Object object
) {
167 if (!(object
instanceof MethodDescriptor
)) {
170 MethodDescriptor methodDescriptor
= (MethodDescriptor
)object
;
173 methodName
.equals(methodDescriptor
.methodName
) &&
174 clazz
.equals(methodDescriptor
.clazz
) &&
175 java
.util
.Arrays
.equals(parameterTypes
, methodDescriptor
.parameterTypes
)
179 * Returns the string length of method name. I.e. if the
180 * hashcodes are different, the objects are different. If the
181 * hashcodes are the same, need to use the equals method to
182 * determine equality.
183 * @return the string length of method name.
185 public int hashCode() {