private static void addMethods ( Set < MethodEntry > methods , Class < ? > clazz , Map < String , Class < ? > > types , Class < ? > parent , Method method ) { // validate interface //if (!clazz.isInterface()) { // throw new IllegalStateException("class must be interface: " + clazz); //} // check if the method requires a bridge and add generic method // with overridden type params MethodEntry impl = null ; boolean bridged = isBridgeRequired ( types , method ) ; // do not add method if already implemented // ignore if method already defined on the parent if ( ! bridged && parent != null && findMethod ( parent , method ) != null ) { return ; } // bridge if necessary if ( bridged ) { // get the underying generic type if provided Class < ? > returnType = getMethodType ( types , method . getGenericReturnType ( ) , method . getReturnType ( ) ) ; // get the underlying generic params if provided Type [ ] paramTypes = method . getGenericParameterTypes ( ) ; Class < ? > [ ] paramClasses = method . getParameterTypes ( ) ; for ( int i = 0 ; i < paramClasses . length ; i ++ ) { paramClasses [ i ] = getMethodType ( types , paramTypes [ i ] , paramClasses [ i ] ) ; } // check if only return type is overridden and only add impl // if not yet defined...this is possible since return type is // not part of a method signature for equality purposes so we // only need to implement in a concrete implementation once and // bridge all other methods. Parameters, on the other hand // must always be explicitly implemented to satisfy their // interface definition. MethodEntry bridgeMethod = null ; if ( Arrays . equals ( paramClasses , method . getParameterTypes ( ) ) ) { for ( MethodEntry mentry : methods ) { if ( mentry . getName ( ) . equals ( method . getName ( ) ) && Arrays . equals ( mentry . getParamTypes ( ) , method . getParameterTypes ( ) ) ) { bridgeMethod = mentry ; } } } // add implementation impl = new MethodEntry ( method . getName ( ) , returnType , paramClasses , bridgeMethod ) ; addMethod ( methods , impl ) ; } // add actual method definition, bridging if implemented above addMethod ( methods , new MethodEntry ( method . getName ( ) , method . getReturnType ( ) , method . getParameterTypes ( ) , impl ) ) ; // recursively add each super interface providing type info if valid addParentMethods ( methods , clazz , types , parent , method ) ; }
Recursive method that adds all applicable methods related to the given class which is expected to be an interface . The tree is walked for the class and all super interfaces in recursive fashion to get each available method that matches the provided method . Any method that is already defined by the given parent will be ignored . Otherwise the method including any required bridged methods will be added . The specified list of types define the optional type parameters of the given interface class . These types will propogate up the tree as necessary for any super - interfaces that match .