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