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

io.datakernel.di.impl.BindingInitializer Maven / Gradle / Ivy

Go to download

DataKernel has an extremely lightweight DI with ground-breaking design principles. It supports nested scopes, singletons, object factories, modules and plugins which allow to transform graph of dependencies at startup time without any reflection.

The newest version!
package io.datakernel.di.impl;

import io.datakernel.di.core.Binding;
import io.datakernel.di.core.Dependency;

import java.util.Collection;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReferenceArray;
import java.util.stream.Collectors;

import static java.util.Arrays.asList;
import static java.util.Collections.emptySet;

/**
 * This is a {@link Binding} binding modifying function, that can add extra dependencies to it
 * and run initialization code for instance after it was created.
 */
public final class BindingInitializer {
	private static final BindingInitializer NOOP = new BindingInitializer<>(emptySet(),
			compiledBindings -> new CompiledBindingInitializer() {
				@Override
				public void initInstance(Object instance, AtomicReferenceArray[] instances, int synchronizedScope) {
					// noop
				}
			});

	private final Set dependencies;
	private final BindingInitializerCompiler compiler;

	private BindingInitializer(Set dependencies, BindingInitializerCompiler compiler) {
		this.dependencies = dependencies;
		this.compiler = compiler;
	}

	public Set getDependencies() {
		return dependencies;
	}

	public BindingInitializerCompiler getCompiler() {
		return compiler;
	}

	public static  BindingInitializer of(Set dependencies, BindingInitializerCompiler bindingInitializerCompiler) {
		return new BindingInitializer<>(dependencies, bindingInitializerCompiler);
	}

	@SafeVarargs
	public static  BindingInitializer combine(BindingInitializer... bindingInitializers) {
		return combine(asList(bindingInitializers));
	}

	@SuppressWarnings("unchecked")
	public static  BindingInitializer combine(Collection> bindingInitializers) {
		return new BindingInitializer<>(bindingInitializers.stream().map(BindingInitializer::getDependencies).flatMap(Collection::stream).collect(Collectors.toSet()),
				compiledBindings -> {
					CompiledBindingInitializer[] initializers = bindingInitializers.stream()
							.filter(bindingInitializer -> bindingInitializer != NOOP)
							.map(bindingInitializer -> bindingInitializer.compiler.compile(compiledBindings))
							.toArray(CompiledBindingInitializer[]::new);
					if (initializers.length == 0) return new CompiledBindingInitializer() {
						@Override
						public void initInstance(T instance, AtomicReferenceArray[] instances, int synchronizedScope) {
							// noop
						}
					};
					if (initializers.length == 1) return initializers[0];
					if (initializers.length == 2) {
						CompiledBindingInitializer initializer0 = initializers[0];
						CompiledBindingInitializer initializer1 = initializers[1];
						return new CompiledBindingInitializer() {
							@Override
							public void initInstance(T instance, AtomicReferenceArray[] instances, int synchronizedScope) {
								initializer0.initInstance(instance, instances, synchronizedScope);
								initializer1.initInstance(instance, instances, synchronizedScope);
							}
						};
					}
					return new CompiledBindingInitializer() {
						@Override
						public void initInstance(T instance, AtomicReferenceArray[] instances, int synchronizedScope) {
							for (CompiledBindingInitializer initializer : initializers) {
								initializer.initInstance(instance, instances, synchronizedScope);
							}
						}
					};
				});
	}

	@SuppressWarnings("unchecked")
	public static  BindingInitializer noop() {
		return (BindingInitializer) NOOP;
	}
}