@SuppressWarnings({"unchecked", "rawtypes"})
    public static <T> Map<Key<T>, Class<? extends T>> resolveBindingDefinitions(Class<T> injecteeClass,
            Class<? extends T> firstImplClass, Class<? extends T>... restImplClasses) {
        Map<Key<T>, Class<? extends T>> typeLiterals = new HashMap<>();
        List<Class<? extends T>> subClasses = new ArrayList<>();

        if (firstImplClass != null) {
            subClasses.add(firstImplClass);
        }
        if (restImplClasses != null && restImplClasses.length > 0) {
            subClasses.addAll(Arrays.asList(restImplClasses));
        }

        for (Class<? extends T> subClass : subClasses) {
            if (isBindable(subClass)) {
                Type resolvedType = TypeToken.of(subClass).getSupertype((Class) injecteeClass).getType();
                TypeLiteral<T> parentTypeLiteral;
                if (resolvedType == null) {
                    parentTypeLiteral = TypeLiteral.get(injecteeClass);
                } else {
                    parentTypeLiteral = (TypeLiteral<T>) TypeLiteral.get(resolvedType);
                }

                Optional<Annotation> qualifier = Annotations.on(subClass)
                        .traversingSuperclasses()
                        .traversingInterfaces()
                        .findAll()
                        .filter(AnnotationPredicates.annotationAnnotatedWith(Qualifier.class, false))
                        .findFirst();
                Key<T> key = qualifier.map(annotation -> Key.get(parentTypeLiteral, annotation)).orElseGet(
                        () -> Key.get(parentTypeLiteral));
                if (typeLiterals.containsKey(key)) {
                    throw SeedException.createNew(CoreErrorCode.DUPLICATED_BINDING_KEY)
                            .put("duplicatedKey", key)
                            .put("firstClass", subClass.getName())
                            .put("secondClass", typeLiterals.get(key).getName());
                }
                typeLiterals.put(key, subClass);
            }
        }

        return typeLiterals;
    }
@ SuppressWarnings ( { "unchecked" , "rawtypes" } ) public static < T > Map < Key < T > , Class < ? extends T > > resolveBindingDefinitions ( Class < T > injecteeClass , Class < ? extends T > firstImplClass , Class < ? extends T > ... restImplClasses ) { Map < Key < T > , Class < ? extends T > > typeLiterals = new HashMap < > ( ) ; List < Class < ? extends T > > subClasses = new ArrayList < > ( ) ; if ( firstImplClass != null ) { subClasses . add ( firstImplClass ) ; } if ( restImplClasses != null && restImplClasses . length > 0 ) { subClasses . addAll ( Arrays . asList ( restImplClasses ) ) ; } for ( Class < ? extends T > subClass : subClasses ) { if ( isBindable ( subClass ) ) { Type resolvedType = TypeToken . of ( subClass ) . getSupertype ( ( Class ) injecteeClass ) . getType ( ) ; TypeLiteral < T > parentTypeLiteral ; if ( resolvedType == null ) { parentTypeLiteral = TypeLiteral . get ( injecteeClass ) ; } else { parentTypeLiteral = ( TypeLiteral < T > ) TypeLiteral . get ( resolvedType ) ; } Optional < Annotation > qualifier = Annotations . on ( subClass ) . traversingSuperclasses ( ) . traversingInterfaces ( ) . findAll ( ) . filter ( AnnotationPredicates . annotationAnnotatedWith ( Qualifier . class , false ) ) . findFirst ( ) ; Key < T > key = qualifier . map ( annotation -> Key . get ( parentTypeLiteral , annotation ) ) . orElseGet ( ( ) -> Key . get ( parentTypeLiteral ) ) ; if ( typeLiterals . containsKey ( key ) ) { throw SeedException . createNew ( CoreErrorCode . DUPLICATED_BINDING_KEY ) . put ( "duplicatedKey" , key ) . put ( "firstClass" , subClass . getName ( ) ) . put ( "secondClass" , typeLiterals . get ( key ) . getName ( ) ) ; } typeLiterals . put ( key , subClass ) ; } } return typeLiterals ; }
Construct a checked map of bindable key with the corresponding implementation class.
<p>
Given the following injectee class and implementation classes :
<pre>
interface Sort&lt;T&gt; {...}

{@literal @}Named("quick")
class StringQuickSort implements Sort&lt;String&gt; {...}

{@literal @}Named("bubble")
class BubbleSort implements Sort&lt;String&gt; {...}

class LongQuickSort implements Sort&lt;Long&gt; {...}
</pre>
The method will return a map with:
<pre>
Key[type=Sort&lt;String&gt;, annotation = Named[value = "quick"]] -&gt; StringQuickSort
Key[type=Sort&lt;String&gt;, annotation = Named[value = "bubble"]] -&gt; BubbleSort
Key[type=Sort&lt;Long&gt;] -&gt; LongQuickSort
</pre>
Possible injection patterns will be:
<pre>
{@literal @}Inject {@literal @}Name("quick")
Sort@lt;String&gt; stringQuickSort;

{@literal @}Inject {@literal @}Name("bubble")
Sort@lt;String&gt; bubbleSort;

{@literal @}Inject
Sort@lt;Long&gt; longQuickSort;
</pre>

@param injecteeClass   the parent class to reach
@param firstImplClass  the first class
@param restImplClasses the sub classes
@return a multimap with typeliterals for keys and a list of associated subclasses for values
@throws SeedException when duplicates keys are found.