package com.github.czyzby.uedi.stereotype.impl; import java.lang.reflect.Member; import com.badlogic.gdx.utils.ObjectMap; import com.github.czyzby.kiwi.util.gdx.collection.GdxMaps; import com.github.czyzby.uedi.Context; import com.github.czyzby.uedi.stereotype.Provider; /** Allows to resolve ambiguous dependencies. * * @author MJ * * @param <Type> type of provided objects. */ public class ProviderManager<Type> implements Provider<Type> { private final ObjectMap<String, Provider<Type>> providers = GdxMaps.newObjectMap(); private final Class<Type> type; private final Context context; private Provider<Type> defaultProvider; /** @param type type of provided values. * @param context parent context. Used to resolve depedendencies. */ public ProviderManager(final Class<Type> type, final Context context) { this.type = type; this.context = context; } /** @param provider will be included in the providers collection. Must provide the same type of values. */ @SuppressWarnings("unchecked") public void addProvider(final Provider<?> provider) { providers.put(Providers.getName(provider), (Provider<Type>) provider); if (Providers.isDefault(provider)) { defaultProvider = (Provider<Type>) provider; } } @Override public Class<? extends Type> getType() { return type; } @Override public Type provide(final Object target, final Member member) { if (member != null) { final Provider<Type> provider = providers.get(Providers.getName(member)); if (provider != null) { return provider.provide(target, member); } } if (defaultProvider == null) { if (context.isFailIfAmbiguousDependency() || context.isFailIfUnknownType()) { throw new RuntimeException("Ambiguous dependency: '" + target + "' component requested '" + type.getName() + "' instance, found multiple providers and no default one."); } return context.create(type); } return defaultProvider.provide(target, member); } }