protected void _addClassMixIns(AnnotationMap annotations, Class<?> toMask, Class<?> mixin) { if (mixin == null) { return; } // Ok, first: annotations from mix-in class itself: for (Annotation a : mixin.getDeclaredAnnotations()) { if (_annotationIntrospector.isHandled(a)) { annotations.addIfNotPresent(a); } } /* And then from its supertypes, if any. But note that we will * only consider super-types up until reaching the masked * class (if found); this because often mix-in class * is a sub-class (for convenience reasons). And if so, we * absolutely must NOT include super types of masked class, * as that would inverse precedence of annotations. */ for (Class<?> parent : ClassUtil.findSuperTypes(mixin, toMask)) { for (Annotation a : parent.getDeclaredAnnotations()) { if (_annotationIntrospector.isHandled(a)) { annotations.addIfNotPresent(a); } } } }
/** * Initialization method that will recursively collect Jackson annotations for this class and all * super classes and interfaces. * * <p>Starting with 1.2, it will also apply mix-in annotations, as per [JACKSON-76] */ protected void resolveClassAnnotations() { _classAnnotations = new AnnotationMap(); // add mix-in annotations first (overrides) if (_primaryMixIn != null) { _addClassMixIns(_classAnnotations, _class, _primaryMixIn); } // first, annotations from the class itself: for (Annotation a : _class.getDeclaredAnnotations()) { if (_annotationIntrospector.isHandled(a)) { _classAnnotations.addIfNotPresent(a); } } // and then from super types for (Class<?> cls : _superTypes) { // and mix mix-in annotations in-between _addClassMixIns(_classAnnotations, cls); for (Annotation a : cls.getDeclaredAnnotations()) { if (_annotationIntrospector.isHandled(a)) { _classAnnotations.addIfNotPresent(a); } } } /* and finally... any annotations there might be for plain * old Object.class: separate because for all other purposes * it is just ignored (not included in super types) */ /* 12-Jul-2009, tatu: Should this be done for interfaces too? * For now, yes, seems useful for some cases, and not harmful * for any? */ _addClassMixIns(_classAnnotations, Object.class); }
/** * Method that will add annotations from specified source method to target method, but only if * target does not yet have them. */ protected void _addMixUnders(Method src, AnnotatedMethod target) { for (Annotation a : src.getDeclaredAnnotations()) { if (_annotationIntrospector.isHandled(a)) { target.addIfNotPresent(a); } } }
/** * Method that will collect all member (non-static) fields that are either public, or have at * least a single annotation associated with them. * * @param collectIgnored Whether to collect list of ignored methods for later retrieval */ public void resolveFields(boolean collectIgnored) { LinkedHashMap<String, AnnotatedField> foundFields = new LinkedHashMap<String, AnnotatedField>(); _addFields(foundFields, _class); /* And last but not least: let's remove all fields that are * deemed to be ignorable after all annotations have been * properly collapsed. */ Iterator<Map.Entry<String, AnnotatedField>> it = foundFields.entrySet().iterator(); while (it.hasNext()) { AnnotatedField f = it.next().getValue(); if (_annotationIntrospector.isIgnorableField(f)) { it.remove(); if (collectIgnored) { _ignoredFields = ArrayBuilders.addToList(_ignoredFields, f); } } else { } } if (foundFields.isEmpty()) { _fields = Collections.emptyList(); } else { _fields = new ArrayList<AnnotatedField>(foundFields.size()); _fields.addAll(foundFields.values()); } }
/** * Method for resolving member method information: aggregating all non-static methods and * combining annotations (to implement method-annotation inheritance) * * @param collectIgnored Whether to collect list of ignored methods for later retrieval */ public void resolveMemberMethods(MethodFilter methodFilter, boolean collectIgnored) { _memberMethods = new AnnotatedMethodMap(); AnnotatedMethodMap mixins = new AnnotatedMethodMap(); // first: methods from the class itself _addMemberMethods(_class, methodFilter, _memberMethods, _primaryMixIn, mixins); // and then augment these with annotations from super-types: for (Class<?> cls : _superTypes) { Class<?> mixin = (_mixInResolver == null) ? null : _mixInResolver.findMixInClassFor(cls); _addMemberMethods(cls, methodFilter, _memberMethods, mixin, mixins); } // Special case: mix-ins for Object.class? (to apply to ALL classes) if (_mixInResolver != null) { Class<?> mixin = _mixInResolver.findMixInClassFor(Object.class); if (mixin != null) { _addMethodMixIns(methodFilter, _memberMethods, mixin, mixins); } } /* Any unmatched mix-ins? Most likely error cases (not matching * any method); but there is one possible real use case: * exposing Object#hashCode (alas, Object#getClass can NOT be * exposed, see [JACKSON-140]) */ if (!mixins.isEmpty()) { Iterator<AnnotatedMethod> it = mixins.iterator(); while (it.hasNext()) { AnnotatedMethod mixIn = it.next(); try { Method m = Object.class.getDeclaredMethod(mixIn.getName(), mixIn.getParameterClasses()); if (m != null) { AnnotatedMethod am = _constructMethod(m); _addMixOvers(mixIn.getAnnotated(), am, false); _memberMethods.add(am); } } catch (Exception e) { } } } /* And last but not least: let's remove all methods that are * deemed to be ignorable after all annotations have been * properly collapsed. */ Iterator<AnnotatedMethod> it = _memberMethods.iterator(); while (it.hasNext()) { AnnotatedMethod am = it.next(); if (_annotationIntrospector.isIgnorableMethod(am)) { it.remove(); if (collectIgnored) { _ignoredMethods = ArrayBuilders.addToList(_ignoredMethods, am); } } } }
protected AnnotationMap _collectRelevantAnnotations(Annotation[] anns) { AnnotationMap annMap = new AnnotationMap(); if (anns != null) { for (Annotation a : anns) { if (_annotationIntrospector.isHandled(a)) { annMap.add(a); } } } return annMap; }
/** @param addParamAnnotations Whether parameter annotations are to be added as well */ protected void _addMixOvers(Method mixin, AnnotatedMethod target, boolean addParamAnnotations) { for (Annotation a : mixin.getDeclaredAnnotations()) { if (_annotationIntrospector.isHandled(a)) { target.addOrOverride(a); } } if (addParamAnnotations) { Annotation[][] pa = mixin.getParameterAnnotations(); for (int i = 0, len = pa.length; i < len; ++i) { for (Annotation a : pa[i]) { target.addOrOverrideParam(i, a); } } } }
/** * Method called to add field mix-ins from given mix-in class (and its fields) into already * collected actual fields (from introspected classes and their super-classes) */ protected void _addFieldMixIns(Class<?> mixin, Map<String, AnnotatedField> fields) { for (Field mixinField : mixin.getDeclaredFields()) { /* there are some dummy things (static, synthetic); better * ignore */ if (!_isIncludableField(mixinField)) { continue; } String name = mixinField.getName(); // anything to mask? (if not, quietly ignore) AnnotatedField maskedField = fields.get(name); if (maskedField != null) { for (Annotation a : mixinField.getDeclaredAnnotations()) { if (_annotationIntrospector.isHandled(a)) { maskedField.addOrOverride(a); } } } } }
/** * Initialization method that will find out all constructors and potential static factory methods * the class has. * * <p>Starting with 1.2, it will also apply mix-in annotations, as per [JACKSON-76] * * @param includeAll If true, includes all creator methods; if false, will only include the * no-arguments "default" constructor */ public void resolveCreators(boolean includeAll) { // Then see which constructors we have _constructors = null; for (Constructor<?> ctor : _class.getDeclaredConstructors()) { switch (ctor.getParameterTypes().length) { case 0: _defaultConstructor = _constructConstructor(ctor, true); break; default: if (includeAll) { if (_constructors == null) { _constructors = new ArrayList<AnnotatedConstructor>(); } _constructors.add(_constructConstructor(ctor, false)); } } } // and if need be, augment with mix-ins if (_primaryMixIn != null) { if (_defaultConstructor != null || _constructors != null) { _addConstructorMixIns(_primaryMixIn); } } /* And then... let's remove all constructors that are * deemed to be ignorable after all annotations have been * properly collapsed. */ if (_defaultConstructor != null) { if (_annotationIntrospector.isIgnorableConstructor(_defaultConstructor)) { _defaultConstructor = null; } } if (_constructors != null) { // count down to allow safe removal for (int i = _constructors.size(); --i >= 0; ) { if (_annotationIntrospector.isIgnorableConstructor(_constructors.get(i))) { _constructors.remove(i); } } } _creatorMethods = null; if (includeAll) { /* Then static methods which are potential factory * methods */ for (Method m : _class.getDeclaredMethods()) { if (!Modifier.isStatic(m.getModifiers())) { continue; } int argCount = m.getParameterTypes().length; // factory methods take at least one arg: if (argCount < 1) { continue; } if (_creatorMethods == null) { _creatorMethods = new ArrayList<AnnotatedMethod>(); } _creatorMethods.add(_constructCreatorMethod(m)); } // mix-ins to mix in? if (_primaryMixIn != null && _creatorMethods != null) { _addFactoryMixIns(_primaryMixIn); } // anything to ignore at this point? if (_creatorMethods != null) { // count down to allow safe removal for (int i = _creatorMethods.size(); --i >= 0; ) { if (_annotationIntrospector.isIgnorableMethod(_creatorMethods.get(i))) { _creatorMethods.remove(i); } } } } }