帆软使用的第三方框架。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

715 lines
29 KiB

package com.fasterxml.classmate;
import java.lang.annotation.Annotation;
import java.lang.annotation.Inherited;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.*;
import com.fasterxml.classmate.members.*;
import com.fasterxml.classmate.util.MethodKey;
/**
* Class that contains information about fully resolved members of a
* type; resolution meaning that masking is handled for methods, and
* all inheritable annotations are flattened using optional overrides
* as well ("mix-in annotations").
* Instances are created by {@link com.fasterxml.classmate.MemberResolver}.
*<p>
* Note that instances are not thread-safe, as the expectation is that instances
* will not be shared (unlike raw members or resolved types)
*/
public class ResolvedTypeWithMembers
{
private final static ResolvedType[] NO_RESOLVED_TYPES = new ResolvedType[0];
private final static ResolvedMethod[] NO_RESOLVED_METHODS = new ResolvedMethod[0];
private final static ResolvedField[] NO_RESOLVED_FIELDS = new ResolvedField[0];
private final static ResolvedConstructor[] NO_RESOLVED_CONSTRUCTORS = new ResolvedConstructor[0];
/**
* Default annotation configuration is to ignore all annotations types.
*/
protected final static AnnotationConfiguration DEFAULT_ANNOTATION_CONFIG
= new AnnotationConfiguration.StdConfiguration(AnnotationInclusion.DONT_INCLUDE);
/**
* Need to be able to resolve member types still
*/
protected final TypeResolver _typeResolver;
/**
* Handler for resolving annotation information
*/
protected final AnnotationHandler _annotationHandler;
/**
* Leaf of the type hierarchy, i.e. type from which this hierarchy
* was generated.
*/
protected final HierarchicType _mainType;
/**
* All types that hierarchy contains, in order of increasing precedence
* (that is, later entries override members of earlier members)
*/
protected final HierarchicType[] _types;
/**
* Filter to use for selecting fields to include
*/
protected Filter<RawField> _fieldFilter;
/**
* Filter to use for selecting constructors to include
*/
protected Filter<RawConstructor> _constructorFilter;
/**
* Filter to use for selecting methods to include
*/
protected Filter<RawMethod> _methodFilter;
/*
/**********************************************************************
/* Lazily constructed members
/**********************************************************************
*/
protected ResolvedMethod[] _staticMethods = null;
protected ResolvedField[] _staticFields = null;
protected ResolvedMethod[] _memberMethods = null;
protected ResolvedField[] _memberFields = null;
protected ResolvedConstructor[] _constructors = null;
/*
/**********************************************************************
/* Life cycle at this point
/**********************************************************************
*/
public ResolvedTypeWithMembers(TypeResolver typeResolver, AnnotationConfiguration annotationConfig,
HierarchicType mainType, HierarchicType[] types,
Filter<RawConstructor> constructorFilter, Filter<RawField> fieldFilter, Filter<RawMethod> methodFilter)
{
_typeResolver = typeResolver;
_mainType = mainType;
_types = types;
if (annotationConfig == null) {
annotationConfig = DEFAULT_ANNOTATION_CONFIG;
}
_annotationHandler = new AnnotationHandler(annotationConfig);
_constructorFilter = constructorFilter;
_fieldFilter = fieldFilter;
_methodFilter = methodFilter;
}
/*
/**********************************************************************
/* Public API, access to component types
/**********************************************************************
*/
public int size() { return _types.length; }
/**
* Accessor for getting full type hierarchy as priority-ordered list, from
* the lowest precedence to highest precedence (main type, its mix-in overrides)
*/
public List<HierarchicType> allTypesAndOverrides() {
return Arrays.asList(_types);
}
/**
* Accessor for getting subset of type hierarchy which only contains main type
* and possible overrides (mix-ins) it has, but not supertypes or their overrides.
*/
public List<HierarchicType> mainTypeAndOverrides()
{
List<HierarchicType> l = Arrays.asList(_types);
int end = _mainType.getPriority() + 1;
if (end < l.size()) {
l = l.subList(0, end);
}
return l;
}
/**
* Accessor for finding just overrides for the main type (if any).
*/
public List<HierarchicType> overridesOnly()
{
int index = _mainType.getPriority();
if (index == 0) {
return Collections.emptyList();
}
List<HierarchicType> l = Arrays.asList(_types);
return l.subList(0, index);
}
/*
/**********************************************************************
/* Public API, actual resolution of members
/**********************************************************************
*/
/**
* Method for finding all static fields of the main type (except for ones
* possibly filtered out by filter) and applying annotation overrides, if any,
* to annotations.
*
* @since 1.2.0
*/
public ResolvedField[] getStaticFields()
{
if (_staticFields == null) {
_staticFields = resolveStaticFields();
}
return _staticFields;
}
/**
* Method for finding all static methods of the main type (except for ones
* possibly filtered out by filter) and applying annotation overrides, if any,
* to annotations.
*/
public ResolvedMethod[] getStaticMethods()
{
if (_staticMethods == null) {
_staticMethods = resolveStaticMethods();
}
return _staticMethods;
}
public ResolvedField[] getMemberFields()
{
if (_memberFields == null) {
_memberFields = resolveMemberFields();
}
return _memberFields;
}
public ResolvedMethod[] getMemberMethods()
{
if (_memberMethods == null) {
_memberMethods = resolveMemberMethods();
}
return _memberMethods;
}
public ResolvedConstructor[] getConstructors()
{
if (_constructors == null) {
_constructors = resolveConstructors();
}
return _constructors;
}
/*
/**********************************************************************
/* Internal methods: actual resolution
/**********************************************************************
*/
/**
* Method that will actually resolve full information (types, annotations)
* for constructors of the main type.
*/
protected ResolvedConstructor[] resolveConstructors()
{
// First get static methods for main type, filter
LinkedHashMap<MethodKey, ResolvedConstructor> constructors = new LinkedHashMap<MethodKey, ResolvedConstructor>();
for (RawConstructor constructor : _mainType.getType().getConstructors()) {
// no filter for constructors (yet?)
if (_constructorFilter == null || _constructorFilter.include(constructor)) {
constructors.put(constructor.createKey(), resolveConstructor(constructor));
}
}
// then apply overrides (mix-ins):
for (HierarchicType type : overridesOnly()) {
for (RawConstructor raw : type.getType().getConstructors()) {
ResolvedConstructor constructor = constructors.get(raw.createKey());
// must override something, otherwise to ignore
if (constructor != null) {
for (Annotation ann : raw.getAnnotations()) {
if (_annotationHandler.includeMethodAnnotation(ann)) {
constructor.applyOverride(ann);
}
}
// and parameter annotations
Annotation[][] params = raw.getRawMember().getParameterAnnotations();
for (int i = 0; i < params.length; i++) {
for (Annotation annotation : params[i]) {
if (_annotationHandler.includeParameterAnnotation(annotation)) {
constructor.applyParamOverride(i, annotation);
}
}
}
}
}
}
if (constructors.size() == 0) {
return NO_RESOLVED_CONSTRUCTORS;
}
return constructors.values().toArray(new ResolvedConstructor[constructors.size()]);
}
/**
* Method for fully resolving field definitions and associated annotations.
* Neither field definitions nor associated annotations inherit, but we may
* still need to add annotation overrides, as well as filter out filters
* and annotations that caller is not interested in.
*/
protected ResolvedField[] resolveMemberFields()
{
LinkedHashMap<String, ResolvedField> fields = new LinkedHashMap<String, ResolvedField>();
/* Fields need different handling: must start from bottom; and annotations only get added
* as overrides, never as defaults. And sub-classes fully mask fields. This makes
* handling bit simpler than that of member methods.
*/
for (int typeIndex = _types.length; --typeIndex >= 0; ) {
HierarchicType thisType = _types[typeIndex];
// If it's just a mix-in, add annotations as overrides
if (thisType.isMixin()) {
for (RawField raw : thisType.getType().getMemberFields()) {
if ((_fieldFilter != null) && !_fieldFilter.include(raw)) {
continue;
}
ResolvedField field = fields.get(raw.getName());
if (field != null) {
for (Annotation ann : raw.getAnnotations()) {
if (_annotationHandler.includeMethodAnnotation(ann)) {
field.applyOverride(ann);
}
}
}
}
} else { // If actual type, add fields, masking whatever might have existed before:
for (RawField field : thisType.getType().getMemberFields()) {
if ((_fieldFilter != null) && !_fieldFilter.include(field)) {
continue;
}
fields.put(field.getName(), resolveField(field));
}
}
}
// and that's it?
if (fields.size() == 0) {
return NO_RESOLVED_FIELDS;
}
return fields.values().toArray(new ResolvedField[fields.size()]);
}
protected ResolvedMethod[] resolveMemberMethods()
{
LinkedHashMap<MethodKey, ResolvedMethod> methods = new LinkedHashMap<MethodKey, ResolvedMethod>();
LinkedHashMap<MethodKey, Annotations> overrides = new LinkedHashMap<MethodKey, Annotations>();
LinkedHashMap<MethodKey, Annotations[]> paramOverrides = new LinkedHashMap<MethodKey, Annotations[]>();
/* Member methods are handled from top to bottom; and annotations are tracked
* alongside (for overrides), as well as "merged down" for inheritable
* annotations.
*/
for (HierarchicType type : allTypesAndOverrides()) {
for (RawMethod method : type.getType().getMemberMethods()) {
// First: ignore methods caller is not interested
if (_methodFilter != null && !_methodFilter.include(method)) {
continue;
}
MethodKey key = method.createKey();
ResolvedMethod old = methods.get(key);
// Ok, now, mix-ins only contribute annotations; whereas 'real' types methods
if (type.isMixin()) { // mix-in: only get annotations
for (Annotation ann : method.getAnnotations()) {
// If already have a method, must be inheritable to include
if (old != null) {
if (!methodCanInherit(ann)) {
continue;
}
// and if so, apply as default (i.e. do not override)
old.applyDefault(ann);
} else { // If no method, need to add to annotation override map
Annotations oldAnn = overrides.get(key);
if (oldAnn == null) {
oldAnn = new Annotations();
oldAnn.add(ann);
overrides.put(key, oldAnn);
} else {
oldAnn.addAsDefault(ann);
}
}
}
// override argument annotations
final Annotation[][] argAnnotations = method.getRawMember().getParameterAnnotations();
if (old == null) { // no method (yet), add argument annotations to override map
Annotations[] oldParamAnns = paramOverrides.get(key);
if (oldParamAnns == null) { // no existing argument annotations for method
oldParamAnns = new Annotations[argAnnotations.length];
for (int i = 0; i < argAnnotations.length; i++) {
oldParamAnns[i] = new Annotations();
for (final Annotation annotation : argAnnotations[i]) {
if (parameterCanInherit(annotation)) {
oldParamAnns[i].add(annotation);
}
}
}
paramOverrides.put(key, oldParamAnns);
} else {
for (int i = 0; i < argAnnotations.length; i++) {
for (final Annotation annotation : argAnnotations[i]) {
if (parameterCanInherit(annotation)) {
oldParamAnns[i].addAsDefault(annotation);
}
}
}
}
} else { // already have a method, apply argument annotations as defaults
for (int i = 0; i < argAnnotations.length; i++) {
for (final Annotation annotation : argAnnotations[i]) {
if (parameterCanInherit(annotation)) {
old.applyParamDefault(i, annotation);
}
}
}
}
} else { // "real" methods; add if not present, possibly add defaults as well
if (old == null) { // new one to add
ResolvedMethod newMethod = resolveMethod(method);
methods.put(key, newMethod);
// But we may also have annotation overrides, so:
Annotations overrideAnn = overrides.get(key);
if (overrideAnn != null) {
newMethod.applyOverrides(overrideAnn);
}
// and apply parameter annotation overrides
Annotations[] annotations = paramOverrides.get(key);
if (annotations != null) {
for (int i = 0; i < annotations.length; i++) {
newMethod.applyParamOverrides(i, annotations[i]);
}
}
} else { // method masked by something else? can only contribute annotations
for (Annotation ann : method.getAnnotations()) {
if (methodCanInherit(ann)) {
old.applyDefault(ann);
}
}
// and parameter annotations
final Annotation[][] parameterAnnotations = method.getRawMember().getParameterAnnotations();
for (int i = 0; i < parameterAnnotations.length; i++) {
for (final Annotation annotation : parameterAnnotations[i]) {
if (parameterCanInherit(annotation)) {
old.applyParamDefault(i, annotation);
}
}
}
}
}
}
}
if (methods.size() == 0) {
return NO_RESOLVED_METHODS;
}
return methods.values().toArray(new ResolvedMethod[methods.size()]);
}
/**
* Method for fully resolving static field definitions and associated annotations.
* Neither field definitions nor associated annotations inherit, but we may
* still need to add annotation overrides, as well as filter out filters
* and annotations that caller is not interested in.
*
* @since 1.2.0
*/
protected ResolvedField[] resolveStaticFields()
{
// First get static methods for main type, filter
LinkedHashMap<String, ResolvedField> fields = new LinkedHashMap<String, ResolvedField>();
for (RawField field : _mainType.getType().getStaticFields()) {
if (_fieldFilter == null || _fieldFilter.include(field)) {
fields.put(field.getName(), resolveField(field));
}
}
// then apply overrides (mix-ins):
for (HierarchicType type : overridesOnly()) {
for (RawField raw : type.getType().getStaticFields()) {
ResolvedField field = fields.get(raw.getName());
// must override something, otherwise to ignore
if (field != null) {
for (Annotation ann : raw.getAnnotations()) {
if (_annotationHandler.includeFieldAnnotation(ann)) {
field.applyOverride(ann);
}
}
}
}
}
// and that's it?
if (fields.isEmpty()) {
return NO_RESOLVED_FIELDS;
}
return fields.values().toArray(new ResolvedField[ fields.size()]);
}
/**
* Method that will actually resolve full information (types, annotations)
* for static methods, using configured filter.
*/
protected ResolvedMethod[] resolveStaticMethods()
{
// First get static methods for main type, filter
LinkedHashMap<MethodKey, ResolvedMethod> methods = new LinkedHashMap<MethodKey, ResolvedMethod>();
for (RawMethod method : _mainType.getType().getStaticMethods()) {
if (_methodFilter == null || _methodFilter.include(method)) {
methods.put(method.createKey(), resolveMethod(method));
}
}
// then apply overrides (mix-ins):
for (HierarchicType type : overridesOnly()) {
for (RawMethod raw : type.getType().getStaticMethods()) {
ResolvedMethod method = methods.get(raw.createKey());
// must override something, otherwise to ignore
if (method != null) {
for (Annotation ann : raw.getAnnotations()) {
if (_annotationHandler.includeMethodAnnotation(ann)) {
method.applyOverride(ann);
}
}
}
}
}
if (methods.size() == 0) {
return NO_RESOLVED_METHODS;
}
return methods.values().toArray(new ResolvedMethod[methods.size()]);
}
/*
/**********************************************************************
/* Helper methods
/**********************************************************************
*/
/**
* Method for resolving individual constructor completely
*/
protected ResolvedConstructor resolveConstructor(RawConstructor raw)
{
final ResolvedType context = raw.getDeclaringType();
final TypeBindings bindings = context.getTypeBindings();
Constructor<?> ctor = raw.getRawMember();
Type[] rawTypes = ctor.getGenericParameterTypes();
ResolvedType[] argTypes;
if (rawTypes == null || rawTypes.length == 0) {
argTypes = NO_RESOLVED_TYPES;
} else {
argTypes = new ResolvedType[rawTypes.length];
for (int i = 0, len = rawTypes.length; i < len; ++i) {
argTypes[i] = _typeResolver.resolve(bindings, rawTypes[i]);
}
}
// And then annotations
Annotations anns = new Annotations();
for (Annotation ann : ctor.getAnnotations()) {
if (_annotationHandler.includeConstructorAnnotation(ann)) {
anns.add(ann);
}
}
ResolvedConstructor constructor = new ResolvedConstructor(context, anns, ctor, argTypes);
// and parameter annotations
Annotation[][] annotations = ctor.getParameterAnnotations();
for (int i = 0; i < argTypes.length; i++) {
for (Annotation ann : annotations[i]) {
constructor.applyParamOverride(i, ann);
}
}
return constructor;
}
/**
* Method for resolving individual field completely
*/
protected ResolvedField resolveField(RawField raw)
{
final ResolvedType context = raw.getDeclaringType();
Field field = raw.getRawMember();
ResolvedType type = _typeResolver.resolve(context.getTypeBindings(), field.getGenericType());
// And then annotations
Annotations anns = new Annotations();
for (Annotation ann : field.getAnnotations()) {
if (_annotationHandler.includeFieldAnnotation(ann)) {
anns.add(ann);
}
}
return new ResolvedField(context, anns, field, type);
}
/**
* Method for resolving individual method completely
*/
protected ResolvedMethod resolveMethod(RawMethod raw)
{
final ResolvedType context = raw.getDeclaringType();
final TypeBindings bindings = context.getTypeBindings();
Method m = raw.getRawMember();
Type rawType = m.getGenericReturnType();
ResolvedType rt = (rawType == Void.TYPE) ? null : _typeResolver.resolve(bindings, rawType);
Type[] rawTypes = m.getGenericParameterTypes();
ResolvedType[] argTypes;
if (rawTypes == null || rawTypes.length == 0) {
argTypes = NO_RESOLVED_TYPES;
} else {
argTypes = new ResolvedType[rawTypes.length];
for (int i = 0, len = rawTypes.length; i < len; ++i) {
argTypes[i] = _typeResolver.resolve(bindings, rawTypes[i]);
}
}
// And then annotations
Annotations anns = new Annotations();
for (Annotation ann : m.getAnnotations()) {
if (_annotationHandler.includeMethodAnnotation(ann)) {
anns.add(ann);
}
}
ResolvedMethod method = new ResolvedMethod(context, anns, m, rt, argTypes);
// and argument annotations
Annotation[][] annotations = m.getParameterAnnotations();
for (int i = 0; i < argTypes.length; i++) {
for (Annotation ann : annotations[i]) {
method.applyParamOverride(i, ann);
}
}
return method;
}
protected boolean methodCanInherit(Annotation annotation) {
AnnotationInclusion annotationInclusion = _annotationHandler.methodInclusion(annotation);
if (annotationInclusion == AnnotationInclusion.INCLUDE_AND_INHERIT_IF_INHERITED) {
return annotation.annotationType().isAnnotationPresent(Inherited.class);
}
return (annotationInclusion == AnnotationInclusion.INCLUDE_AND_INHERIT);
}
protected boolean parameterCanInherit(Annotation annotation) {
AnnotationInclusion annotationInclusion = _annotationHandler.parameterInclusion(annotation);
if (annotationInclusion == AnnotationInclusion.INCLUDE_AND_INHERIT_IF_INHERITED) {
return annotation.annotationType().isAnnotationPresent(Inherited.class);
}
return (annotationInclusion == AnnotationInclusion.INCLUDE_AND_INHERIT);
}
/*
/**********************************************************************
/* Helper types
/**********************************************************************
*/
/**
* Helper class we use to reduce number of calls to {@link AnnotationConfiguration};
* mostly because determination may be expensive.
*/
private final static class AnnotationHandler
{
private final AnnotationConfiguration _annotationConfig;
private HashMap<Class<? extends Annotation>, AnnotationInclusion> _fieldInclusions;
private HashMap<Class<? extends Annotation>, AnnotationInclusion> _constructorInclusions;
private HashMap<Class<? extends Annotation>, AnnotationInclusion> _methodInclusions;
private HashMap<Class<? extends Annotation>, AnnotationInclusion> _parameterInclusions;
public AnnotationHandler(AnnotationConfiguration annotationConfig) {
_annotationConfig = annotationConfig;
}
public boolean includeConstructorAnnotation(Annotation ann)
{
Class<? extends Annotation> annType = ann.annotationType();
if (_constructorInclusions == null) {
_constructorInclusions = new HashMap<Class<? extends Annotation>, AnnotationInclusion>();
} else {
AnnotationInclusion incl = _constructorInclusions.get(annType);
if (incl != null) {
return (incl != AnnotationInclusion.DONT_INCLUDE);
}
}
AnnotationInclusion incl = _annotationConfig.getInclusionForConstructor(annType);
_constructorInclusions.put(annType, incl);
return (incl != AnnotationInclusion.DONT_INCLUDE);
}
public boolean includeFieldAnnotation(Annotation ann)
{
Class<? extends Annotation> annType = ann.annotationType();
if (_fieldInclusions == null) {
_fieldInclusions = new HashMap<Class<? extends Annotation>, AnnotationInclusion>();
} else {
AnnotationInclusion incl = _fieldInclusions.get(annType);
if (incl != null) {
return (incl != AnnotationInclusion.DONT_INCLUDE);
}
}
AnnotationInclusion incl = _annotationConfig.getInclusionForField(annType);
_fieldInclusions.put(annType, incl);
return (incl != AnnotationInclusion.DONT_INCLUDE);
}
public boolean includeMethodAnnotation(Annotation ann)
{
return methodInclusion(ann) != AnnotationInclusion.DONT_INCLUDE;
}
public AnnotationInclusion methodInclusion(Annotation ann)
{
Class<? extends Annotation> annType = ann.annotationType();
if (_methodInclusions == null) {
_methodInclusions = new HashMap<Class<? extends Annotation>, AnnotationInclusion>();
} else {
AnnotationInclusion incl = _methodInclusions.get(annType);
if (incl != null) {
return incl;
}
}
AnnotationInclusion incl = _annotationConfig.getInclusionForMethod(annType);
_methodInclusions.put(annType, incl);
return incl;
}
public boolean includeParameterAnnotation(Annotation ann)
{
return parameterInclusion(ann) != AnnotationInclusion.DONT_INCLUDE;
}
public AnnotationInclusion parameterInclusion(Annotation ann)
{
Class<? extends Annotation> annType = ann.annotationType();
if (_parameterInclusions == null) {
_parameterInclusions = new HashMap<Class<? extends Annotation>, AnnotationInclusion>();
} else {
AnnotationInclusion incl = _parameterInclusions.get(annType);
if (incl != null) {
return incl;
}
}
AnnotationInclusion incl = _annotationConfig.getInclusionForParameter(annType);
_parameterInclusions.put(annType, incl);
return incl;
}
}
}