/** * 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); } } } }
/** * Method that can be called to find if introspected class declares a static "valueOf" factory * method that returns an instance of introspected type, given one of acceptable types. * * @param expArgTypes Types that the matching single argument factory method can take: will also * accept super types of these types (ie. arg just has to be assignable from expArgType) */ public Method findFactoryMethod(Class<?>... expArgTypes) { // So, of all single-arg static methods: for (AnnotatedMethod am : _classInfo.getStaticMethods()) { if (isFactoryMethod(am)) { // And must take one of expected arg types (or supertype) Class<?> actualArgType = am.getParameterClass(0); for (Class<?> expArgType : expArgTypes) { // And one that matches what we would pass in if (actualArgType.isAssignableFrom(expArgType)) { return am.getAnnotated(); } } } } return null; }
protected void _addMemberMethods( Class<?> cls, MethodFilter methodFilter, AnnotatedMethodMap methods, Class<?> mixInCls, AnnotatedMethodMap mixIns) { // first, mixIns, since they have higher priority then class methods if (mixInCls != null) { _addMethodMixIns(methodFilter, methods, mixInCls, mixIns); } if (cls == null) { // just so caller need not check when passing super-class return; } // then methods from the class itself for (Method m : cls.getDeclaredMethods()) { if (!_isIncludableMethod(m, methodFilter)) { continue; } AnnotatedMethod old = methods.find(m); if (old == null) { AnnotatedMethod newM = _constructMethod(m); methods.add(newM); // Ok, but is there a mix-in to connect now? old = mixIns.remove(m); if (old != null) { _addMixOvers(old.getAnnotated(), newM, false); } } else { /* If sub-class already has the method, we only want to augment * annotations with entries that are not masked by sub-class. */ _addMixUnders(m, old); /* 06-Jan-2010, tatu: [JACKSON-450] Except that if method we saw first is * from an interface, and we now find a non-interface definition, we should * use this method, but with combination of annotations. * This helps (or rather, is essential) with JAXB annotations and * may also result in faster method calls (interface calls are slightly * costlier than regular method calls) */ if (old.getDeclaringClass().isInterface() && !m.getDeclaringClass().isInterface()) { methods.add(old.withMethod(m)); } } } }