/*
* JBoss, Home of Professional Open Source
* Copyright 2011, Red Hat, Inc. and/or its affiliates, and individual
* contributors by the @authors tag. See the copyright.txt in the
* distribution for a full listing of individual contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jboss.solder.reflection.annotated;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Constructor;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import org.jboss.solder.reflection.Reflections;
/**
* An implementation of Member for parameters
*
* @author pmuir
*/
abstract class Parameter<X> implements AnnotatedElement {
static <X> Parameter<X> create(Member declaringMember, int position) {
if (declaringMember instanceof Method) {
return new MethodParameter<X>((Method) declaringMember, position);
} else if (declaringMember instanceof Constructor<?>) {
return new ConstructorParameter<X>(Reflections.<Constructor<X>>cast(declaringMember), position);
} else {
throw new IllegalArgumentException("Can only process members of type Method and Constructor, cannot process " + declaringMember);
}
}
private static class MethodParameter<X> extends Parameter<X> {
private final Method declaringMethod;
private MethodParameter(Method declaringMethod, int position) {
super(position);
this.declaringMethod = declaringMethod;
}
@Override
public Method getDeclaringMember() {
return declaringMethod;
}
public Annotation[] getAnnotations() {
if (declaringMethod.getParameterAnnotations().length > getPosition()) {
return declaringMethod.getParameterAnnotations()[getPosition()];
} else {
return Reflections.EMPTY_ANNOTATION_ARRAY;
}
}
@Override
public Type getBaseType() {
if (declaringMethod.getGenericParameterTypes().length > getPosition()) {
return declaringMethod.getGenericParameterTypes()[getPosition()];
} else {
return declaringMethod.getParameterTypes()[getPosition()];
}
}
}
private static class ConstructorParameter<X> extends Parameter<X> {
private final Constructor<X> declaringConstructor;
private ConstructorParameter(Constructor<X> declaringConstructor, int position) {
super(position);
this.declaringConstructor = declaringConstructor;
}
@Override
public Constructor<X> getDeclaringMember() {
return declaringConstructor;
}
public Annotation[] getAnnotations() {
if (declaringConstructor.getParameterAnnotations().length > getPosition()) {
return declaringConstructor.getParameterAnnotations()[getPosition()];
} else {
return Reflections.EMPTY_ANNOTATION_ARRAY;
}
}
@Override
public Type getBaseType() {
if (declaringConstructor.getGenericParameterTypes().length > getPosition()) {
return declaringConstructor.getGenericParameterTypes()[getPosition()];
} else {
return declaringConstructor.getParameterTypes()[getPosition()];
}
}
}
private final int position;
Parameter(int position) {
this.position = position;
}
public abstract Member getDeclaringMember();
public int getPosition() {
return position;
}
@Override
public int hashCode() {
int hash = 1;
hash = hash * 31 + getDeclaringMember().hashCode();
hash = hash * 31 + Integer.valueOf(position).hashCode();
return hash;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof Parameter<?>) {
Parameter<?> that = (Parameter<?>) obj;
return this.getDeclaringMember().equals(that.getDeclaringMember()) && this.getPosition() == that.getPosition();
} else {
return false;
}
}
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
for (Annotation annotation : getAnnotations()) {
if (annotation.annotationType().equals(annotationClass)) {
return annotationClass.cast(annotation);
}
}
return null;
}
public Annotation[] getDeclaredAnnotations() {
return getAnnotations();
}
public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
return getAnnotation(annotationClass) != null;
}
public abstract Type getBaseType();
}