package com.fasterxml.jackson.databind.introspect;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.type.TypeBindings;
import com.fasterxml.jackson.databind.type.TypeFactory;
/**
* Intermediate base class that encapsulates features that
* constructors and methods share.
*/
public abstract class AnnotatedWithParams
extends AnnotatedMember
{
/**
* Annotations associated with parameters of the annotated
* entity (method or constructor parameters)
*/
protected final AnnotationMap[] _paramAnnotations;
/*
/**********************************************************
/* Life-cycle
/**********************************************************
*/
protected AnnotatedWithParams(AnnotationMap annotations, AnnotationMap[] paramAnnotations)
{
super(annotations);
_paramAnnotations = paramAnnotations;
}
/**
* Method called to override a method parameter annotation,
* usually due to a mix-in
* annotation masking or overriding an annotation 'real' method
* has.
*/
public final void addOrOverrideParam(int paramIndex, Annotation a)
{
AnnotationMap old = _paramAnnotations[paramIndex];
if (old == null) {
old = new AnnotationMap();
_paramAnnotations[paramIndex] = old;
}
old.add(a);
}
/**
* Method called by parameter object when an augmented instance is created;
* needs to replace parameter with new instance
*/
protected AnnotatedParameter replaceParameterAnnotations(int index, AnnotationMap ann)
{
_paramAnnotations[index] = ann;
return getParameter(index);
}
/*
/**********************************************************
/* Helper methods for subclasses
/**********************************************************
*/
protected JavaType getType(TypeBindings bindings, TypeVariable<?>[] typeParams)
{
// [JACKSON-468] Need to consider local type binding declarations too...
if (typeParams != null && typeParams.length > 0) {
bindings = bindings.childInstance();
for (TypeVariable<?> var : typeParams) {
String name = var.getName();
// to prevent infinite loops, need to first add placeholder ("<T extends Enum<T>>" etc)
bindings._addPlaceholder(name);
// About only useful piece of information is the lower bound (which is at least Object.class)
Type lowerBound = var.getBounds()[0];
JavaType type = (lowerBound == null) ? TypeFactory.unknownType()
: bindings.resolveType(lowerBound);
bindings.addBinding(var.getName(), type);
}
}
return bindings.resolveType(getGenericType());
}
/*
/**********************************************************
/* Partial Annotated impl
/**********************************************************
*/
@Override
public final <A extends Annotation> A getAnnotation(Class<A> acls)
{
return _annotations.get(acls);
}
/*
/**********************************************************
/* Extended API
/**********************************************************
*/
public final AnnotationMap getParameterAnnotations(int index)
{
if (_paramAnnotations != null) {
if (index >= 0 && index <= _paramAnnotations.length) {
return _paramAnnotations[index];
}
}
return null;
}
public final AnnotatedParameter getParameter(int index) {
return new AnnotatedParameter(this, getGenericParameterType(index),
getParameterAnnotations(index), index);
}
public abstract int getParameterCount();
public abstract Class<?> getRawParameterType(int index);
public abstract Type getGenericParameterType(int index);
/**
* Method called to fully resolve type of one of parameters, given
* specified type variable bindings.
*/
public final JavaType resolveParameterType(int index, TypeBindings bindings) {
return bindings.resolveType(getGenericParameterType(index));
}
public final int getAnnotationCount() { return _annotations.size(); }
/**
* Method that can be used to (try to) call this object without arguments.
* This may succeed or fail, depending on expected number
* of arguments: caller needs to take care to pass correct number.
* Exceptions are thrown directly from actual low-level call.
*<p>
* Note: only works for constructors and static methods.
*/
public abstract Object call() throws Exception;
/**
* Method that can be used to (try to) call this object with specified arguments.
* This may succeed or fail, depending on expected number
* of arguments: caller needs to take care to pass correct number.
* Exceptions are thrown directly from actual low-level call.
*<p>
* Note: only works for constructors and static methods.
*/
public abstract Object call(Object[] args) throws Exception;
/**
* Method that can be used to (try to) call this object with single arguments.
* This may succeed or fail, depending on expected number
* of arguments: caller needs to take care to pass correct number.
* Exceptions are thrown directly from actual low-level call.
*<p>
* Note: only works for constructors and static methods.
*/
public abstract Object call1(Object arg) throws Exception;
}