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 extends Annotation> 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());
}
}