001/*-------------------------------------------------------------------------+ 002| | 003| Copyright 2005-2011 The ConQAT Project | 004| | 005| Licensed under the Apache License, Version 2.0 (the "License"); | 006| you may not use this file except in compliance with the License. | 007| You may obtain a copy of the License at | 008| | 009| http://www.apache.org/licenses/LICENSE-2.0 | 010| | 011| Unless required by applicable law or agreed to in writing, software | 012| distributed under the License is distributed on an "AS IS" BASIS, | 013| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 014| See the License for the specific language governing permissions and | 015| limitations under the License. | 016+-------------------------------------------------------------------------*/ 017package org.conqat.lib.commons.reflect; 018 019import java.lang.annotation.Annotation; 020import java.lang.reflect.Method; 021import java.lang.reflect.Type; 022 023/** 024 * This class models formal method parameters to allow convenient reflective 025 * access as the Java Reflection API does not model them explicitly. 026 * 027 * Instances of this class can be obtained via 028 * {@link ReflectionUtils#getFormalParameters(Method)}. 029 * 030 * @author Florian Deissenboeck 031 * 032 * @see ReflectionUtils#getFormalParameters(Method) 033 * @see ReflectionUtils#invoke(Method, Object, java.util.Map) 034 */ 035public final class FormalParameter { 036 037 /** The method the parameter belongs to. */ 038 private final Method method; 039 040 /** 041 * The position of the formal parameter within the methods parameter list. 042 */ 043 private final int position; 044 045 /** 046 * Create new formal parameter. This is called from 047 * {@link ReflectionUtils#getFormalParameters(Method)}. 048 */ 049 /* package */ FormalParameter(Method method, int position) { 050 this.method = method; 051 this.position = position; 052 } 053 054 /** Get the method that declares this formal parameter. */ 055 public Method getMethod() { 056 return method; 057 } 058 059 /** 060 * Get parameter type. 061 */ 062 public Class<?> getType() { 063 return method.getParameterTypes()[position]; 064 } 065 066 /** 067 * Get generic parameter type. 068 */ 069 public Type getGenericType() { 070 return method.getGenericParameterTypes()[position]; 071 } 072 073 /** 074 * Get parameter annotations. 075 */ 076 public Annotation[] getAnnotations() { 077 Annotation[][] annotations = method.getParameterAnnotations(); 078 return annotations[position]; 079 } 080 081 /** 082 * Get the position of the formal parameter within the methods parameter 083 * list. 084 */ 085 public int getPosition() { 086 return position; 087 } 088 089 /** 090 * The hashcode is computed as the exclusive-or of the method's hashcode and 091 * (position+1). 092 */ 093 @Override 094 public int hashCode() { 095 return method.hashCode() ^ (position + 1); 096 } 097 098 /** 099 * Returns this element's annotation for the specified type if such an 100 * annotation is present, else <code>null</code>. 101 */ 102 @SuppressWarnings("unchecked") 103 public <A extends Annotation> A getAnnotation(Class<A> annotationClass) { 104 if (annotationClass == null) { 105 throw new NullPointerException(); 106 } 107 108 for (Annotation annotation : getAnnotations()) { 109 if (annotation.annotationType().equals(annotationClass)) { 110 return (A) annotation; 111 } 112 } 113 114 return null; 115 } 116 117 /** 118 * Returns <code>true</code> if an annotation of the specified type is 119 * defined for this formal parameter. 120 */ 121 public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) { 122 if (annotationClass == null) { 123 throw new NullPointerException(); 124 } 125 126 return getAnnotation(annotationClass) != null; 127 } 128 129 /** 130 * Two formal parameters are equal if their declaring methods and their 131 * position within the formal parameter list are equal. 132 */ 133 @Override 134 public boolean equals(Object object) { 135 if (object == null || !(object instanceof FormalParameter)) { 136 return false; 137 } 138 139 if (object == this) { 140 return true; 141 } 142 143 FormalParameter otherFormalParameter = (FormalParameter) object; 144 145 return method.equals(otherFormalParameter.method) && (position == otherFormalParameter.position); 146 } 147 148 /** 149 * Returns method name, position and type. 150 */ 151 @Override 152 public String toString() { 153 return "Formal parameter #" + position + " of method '" + method.getName() + "' (type: '" + getType().getName() 154 + "')"; 155 } 156}