3 * Copyright (C) 2007 EDIT
4 * European Distributed Institute of Taxonomy
5 * http://www.e-taxonomy.eu
7 * The contents of this file are subject to the Mozilla Public License Version 1.1
8 * See LICENSE.TXT at the top of this package for the full license terms.
11 package eu
.etaxonomy
.cdm
.persistence
.dao
;
13 import java
.lang
.reflect
.Method
;
14 import java
.util
.ArrayList
;
15 import java
.util
.Arrays
;
16 import java
.util
.HashMap
;
17 import java
.util
.List
;
20 import org
.apache
.log4j
.Logger
;
21 import org
.springframework
.stereotype
.Component
;
25 * @created Mar 11, 2010
29 public class MethodCacheImpl
implements IMethodCache
{
33 private Map
<MethodDescriptor
, Method
> methodMap
= new HashMap
<MethodDescriptor
, Method
>();
37 * @see eu.etaxonomy.cdm.persistence.dao.IMethodCache#getMethod(java.lang.Class, java.lang.String, java.lang.Class)
39 public Method
getMethod(Class clazz
, String methodName
, Class parameterType
) {
40 MethodDescriptor methodDescriptor
= new MethodDescriptor(clazz
, methodName
, new Class
[]{parameterType
});
42 if(methodMap
.containsKey(methodDescriptor
)){
43 return methodMap
.get(methodDescriptor
);
46 Method method
= getMethodInternal(clazz
, methodName
, parameterType
);
48 method
.setAccessible(true);
50 // we also put null methods into the map to benefit from caching
51 put(methodDescriptor
, method
);
57 * Checks class hierarchy of the given class for a method that fits to the given name and parameter type
61 * @param parameterType
64 private Method
getMethodInternal(Class clazz
, String methodName
,
66 // stop recursing when there are no more superclasses
73 for(Class includedType
: getIncludedTypes(parameterType
, new ArrayList
<Class
>())){
75 method
= clazz
.getDeclaredMethod(methodName
, includedType
);
76 }catch (NoSuchMethodException e
) {
81 // if we have a method return it
86 // recurse into superclass if no method was found
87 return getMethodInternal(clazz
.getSuperclass(), methodName
, parameterType
);
91 * Create a list containing the type and all supertypes of a given type
97 private List
<Class
> getIncludedTypes(Class clazz
, List
<Class
> classList
){
101 classList
.add(clazz
);
102 Class
[] interfaces
= clazz
.getInterfaces();
103 if(interfaces
!= null){
104 classList
.addAll(Arrays
.asList(interfaces
));
106 return getIncludedTypes(clazz
.getSuperclass(), classList
);
112 * @param methodDescriptor
115 private void put(MethodDescriptor methodDescriptor
, Method method
) {
116 methodMap
.put(methodDescriptor
, method
);
122 * @created Mar 11, 2010
125 private static class MethodDescriptor
{
126 private static final Logger logger
= Logger
127 .getLogger(MethodDescriptor
.class);
129 /** An empty class array */
130 private static final Class
[] emptyClassArray
= new Class
[0];
133 private String methodName
;
134 private Class
[] parameterTypes
;
135 private int hashCode
;
138 * The sole constructor.
140 * @param clazz the class to reflect, must not be null
141 * @param methodName the method name to obtain
142 * @param paramTypes the array of classes representing the paramater types
143 * @param exact whether the match has to be exact.
145 public MethodDescriptor(Class clazz
, String methodName
, Class
[] paramTypes
) {
147 throw new IllegalArgumentException("Class cannot be null");
149 if (methodName
== null) {
150 throw new IllegalArgumentException("Method Name cannot be null");
152 if (paramTypes
== null) {
153 paramTypes
= emptyClassArray
;
157 this.methodName
= methodName
;
158 this.parameterTypes
= paramTypes
;
160 this.hashCode
= methodName
.length();
163 * Checks for equality.
164 * @param object object to be tested for equality
165 * @return true, if the object describes the same Method.
167 public boolean equals(Object object
) {
168 if (!(object
instanceof MethodDescriptor
)) {
171 MethodDescriptor methodDescriptor
= (MethodDescriptor
)object
;
174 methodName
.equals(methodDescriptor
.methodName
) &&
175 clazz
.equals(methodDescriptor
.clazz
) &&
176 java
.util
.Arrays
.equals(parameterTypes
, methodDescriptor
.parameterTypes
)
180 * Returns the string length of method name. I.e. if the
181 * hashcodes are different, the objects are different. If the
182 * hashcodes are the same, need to use the equals method to
183 * determine equality.
184 * @return the string length of method name.
186 public int hashCode() {