// TODO: Remove method parameter, which is unused protected SortedMap<Key<?>, Binding<?>> getPolymorphicAdapterMapBindings( final Class<?> adaptableType, final Method method, final AdapterMap methodAnnotation) { // find available keys final Map<Key<?>, Binding<?>> allBindings = injector.getAllBindings(); // IMPORTANT: use a sorted map, where keys are sorted according to // hierarchy of annotation types (so we have polymorphic injection) final SortedMap<Key<?>, Binding<?>> polymorphicBindings = new TreeMap<Key<?>, Binding<?>>( new Comparator<Key<?>>() { @Override public int compare(final Key<?> o1, final Key<?> o2) { if (!AdapterMap.class.equals(o1.getAnnotationType()) || !AdapterMap.class.equals(o2.getAnnotationType())) { throw new IllegalArgumentException( "Can only compare keys with AdapterMap annotations"); } final AdapterMap a1 = (AdapterMap) o1.getAnnotation(); final AdapterMap a2 = (AdapterMap) o2.getAnnotation(); if (a1.adaptableType().equals(a2.adaptableType())) { return 0; } else if (a1.adaptableType().isAssignableFrom(a2.adaptableType())) { return -1; } else { return 1; } } }); for (final Key<?> key : allBindings.keySet()) { if ((key.getAnnotationType() != null) && AdapterMap.class.equals(key.getAnnotationType())) { final AdapterMap keyAnnotation = (AdapterMap) key.getAnnotation(); // Guice will already have injected all bindings where the // adaptableType used in the method annotation is the same as // the one used in the key annotation. if (!methodAnnotation.adaptableType().equals(keyAnnotation.adaptableType()) /* * The annotation in the binding refers to a true * super-type of instance runtime type (check, because * if the type is the same, the default injector will * already inject the values) IMPORTANT: we use * 'adaptableType' instead of 'methodAnnotation * .adaptableType()' here, because the runtime type of * the to be injected IAdaptable is relevant */ && keyAnnotation.adaptableType().isAssignableFrom(adaptableType)) { // System.out.println("Applying binding for " + // keyAnnotation.value() + " to " + type + // " as subtype of " + methodAnnotation.value()); polymorphicBindings.put(key, allBindings.get(key)); } } } return polymorphicBindings; }
/** * Computes a canonical {@link Qualifier} annotation for the given binding {@link Key}. * * @param key The key to qualify * @return Qualifier for the key */ static final Annotation qualify(final Key<?> key) { if (key instanceof WildcardKey) { final Annotation qualifier = ((WildcardKey) key).getQualifier(); return null != qualifier ? qualifier : DEFAULT_QUALIFIER; } return null != key.getAnnotationType() ? key.getAnnotation() : DEFAULT_QUALIFIER; }
@Override final Annotation qualifies(final Key<?> requirement, final Binding<?> binding) { final Class<? extends Annotation> markerType = requirement.getAnnotationType(); final Annotation qualifier = qualify(binding.getKey()); if (markerType.isInstance(qualifier)) { return qualifier; } final Class<?> implementation = binding.acceptTargetVisitor(ImplementationVisitor.THIS); return null != implementation ? implementation.getAnnotation(markerType) : null; }
/** * Selects the appropriate qualifying strategy for the given requirement {@link Key}. * * @param key The requirement key * @return Qualifying strategy */ static final QualifyingStrategy selectFor(final Key<?> key) { final Class<?> qualifierType = key.getAnnotationType(); if (null == qualifierType) { return QualifyingStrategy.UNRESTRICTED; } if (Named.class == qualifierType) { return key.hasAttributes() ? QualifyingStrategy.NAMED_WITH_ATTRIBUTES : QualifyingStrategy.NAMED; } return key.hasAttributes() ? QualifyingStrategy.MARKED_WITH_ATTRIBUTES : QualifyingStrategy.MARKED; }