All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ch.jalu.injector.handlers.provider.ProviderHandlerImpl Maven / Gradle / Ivy

There is a newer version: 1.0
Show newest version
package ch.jalu.injector.handlers.provider;

import ch.jalu.injector.Injector;
import ch.jalu.injector.exceptions.InjectorException;
import ch.jalu.injector.handlers.dependency.DependencyHandler;
import ch.jalu.injector.handlers.instantiation.DependencyDescription;
import ch.jalu.injector.handlers.instantiation.Instantiation;
import ch.jalu.injector.handlers.instantiation.InstantiationProvider;
import ch.jalu.injector.utils.ReflectionUtils;

import javax.inject.Provider;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static ch.jalu.injector.utils.InjectorUtils.checkArgument;

/**
 * Default handler for {@link Provider} objects. Registers providers and classes and creates
 * {@link Instantiation} objects for classes it can handle.
 */
public class ProviderHandlerImpl implements ProviderHandler, InstantiationProvider, DependencyHandler {

    protected Map, ProviderWrappedInstantiation> providers = new HashMap<>();

    @Override
    public  void onProvider(Class clazz, Provider provider) {
        checkArgument(!providers.containsKey(clazz), "Provider already registered for " + clazz);
        providers.put(clazz, new ProviderInstantiation<>(provider));
    }

    @Override
    public > void onProviderClass(Class clazz, Class

providerClass) { checkArgument(!providers.containsKey(clazz), "Provider already registered for " + clazz); providers.put(clazz, new UninitializedProviderInstantiation<>(clazz, providerClass)); } @Override @SuppressWarnings("unchecked") public Instantiation get(Class clazz) { return (Instantiation) providers.get(clazz); } @Override public Object resolveValue(Injector injector, DependencyDescription dependencyDescription) { if (dependencyDescription.getType() == Provider.class) { Class genericType = ReflectionUtils.getGenericType(dependencyDescription.getGenericType()); if (genericType == null) { throw new InjectorException("Injection of a provider was requested but no generic type was given"); } ProviderWrappedInstantiation instantiation = providers.get(genericType); if (instantiation != null) { return instantiation.getProvider(injector); } return constructStandardProvider(genericType, injector); } return null; } private static Provider constructStandardProvider(final Class genericType, final Injector injector) { return new Provider() { @Override public T get() { return injector.newInstance(genericType); } }; } private void saveConstructedProvider(Class clazz, Provider provider) { providers.put(clazz, new ProviderInstantiation<>(provider)); } private interface ProviderWrappedInstantiation extends Instantiation { Provider getProvider(Injector injector); } /** * Simple instantiation that creates an object with the known provider. * * @param the type of the class to create */ private static final class ProviderInstantiation implements ProviderWrappedInstantiation { private final Provider provider; ProviderInstantiation(Provider provider) { this.provider = provider; } @Override public List getDependencies() { return Collections.emptyList(); } @Override public T instantiateWith(Object... values) { return provider.get(); } @Override public Provider getProvider(Injector injector) { return provider; } } /** * Instantiation that internally creates the required provider first. This is triggered by * declaring the provider class as a dependency, making the injector create the provider * class first. * * @param the type of the class to create */ private final class UninitializedProviderInstantiation implements ProviderWrappedInstantiation { private final Class clazz; private final Class> providerClass; UninitializedProviderInstantiation(Class clazz, Class> providerClass) { this.providerClass = providerClass; this.clazz = clazz; } @Override public List getDependencies() { return Collections.singletonList( new DependencyDescription(providerClass, clazz)); } @Override public T instantiateWith(Object... values) { if (values.length == 1 && values[0] instanceof Provider) { @SuppressWarnings("unchecked") Provider provider = (Provider) values[0]; T object = provider.get(); // The injector passed us the provider, so save it in the map for future uses saveConstructedProvider(clazz, provider); return object; } throw new InjectorException("Provider is required as argument"); } @Override public Provider getProvider(Injector injector) { Provider provider = injector.getSingleton(providerClass); saveConstructedProvider(clazz, provider); return provider; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy