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

io.datakernel.di.module.ModuleBuilder Maven / Gradle / Ivy

package io.datakernel.di.module;

import io.datakernel.di.annotation.ProvidesIntoSet;
import io.datakernel.di.core.*;
import io.datakernel.di.util.Types;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.lang.annotation.Annotation;
import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
import java.util.Set;

/**
 * This interface is used to restrict the DSL.
 * Basically, it disallows any methods from {@link ModuleBuilderBinder} not listed below
 * to be called without previously calling {@link #bind bind(...)}.
 */
@SuppressWarnings("UnusedReturnValue")
public interface ModuleBuilder extends Module {
	/**
	 * Adds all bindings, transformers, generators and multibinders from given modules to this one.
	 * 

* This works just as if you'd define all of those directly in this module. */ ModuleBuilder install(Collection modules); /** * @see #install(Collection) */ default ModuleBuilder install(Module... modules) { return install(Arrays.asList(modules)); } /** * Scans class hierarchy and then installs providers from each class as modules, * so that exports do not interfere between classes. * Class parameter is used to specify from which class in the hierarchy to start. */ ModuleBuilder scan(@NotNull Class containerClass, @Nullable Object container); /** * Same as {@link #scan}, with staring class defaulting to the class of the object instance. */ default ModuleBuilder scan(Object container) { return scan(container.getClass(), container); } /** * Same as {@link #scan}, but scans only static methods and does not depend on instance of the class. * Non-static annotated methods are {@link IllegalStateException prohibited}. */ default ModuleBuilder scan(Class container) { return scan(container, null); } /** * @see #bind(Key) */ default ModuleBuilderBinder bind(Class cls) { return bind(Key.of(cls)); } /** * @see #bind(Key) */ default ModuleBuilderBinder bind(Class cls, Name name) { return bind(Key.of(cls, name)); } /** * @see #bind(Key) */ default ModuleBuilderBinder bind(Class cls, String name) { return bind(Key.of(cls, name)); } /** * @see #bind(Key) */ default ModuleBuilderBinder bind(Class cls, Class annotationType) { return bind(Key.of(cls, annotationType)); } /** * This method begins a chain of binding builder DSL calls. *

* You can use generics in it, only those that are defined at the module class. * And you need to subclass the module at the usage point to 'bake' those generics * into subclass bytecode so that they could be fetched by this bind call. */ ModuleBuilderBinder bind(@NotNull Key key); default ModuleBuilder bindInstanceProvider(Class type) { return bindInstanceProvider(Key.of(type)); } default ModuleBuilder bindInstanceProvider(Key key) { return bind(Key.ofType(Types.parameterized(InstanceProvider.class, key.getType()), key.getName())); } default ModuleBuilder bindInstanceFactory(Class type) { return bindInstanceFactory(Key.of(type)); } default ModuleBuilder bindInstanceFactory(Key key) { return bind(Key.ofType(Types.parameterized(InstanceFactory.class, key.getType()), key.getName())); } default ModuleBuilder bindInstanceInjector(Class type) { return bindInstanceInjector(Key.of(type)); } default ModuleBuilder bindInstanceInjector(Key key) { return bind(Key.ofType(Types.parameterized(InstanceInjector.class, key.getType()), key.getName())); } /** * This is a helper method that provides a functionality similar to {@link ProvidesIntoSet}. * It binds given binding as a singleton set to a set key made from given key * and also {@link Multibinder#toSet multibinds} each of such sets together. */ ModuleBuilder bindIntoSet(Key setOf, Binding binding); /** * @see #bindIntoSet(Key, Binding) * @see Binding#to(Key) */ default ModuleBuilder bindIntoSet(Key setOf, Key item) { return bindIntoSet(setOf, Binding.to(item)); } /** * @see #postInjectInto(Key) */ default ModuleBuilder postInjectInto(Class type) { return postInjectInto(Key.of(type)); } /** * {@link #bindIntoSet(Key, Key) Binds into set} a key of instance injector for given type at a {@link Injector#postInjectInstances special} * key Set<InstanceInjector<?>>. *

* Instance injector bindings are {@link DefaultModule generated automatically}. * * @see Injector#postInjectInstances */ default ModuleBuilder postInjectInto(Key key) { Key> instanceInjectorKey = Key.ofType(Types.parameterized(InstanceInjector.class, key.getType()), key.getName()); bind(instanceInjectorKey); // so that its location is set to this module return bindIntoSet(new Key>() {}, instanceInjectorKey); } /** * Adds a {@link BindingTransformer transformer} with a given priority to this module. */ ModuleBuilder transform(int priority, BindingTransformer bindingTransformer); /** * Adds a {@link BindingGenerator generator} for a given class to this module. */ ModuleBuilder generate(Class pattern, BindingGenerator bindingGenerator); /** * Adds a {@link Multibinder multibinder} for a given key to this module. */ ModuleBuilder multibind(Key key, Multibinder multibinder); default ModuleBuilder multibindToSet(Class type) { return multibindToSet(Key.of(type)); } default ModuleBuilder multibindToSet(Class type, String name) { return multibindToSet(Key.of(type, name)); } default ModuleBuilder multibindToSet(Class type, Name name) { return multibindToSet(Key.of(type, name)); } default ModuleBuilder multibindToSet(Key key) { return multibind(Key.ofType(Types.parameterized(Set.class, key.getType()), key.getName()), Multibinder.toSet()); } default ModuleBuilder multibindToMap(Class keyType, Class valueType) { return multibindToMap(keyType, valueType, (Name) null); } default ModuleBuilder multibindToMap(Class keyType, Class valueType, String name) { return multibindToMap(keyType, valueType, Name.of(name)); } default ModuleBuilder multibindToMap(Class keyType, Class valueType, Name name) { return multibind(Key.ofType(Types.parameterized(Map.class, keyType, valueType), name), Multibinder.toMap()); } }