001/* 002 * Copyright (C) 2012 The Guava Authors 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 005 * in compliance with the License. You may obtain a copy of the License at 006 * 007 * http://www.apache.org/licenses/LICENSE-2.0 008 * 009 * Unless required by applicable law or agreed to in writing, software distributed under the License 010 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 011 * or implied. See the License for the specific language governing permissions and limitations under 012 * the License. 013 */ 014 015package com.google.common.reflect; 016 017import static com.google.common.base.Preconditions.checkNotNull; 018 019import com.google.common.annotations.Beta; 020import com.google.common.collect.FluentIterable; 021import com.google.common.collect.ImmutableList; 022import java.lang.annotation.Annotation; 023import java.lang.reflect.AnnotatedElement; 024import javax.annotation.CheckForNull; 025import org.checkerframework.checker.nullness.qual.Nullable; 026 027/** 028 * Represents a method or constructor parameter. 029 * 030 * @author Ben Yu 031 * @since 14.0 032 */ 033@Beta 034@ElementTypesAreNonnullByDefault 035public final class Parameter implements AnnotatedElement { 036 037 private final Invokable<?, ?> declaration; 038 private final int position; 039 private final TypeToken<?> type; 040 private final ImmutableList<Annotation> annotations; 041 042 Parameter( 043 Invokable<?, ?> declaration, int position, TypeToken<?> type, Annotation[] annotations) { 044 this.declaration = declaration; 045 this.position = position; 046 this.type = type; 047 this.annotations = ImmutableList.copyOf(annotations); 048 } 049 050 /** Returns the type of the parameter. */ 051 public TypeToken<?> getType() { 052 return type; 053 } 054 055 /** Returns the {@link Invokable} that declares this parameter. */ 056 public Invokable<?, ?> getDeclaringInvokable() { 057 return declaration; 058 } 059 060 @Override 061 public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) { 062 return getAnnotation(annotationType) != null; 063 } 064 065 @Override 066 @CheckForNull 067 public <A extends Annotation> A getAnnotation(Class<A> annotationType) { 068 checkNotNull(annotationType); 069 for (Annotation annotation : annotations) { 070 if (annotationType.isInstance(annotation)) { 071 return annotationType.cast(annotation); 072 } 073 } 074 return null; 075 } 076 077 @Override 078 public Annotation[] getAnnotations() { 079 return getDeclaredAnnotations(); 080 } 081 082 /** @since 18.0 */ 083 // @Override on JDK8 084 public <A extends Annotation> A[] getAnnotationsByType(Class<A> annotationType) { 085 return getDeclaredAnnotationsByType(annotationType); 086 } 087 088 /** @since 18.0 */ 089 // @Override on JDK8 090 @Override 091 public Annotation[] getDeclaredAnnotations() { 092 return annotations.toArray(new Annotation[0]); 093 } 094 095 /** @since 18.0 */ 096 // @Override on JDK8 097 @CheckForNull 098 public <A extends Annotation> A getDeclaredAnnotation(Class<A> annotationType) { 099 checkNotNull(annotationType); 100 return FluentIterable.from(annotations).filter(annotationType).first().orNull(); 101 } 102 103 /** @since 18.0 */ 104 // @Override on JDK8 105 public <A extends Annotation> A[] getDeclaredAnnotationsByType(Class<A> annotationType) { 106 @Nullable 107 A[] result = FluentIterable.from(annotations).filter(annotationType).toArray(annotationType); 108 @SuppressWarnings("nullness") // safe because the input list contains no nulls 109 A[] cast = (A[]) result; 110 return cast; 111 } 112 113 @Override 114 public boolean equals(@CheckForNull Object obj) { 115 if (obj instanceof Parameter) { 116 Parameter that = (Parameter) obj; 117 return position == that.position && declaration.equals(that.declaration); 118 } 119 return false; 120 } 121 122 @Override 123 public int hashCode() { 124 return position; 125 } 126 127 @Override 128 public String toString() { 129 return type + " arg" + position; 130 } 131}